Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your help!

We need 7 developers from Canada and 18 more from Australia to help us complete a research survey.

Support our site by taking a quick sponsored survey and win a chance at a $50 Amazon gift card. Click here to get started!


Member Since 05 Oct 2011
Offline Last Active Jul 28 2015 09:38 AM

Topics I've Started

Can't get simple Tesselation Shaders to execute

18 April 2015 - 04:19 PM

Hello all!


I closely followed the following tutorial for basic OpenGL tesselation:




I am using it in a slightly different context with Deferred Rendering.


All I did was added a simple tesselation control shader to completely unalter the triangle patches:




Tesselation Control Shadee:

#version 420                                                                               
// define the number of CPs in the output patch                                                 
layout (vertices = 3) out;                                                                      
uniform vec3 gEyeWorldPos;                                                                      
// attributes of the input CPs                                                                  
  in vec3 WorldPos_CS_in[];                                                                       
  in vec2 TexCoord_CS_in[];                                                                       
  in vec3 Normal_CS_in  [];
  in vec3 Tangent_CS_in [];
// attributes of the output CPs                                                                 
 out vec3 WorldPos_ES_in[];                                                                      
 out vec2 TexCoord_ES_in[];                                                                      
 out vec3 Normal_ES_in[];                                                                        
 out vec3 Tangent_ES_in[];     
