I have a low-poly mesh and I want to add structure on the surface.

The setup: The mesh consists of triangles. Within the TCS the pixel-length for each of the three edges will be calculated and subdivided according to the given allowed u_MAX_LENGTH_TRIANGLE_EDGE. This will be done in the following way:

vec4 vertexPosScreen[3];                                           
for (int i = 0; i < 3; i++)                                   
    vertexPosScreen[i] = vec4(mvp * gl_in[i].gl_Position);          
    vertexPosScreen[i] = vertexPosScreen[i] / vertexPosScreen[i].w; 
    vertexPosScreen[i].x *= u_viewportWidth;                     
    vertexPosScreen[i].y *= u_viewportHeight;                    
float edgeLength[3];                                                                                                  
edgeLength[2] = length(vertexPosScreen[0].xy - vertexPosScreen[1].xy);
edgeLength[1] = length(vertexPosScreen[0].xy - vertexPosScreen[2].xy);
edgeLength[0] = length(vertexPosScreen[1].xy - vertexPosScreen[2].xy);           

float edgeLod[3];                                         
for (int i = 0; i < 3; ++i)                           
    edgeLod[i] = max(1.0, edgeLength[i] / u_MAX_LENGTH_TRIANGLE_EDGE;
gl_TessLevelOuter[0] = edgeLod[0];                        
gl_TessLevelOuter[1] = edgeLod[1];                      
gl_TessLevelOuter[2] = edgeLod[2];                      
gl_TessLevelInner[0] = max(edgeLod[0], max(edgeLod[1], edgeLod[2]));

This guarantees, that in the final image all triangles edges are smaller than u_MAX_LENGTH_TRIANGLE_EDGE.

The GPU is not able to subdivide as mush as wanted. So if we are too close to a triangle, or a triangle is too tall at all, the TCS will subdivide it as mush as possible, but not enough.

My Idea:
After tessellation is done, the new generated triangles should be stored into a new VBO during the TES step. Afterwards the fresh stored triangles in the new VBO will be rendered again and subdivided as well until all of them are small enough.

Now the big question
How are the tessellation limits defined? per edge division? And how can I ask for the maximum division on CPU? glGetInteger? Or is it limited during the number of generated vertices?

I think the easiest solution would be check directly after "edgeLod" is calculated, if edgeLod is too high. If this is the case, write something into a SSBO and loop the shaderprogram again.


1 Answer 1


The tessellation limit is GPU dependent..Any number above the GPU limit is technically an error but most gpu's just clamp to the upper limit. To get beyond the limit either use a Level Of Detail (LOD) approach where you have different models that are used based on distance, or save and recompute like you suggest.

To get the max just set all the edges to the limit AND set all the internals to the limit in the tessellation control shader:

#version 460 core

  layout(vertices = 4) out;

void main(void)
   gl_TessLevelOuter[0] = 64.0;
   gl_TessLevelOuter[1] = 64.0;
   gl_TessLevelOuter[2] = 64.0;
   gl_TessLevelOuter[3] = 64.0;

   gl_TessLevelInner[0] = 64.0;
   gl_TessLevelInner[1] = 64.0;

   gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

And how can I ask for the maximum division on CPU?

Yes use glGetInteger. At the bottom of this page is all the values you would be intrested in: Khoronos Tessellation limits, search for tessellation on the page

  • $\begingroup$ Thanks a lot! GL_MAX_TESS_GEN_LEVEL is what I was looking for. $\endgroup$
    – Thomas
    Commented Oct 8, 2020 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.