Reputation: 6196
Is it possible for only front facing triangles to be sent to the geometry shader? I believe that culling only happens to emitted triangles after the geometry shader by default.
Upvotes: 2
Views: 2402
Reputation: 173
Although it doesn't technically satisfy the question because the triangle reaches the geometry shader, you can cull triangles within the geometry shader itself. This might be the solution people reading this question are looking for, it was for me.
I used the shader below to implement wireframe drawing of quads with culling, where each quad is drawn using two triangles. The idea of using
glPolygonMode(GL_FRONT_AND_BACK, GL_LINES)
with culling includes the diagonal of each quad, which isn't desired, so I use a geometry shader to convert each triangle to just the two lines. However now culling doesn't work because only lines are emitted by the geometry shader. Instead culling is included at the beginning of the geometry shader, just set the uniform culling to -1, 0 or 1 for your desired behaviour (Note, this culling test assumes that the w coord is positive for each vertex).
#version 430 core
layout (triangles) in;
layout (line_strip, max_vertices=3) out;
uniform int culling;
void main()
{
// Perform culling here with an early return
mat3 M = mat3(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz);
if(culling * determinant(M) < 0)
{
EndPrimitive(); // Necessary?
return;
}
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
Upvotes: 0
Reputation: 194
It is actually possible. Like the other answer mentioned you can do it on the software side. But there are stages in-between the vertex shader and geometry shader. Namely, the hull (programmable), primitive generator (fixed), and domain (programmable). In the hull shader you can specify tessellation levels for your patch.
If you set any of these levels to 0.0, then the patch will be discarded and it will not enter the geometry shader!
Hope this helps :)
Upvotes: 0
Reputation: 43319
Yes it is, back in the ancient days of Quake, face culling was done on the CPU using a simple dot product per-triangle. Any triangle that failed the test was not included in the list of indices drawn.
This is not a viable optimization on most hardware these days, but you still see it employed from time to time in specialized applications. One such application I have seen a lot of is using the PS3's Cell SPEs to cull out triangles during batching to save vertex transform workload on the PS3's RSX GPU - keep in mind, the PS3 still uses a basic shader architecture where there are a fixed number of specialized vertex shader units and fragment shader units. Balancing shader workload is important on that GPU.
I may be missing the point of your question though; what benefit do you expect/want to get out of culling the primitives early?
What I was trying to say is that on modern hardware and software, vertex transform / primitive assembly is usually not a bottleneck. Fragment processing is much more expensive these days, so having primitives culled during rasterization is usually the extent to which you have to worry about things for performance. The PS3's RSX is a special case, it has very poor vertex performance and a CPU architecture that is hard to keep busy, so it makes sense to offload primitive culling to the CPU.
You can still cull triangles before the vertex shader/tessellation/geometry shader on the CPU, but storing normals per-triangle somewhere and transferring a new set of indices to draw each frame hardly makes this a wise use of resources. You may spend more time and memory setting up the reduced list of triangles than you would of if you processed them on the GPU and let GL throw the backward facing primitives out during rasterization.
There is at least one use-case that comes to mind where this actually could still be a useful thing to do. I am referring to tessellated patches. If you can determine on the CPU before tessellation occurs that the entire patch faces the wrong way, you can skip having to tessellate them on the GPU. Ordinarily rendering will not be vertex-bound these days, but tessellation is one case where it may be.
Upvotes: 3