Why does the following tessellation control shader makes most triangles disappear?
#version 410
layout(vertices = 3) out;
void main(void) {
gl_TessLevelInner[0]=1;
gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
}
I input triangles. When I index gl_TessLevelOuter with 0,1 and 2, everything works fine. It seems to me that this construct saves me the if statement, which I believe helps in parallel execution of the shader. Of course, I omitted the vertex calculations in the snippet.
Triangles disappear because you incurred in "undefined" behaviour, that's it. The Inner tesellation level should be at least 2.
gl_TessLevelInner[0] = 2;
The weird results you obtain are because of how baricentric coordinates are computed when inner level is 1. Given you provide at least 2 as value, you can use any value you want for Outerlevels.
The following is the edge association for a triangle
out0 => edge 1-2
out1 => edge 2-3
out2 => edge 3-1
Out[0] = 4
Out[1] = 1
Out[2] = 2
As you see, the Inner
of 2, cutted the triangle twice along triangle's bisectors, while the 3 different Outer
levels cutted the triangle along the edges (no cuts for 1
, twice for 2
and 4 pieces when value is 4
)
Tips:
Also there are some small advices, data in tessellation control is shared, that's means it is called multiple times, you need to set tessellation control only once:
if(gl_InvocationID==0){
gl_TessLevelInner[0] = 2; //take a triangle
gl_TessLevelOuter[0] = 1; //and subdivde it in 3 triangles
gl_TessLevelOuter[1] = 1;
gl_TessLevelOuter[2] = 1;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
So why it is still possible to set different values for each invocation? that's to add subdivisions based on screen error (at least is a reasonable use).
if(gl_InvocationID==0){
gl_TessLevelInner[0] = 2; //take a triangle
gl_TessLevelOuter[0] = lenghtOnScreen<5? 3: 4;
}
if(gl_InvocationID==1)
gl_TessLevelOuter[1] = lenghtOnScreen<5? 3: 4;
if(gl_InvocationID==2)
gl_TessLevelOuter[2] = lenghtOnScreen<5? 3: 4;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
In the End:
Another example with Inner=3
and Outer=2
.
Note the 3 cuts along the bisector and 2 cuts along the edges, all other cuts are just for "seamless transition"