float GetTessLevel(float Distance0, float Distance1)                                            
    float AvgDistance = (Distance0 + Distance1) / 2.0;                                          
    if (AvgDistance <= 2.0) {                                                                   
        return 10.0;                                                                            
    else if (AvgDistance <= 5.0) {                                                              
        return 7.0;                                                                             
    else {                                                                                      
        return 3.0;                                                                             
void main()                                                                                     
    // Set the control points of the output patch                                               
    TexCoord_ES_in[gl_InvocationID] = TexCoord_CS_in[gl_InvocationID];                          
    Normal_ES_in[gl_InvocationID] = Normal_CS_in[gl_InvocationID];  
    Tangent_ES_in[gl_InvocationID] = Tangent_CS_in[gl_InvocationID];                          
    WorldPos_ES_in[gl_InvocationID] = WorldPos_CS_in[gl_InvocationID];                          
    // Calculate the distance from the camera to the three control points                       
    float EyeToVertexDistance0 = distance(gEyeWorldPos, WorldPos_ES_in[0]);                     
    float EyeToVertexDistance1 = distance(gEyeWorldPos, WorldPos_ES_in[1]);                     
    float EyeToVertexDistance2 = distance(gEyeWorldPos, WorldPos_ES_in[2]);                     
    // Calculate the tessellation levels                                                        
    gl_TessLevelOuter[0] = GetTessLevel(EyeToVertexDistance1, EyeToVertexDistance2);            
    gl_TessLevelOuter[1] = GetTessLevel(EyeToVertexDistance2, EyeToVertexDistance0);            
    gl_TessLevelOuter[2] = GetTessLevel(EyeToVertexDistance0, EyeToVertexDistance1);            
    gl_TessLevelInner[0] = gl_TessLevelOuter[2];                                                

And a simple Tesselation Evaluation Shader (this will ultimately sample from a Displacement Map, but at the moment I have the displacement commented out)

#version 420                                                                                 
layout(triangles, equal_spacing, ccw) in;                                                       
uniform mat4 gVP;                                                                               
uniform sampler2D gDisplacementMap;                                                             
uniform float gDispFactor;                                                                      
  in vec3 WorldPos_ES_in[];                                                                       
  in vec2 TexCoord_ES_in[];                                                                       
  in vec3 Normal_ES_in[]; 
  in vec3 Tangent_ES_in[];  
  out vec3 WorldPos_FS_in;                                                                        
  out vec2 TexCoord_FS_in;                                                                        
  out vec3 Normal_FS_in;                                                                          
  out vec3 Tangent_FS_in;
vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2)                                                   
    return vec2(gl_TessCoord.x) * v0 + vec2(gl_TessCoord.y) * v1 + vec2(gl_TessCoord.z) * v2;   
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2)                                                   
    return vec3(gl_TessCoord.x) * v0 + vec3(gl_TessCoord.y) * v1 + vec3(gl_TessCoord.z) * v2;   
void main()                                                                                     
    // Interpolate the attributes of the output vertex using the barycentric coordinates        
    TexCoord_FS_in = interpolate2D(TexCoord_ES_in[0], TexCoord_ES_in[1], TexCoord_ES_in[2]);    
    Normal_FS_in = interpolate3D(Normal_ES_in[0], Normal_ES_in[1], Normal_ES_in[2]);            
    Normal_FS_in = normalize(Normal_FS_in);
	Tangent_FS_in = interpolate3D(Tangent_ES_in[0], Tangent_ES_in[1], Tangent_ES_in[2]);            
    Tangent_FS_in = normalize(Tangent_FS_in);
    WorldPos_FS_in = interpolate3D(WorldPos_ES_in[0], WorldPos_ES_in[1], WorldPos_ES_in[2]);    
    // Displace the vertex along the normal                                                     
    //float Displacement = texture(gDisplacementMap, TexCoord_FS_in.xy).x;                        
    //WorldPos_FS_in += Normal_FS_in * Displacement * gDispFactor;                                
    gl_Position = gVP * vec4(WorldPos_FS_in, 1.0);                                              

I am using NVidia NSight. If I do not attach the Control and Evaluation Shaders, the shader executes just fine. I can put breakpoints on my vertex and fragment shader in NSight, and the shaders are executing and I'm seeing what I'd expect on screen.


If I do attach the tesselation shaders, I see nothing on screen and putting breakpoints on the Vertex or Fragment shader doesn't work, indicating that they are not executing at all.


NSight requires that you are running OpenGL 4.x to run the shader debugger, so my OpenGL version should be fine. I remembered to call: glPatchParameteri(GL_PATCH_VERTICES, 3); and I checked my GL_MAX_PATCH_VERTICES and the value is 32.


I read that I may need to use GL_PATCHES as my primitive type, so I am using this in my draw call:

      glDrawElementsBaseVertex(GL_PATCHES, numIndices,
                                  (void*)(sizeof(unsigned int) * mesh->m_index_offset), 

 still the Shader refuses to execute.


Kind of at my wits end here. :\ does anyone have any ideas?




How many dedicated Shaders to use?

06 December 2014 - 01:12 PM

So I've read its best to write dedicated shaders for specific purposes rather than bloat them with too many conditionals. And it makes sense. But I look at how many options are possible and it quickly becomes overwhelming:


1. Normal mapping

2. GPU Tesselation / Displacement mapping

3. Shadow mapping

4. Animation/Skinning


I could go with or without the each of these for any particular shader, resulting in 16 possible shaders. When you consider I have to write shaders for shadow passes for different types of lights (point, spot, directional, etc). the number of shaders quickly becomes ridiculous.


What's a smart way to cluster these and keep it reasonable?



Trouble reading from depth-texture

28 July 2013 - 09:46 PM

In my last post I stated that I was having trouble with rendering to a depth texture. But I believe the following has demonstrated that the render to texture is successful and the issue is I can't read from the texture after the rendering is complete. 


I used glReadPixels to check if my depth texture is being cleared. I used the following after calling glClear:
glBindFramebuffer(GL_READ_FRAMEBUFFER,  m_fbo);
float depth;
glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
printf("depth value is %f",depth);
The print message outputs whatever clear depth I've set before calling glClear (with the fbo bound as the draw buffer), so I at least now know that the depth texture IS being written to. The problem is I just can't get my shaders to read from it! Here is where the texture is sampled:

float mapSample = (texture( gCascadedShadowMap, TexCoord).x);
FragColor =   vec4(mapSample,mapSample,mapSample,1);

I am well aware of the usual faintness of the depth-texture rendering, that's why I'm using glClear() with a depth value of around 0.5. I should be seeing a mid-gray screen when I render, but instead I just see blackness. If I set other textures to gCascadedShadowMap, however, it draws the texture to the screen correctly.
Any help or ideas would be greatly appreciated!

FBO - Render to texture not working

20 July 2013 - 05:35 PM

I am trying to implement cascaded shadow maps but I am having a strange issue with my FBO. As far as I can tell I am completely unable to write to the attached depth-texture. Even using glClear(GL_DEPTH_BUFFER_BIT) and trying various different clear values, I am unable to see any changes in the texture when I render it to the screen.


Here's a peek at some of my code:

bool CascadedShadowMap::Initialize(unsigned int WindowWidth, unsigned int WindowHeight)
m_width = WindowWidth;
m_height= WindowHeight;
    // Create the FBO
    glGenFramebuffers(1, &m_fbo);
    // Create the depth buffer
    glGenTextures(1, &m_shadowMap);
    glBindTexture(GL_TEXTURE_2D, m_shadowMap);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 2 * WindowWidth, 2 * WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadowMap, 0);
    // Disable writes to the color buffer
    GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (Status != GL_FRAMEBUFFER_COMPLETE) {
        vDebugOut("error initializing shadow map! -CasadedShadowMap.cpp");
return false;
    return true;

The debug message is not printed so I know the frame buffer is complete. I also made sure the function is being called.


Here's where the texture should be cleared:

void vGraphics::fillShadowTextureDirectionalCascadedMap()
// Rendering models commented out for now. Trying to get Clear() to work.


The methods "BindForReading" and "Clear" shown above are implemented like so:

void CascadedShadowMap::BindForWriting()
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
void CascadedShadowMap::Clear()
glViewport(0, 0, 2* m_width, 2 * m_height);

As you can see I'm setting a lot of options to try to make absolutely certain that nothing will prevent the GBuffer from getting cleared. 
Now, just before my light pass, have:


Here's the code for the two functions above.

void vDirectionalLightShader::setCascadedShadowUnit(GLuint textureUnit)
glUniform1i(m_unif_casc_shadow_map_id, textureUnit);
void  CascadedShadowMap::BindForReading(GLenum TextureUnit)
    glBindTexture(GL_TEXTURE_2D, m_shadowMap);

Now at the end of my fragment shader in my light pass (or "texture render pass" if you will):

float mapSample = (texture(gCascadedShadowMap, TexCoord).x);
FragColor =   vec4(mapSample,mapSample,mapSample,1);
Its worth noting that if I say:
cascaded_shadow_map->BindForReading(0); then the texture bound to texture unit 0 (I think its the Position map on my deferred rendering set up) displays perfectly fine. But using the texture unit that the texture CascadedShadowMap::m_shadowMap is bound to, produces a pure black screen, regardless of what I set the depth clear color to in CascadedShadowMap::Clear().
Any ideas would be most appreciated. Thanks!

Stencil shadow volumes - a thing of the past?

08 June 2013 - 05:16 PM

After realizing the benefits of stencil shadow volumes for handling point-light shadows, I have been determined to add them to my own graphics engine. Days have turned into weeks and weeks into months. I can easily cast beautiful, clean shadows behind an occluder; but the self shadowing always suffers from ugly artifacts. 


I thought I'd found my solution to cast smooth silhouette edges here, but issues involving z-fighting and the per-polygon nature of these calculations always ensure self-shadowing issues crop up. Countless tweaks and special case handling haven't gotten me out of the woods.


Even if I can get this working, I have more concerns. How well will GPU tessellation and displacement mapping work with stencil shadow volumes? Can I realistically expect to get the smoothness of shadow maps with these per-polygon calculations?


Moreover, all the literature I find on stencil shadow volumes seems to be at least 6 years old.. and it has me wondering are they just not practical anymore?


The only possibility I can see is if you used a hybrid: shadow-maps to handle self shadowing, and projected stencil shadow volumes elsewhere. But I wonder if you might as well go for all-shadow maps in that case.


If there are any proponents of stencil shadow volumes here, I'd love to know how you handle these concerns because if I switch to only shadow maps, I'll have to throw away a lot of work! :(