1
votes

I am sending a triangle down the pipeline and want to tessellate it into an sierpinski gasket. It feels like this would be so much easier with instancing of the geometry shader, therefore please tell me if the idea of doing it with tessellation shaders is simply wrong.

During tessellation control I check the ID against 0-11 and store the vertex position and color on the position of the current ID.

I define glPatchParameteri(GL_PATCH_VERTICES, 3); and layout(vertices = 12) out; for my tesselation control shader as I want each triangle tesselated into 4 triangles.

It looks like during my tessellation evaluation shader the in vec3 tcPosition[]; and in vec3 tcColor[]; arrays contain the correct 12 values in the correct order. However: How do I associate them correctly during evaluation? Is there anything like gl_primitiveID during tessellation evaluation? I would need a replacement for gl_primitiveID which is 0 for all generated vertices as they are spawned from the same patch. Currently I just use the information of the first three vertices (0,1,2) but I would need to shift those indices by 3 after each generated triangle.

void main(){
    vec3 p0 = gl_TessCoord.x * tcPosition[0];
    vec3 p1 = gl_TessCoord.y * tcPosition[1];
    vec3 p2 = gl_TessCoord.z * tcPosition[2];
    tePosition = p0 + p1 + p2;
    teColor = gl_TessCoord.x * tcColor[0] + gl_TessCoord.y * tcColor[1] + gl_TessCoord.z * tcColor[2]; 
    gl_Position = mvp * vec4(tePosition, 1);
} 

Any insights or ideas how to cleverly tessellate the triangle such that I am later able to use transform feedback for ping-pong rendering are highly appreciated.

1

1 Answers

1
votes

I am sending a triangle down the pipeline and want to tessellate it into an sierpinski gasket.

Stop. You cannot do that.

Triangle tessellation is not done in a way that would allow you to generate that. The particular tessellation algorithm required for tessellation is designed to make it easy for edges to connect. It is also designed to make it possible to have adaptive and smooth tessellation.

Sierpinski triangles don't have these properties.

If you need such strict control over the exact means of tessellation, I would suggest doing the tessellation on the CPU. A GS would be incapable of tessellating a triangle finely enough; most OpenGL implementations don't allow the GS to output that many triangles, even with geometry shader instancing.

As to the particulars of your question:

I define glPatchParameteri(GL_PATCH_VERTICES, 3); and layout(vertices = 12) out; for my tesselation control shader as I want each triangle tesselated into 4 triangles.

That's not how tessellation works.

Each patch which reaches the tessellation primitive generator (the step after the TCS), no matter how many vertices it has, is considered a single primitive to be tessellated. Your TCS here outputs 12 vertices in a patch, but the patch itself will still be a single triangle.

Allowing you to control the number of vertices allows you to define what a "vertex" means for your tessellation algorithm. For example, a Bezier surface has 16 control pointsvertices, but it's still a quad. This allows a Bezier-based TES to take all 16 control points as inputs when generating vertex positions.

Also, tessellation does not work based on asking how many triangles you get. It works based on how much subdivision you want. That's what the outer and inner tessellation levels define: the number of segments that the edges of the triangle will be tessellated into.

However: How do I associate them correctly during evaluation?

The TES's inputs are the same values the TCS wrote. In the same order.

The way tessellation works is that what is being tessellated is not your vertices written by the TCS. What is being tessellated is an abstract patch. The tessellation primitive generator generates "vertices" with respect to the abstract patch.

The gl_TessCoord is what allows you to detect where a particular TES invocation is within the abstract patch. You then combine that with the TCS's output data (which are inputs to the TES) to generate the per-vertex values you need for that coordinate.

I would need a replacement for gl_primitiveID which is 0 for all generated vertices as they are spawned from the same patch.

It already does that. gl_PrimitiveID will be the same for each TES invocation in a single patch.