Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: Tessellation Shader - No Output

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    5

    Tessellation Shader - No Output

    I have been battling this for hours. Scoured the internet and past forums posts but nothing I have found or tried has helped so far. I am just trying to get a very minimal working example of a tessellation shader running, but am having no luck.

    I am in OpenGL 4.5 on Windows, C++ in VS. I use SFML, GLEW and GLM libraries.

    I have no GL errors, no shader compile errors, no shader linker errors in my log. If I swap the shader (game.GL.shaderTess) for just a standard one with only vertex and fragment and change GL_PATCHES to GL_TRIANGLES it works as expected.

    I imagine there is probably some simple mistake in there somewhere but I can figure out what it is for the life of me.

    Draw Code
    Code :
    glUseProgram(game.GL.shaderTess);
    glUniformMatrix4fv(game.GL.unifModelViewMatrixQuad, 1, GL_FALSE, glm::value_ptr(modelViewMatrix));
    glBindVertexArray(game.GL.quadVertexArray);
    glBindBuffer(GL_ARRAY_BUFFER, game.GL.quadPositionBuffer);
     
    glBufferSubData(GL_ARRAY_BUFFER, 0, game.GL.SIZE_OF_QUAD_VERTEX_ARRAY, game.GL.quadVertices);
    glBufferSubData(GL_ARRAY_BUFFER, game.GL.SIZE_OF_QUAD_VERTEX_ARRAY, game.GL.SIZE_OF_QUAD_VERTEX_ARRAY, game.GL.quadColor);
     
    glPatchParameteri(GL_PATCH_VERTICES, 3);
    glDrawArrays(GL_PATCHES, 0, game.GL.NUMBER_OF_QUAD_VERTEX_COORDINATES);

    Vertex Shader
    Code :
    #version 430 core
     
    in vec3 position;
    in vec3 color;
    out vec3 colorFS; 
    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;
     
    void main()
    {
    	gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0f);
    	colorFS = color;
    }

    Tessellation Control Shader
    Code :
    #version 430 core
     
    layout (vertices = 3) out;
     
    void main() 
    {
    	gl_TessLevelInner[0] = 3.0;
    	gl_TessLevelOuter[0] = 3.0;
    	gl_TessLevelOuter[1] = 3.0;
    	gl_TessLevelOuter[2] = 3.0;
    	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    }

    Tessellation Evaluation Shader
    Code :
    #version 430 core
     
    layout (triangles, equal_spacing, cw) in;
     
    void main()
    {
    	gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
    }

    Fragment Shader
    Code :
    #version 430
     
    in vec3 colorFS;
    out vec4 FragColor;
     
    void main()
    {
     
    	FragColor = vec4(1.0,1.0,1.0,1.0);
    }

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,002
    Quote Originally Posted by Acumen View Post
    Tessellation Evaluation Shader
    Code :
    #version 430 core
     
    layout (triangles, equal_spacing, cw) in;
     
    void main()
    {
    	gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
    }
    Note that this will flip the ordering relative to GL_TRIANGLES. This may be an issue if GL_CULL_FACE is enabled. Try changing "cw" to "ccw".

    Also: many tessellation techniques require the transformations (or at least the projection transformation) to be applied after tessellation.

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    5
    I can verify that culling is not on with the other shaders that do render. I did try it anyway but no dice.

    Wouldn't this shader be applying the tessellation to already transformed vertices so not need additional transformation? I tried moving the transformation from the vertex shader to the tessellation evaluation shader but nothing changed then either.

    I am going to verify all the inputs going to the draw call, probably should have done that earlier but it worked fine with the standard shader so didn't think too. Out of ideas though.

    Edit: Verified the data going in to the draw call looks correct:

    Code :
    game.GL.NUMBER_OF_QUAD_VERTEX_COORDINATES: 18
    Size of GLFloat: 4
    game.GL.SIZE_OF_QUAD_VERTEX_ARRAY: 72
     
    game.GL.quadVertices:
     
    0: (0.200000,0.600000,0.000000)
    3: (0.100000,0.600000,0.000000)
    6: (0.200000,0.700000,0.000000)
     
    9: (0.200000,0.700000,0.000000)
    12: (0.100000,0.600000,0.000000)
    15: (0.100000,0.700000,0.000000)

    Just for clarification I use the word quad in my variables, but for everything GL related it is a regular list of triangles, I only use it internally in quad form.
    Last edited by Acumen; 12-13-2017 at 10:57 AM.

  4. #4
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    5
    OK I fixed it, not sure why the code above wasn't working since it seemed to work for the tutorials that wrote it. Can someone maybe shed light?

    What I am pretty sure it ended up being is the shader compiler was optimizing out
    Code :
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0f);
    from the vertex shader, due to
    Code :
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
    being set in the tessellation evaluation shader? Even though it relied on the value already being in gl_position when I set it in the vertex shader? Does that sound right?

    My first problem was I was still binding the attributes back the original non tessellated shader after I bound them to the tessellated shader as mentally I was still modifying it, but had switched to A/B when I started having problems. That led to me reading the errors from the old attributes which were clean instead of the new ones, so once I figured that out I found an error in the bind. The attribute was coming back as not found, but since it was in my code, it means it was optimized out. I instead passed the position variable down the pipeline so that I was only writing gl_position once and it started working no problem.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,002
    Quote Originally Posted by Acumen View Post
    What I am pretty sure it ended up being is the shader compiler was optimizing out
    Code :
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0f);
    from the vertex shader, due to
    Code :
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
    being set in the tessellation evaluation shader? Even though it relied on the value already being in gl_position when I set it in the vertex shader? Does that sound right?
    If that's happening, it's a bug in the implementation. If a tessellation evaluation shader is present, it's supposed to set gl_Position, and there wouldn't be any point in having gl_Position in gl_in[] if it couldn't be used.

    Quote Originally Posted by Acumen View Post
    My first problem was I was still binding the attributes back the original non tessellated shader after I bound them to the tessellated shader as mentally I was still modifying it, but had switched to A/B when I started having problems. That led to me reading the errors from the old attributes which were clean instead of the new ones, so once I figured that out I found an error in the bind. The attribute was coming back as not found, but since it was in my code, it means it was optimized out. I instead passed the position variable down the pipeline so that I was only writing gl_position once and it started working no problem.
    A common problem when using geometry or tessellation shaders is forgetting that variables don't automatically get "passed through" from the vertex shader to the fragment shader. The intermediate shaders have to explicitly copy inputs to outputs. Also, as you can't use the same name for both input and output variables, you need to either have the fragment shader use different names depending upon whether there's a geometry/tessellation shader present, or use interface blocks, or use location-based binding.

  6. #6
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    5
    Quote Originally Posted by GClements View Post
    A common problem when using geometry or tessellation shaders is forgetting that variables don't automatically get "passed through"
    Ah! OK thanks I found it. I was missing
    Code :
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    in the tessellation control shader. I had assumed once gl_Position was set that it was a special case in memory so I didn't need to pass it through. Seems like the kind of thing that could easily be. I guess maybe there are ways to take advantage of the fact that it doesn't work that way?

  7. #7
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,002
    Quote Originally Posted by Acumen View Post
    Ah! OK thanks I found it. I was missing
    Code :
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    in the tessellation control shader. I had assumed once gl_Position was set that it was a special case in memory so I didn't need to pass it through. Seems like the kind of thing that could easily be. I guess maybe there are ways to take advantage of the fact that it doesn't work that way?
    One of the reasons that it doesn't work that way is that there's no requirement for the number of input vertices to be equal to the number of output vertices. In fact, "output vertices" is an abuse of terminology. It's just the number of TCS invocations, nothing more or less. Splitting the TCS' workload into multiple invocations allows the inherent parallelism of GPU architectures to be taken advantage of. It's not required (or even common) for the non-patch outputs of a TCS correspond to vertices in any way. E.g. it's fairly typical for a TCS to convert control points to polynomial coefficients, as this simplifies the calculations which the TES performs for each generated vertex.

  8. #8
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    5
    Ah OK that makes complete sense. Thank you for your help!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •