I’m curious as to where user clip planes live in the pipeline. Are they part of the triangle setup or rasterization stage? More specifically, if I use user clip planes with multipass rendering (assuming I’m using different clip planes for each pass), will I get Z fighting if I don’t use a depth bias? Is this implementation dependent?
This is implementation dependant.
If I recall well, ATI does it at rasterization stage, Nvidia clips triangles.
I am not sure, but I think the Nvidia way is the one expected by the spec, can anybody clarify this ?
GL specifies clipping of triangles to the clip volume (which includes the frustum planes as well as user clip planes). It’s described to happen in homogeneous clip coordinates - the space after the PROJECTION matrix, before the projective divide and the viewport/depthrange scale and bias.
Almost no implementation does clipping exactly as described. Because clipping can be expensive and complex in the worst-case scenarios, folks go to some lengths to avoid it.
Guard band clipping is a common way to avoid most of the hard clipping cases, and fully clipless rasterizers are also possible.
NVIDIA hardware typically implements user clip in the raster/fragment part of the pipe, though the exact details vary from one architecture to the next.
Great to know, thanks for the info! Is there any recommended way to get around this? I’d really like to avoid using a depth bias if possible. Since what I’m clipping by amounts to a convex hull, would it be best for me to simply use the stencil buffer?
If you want a clipped triangle to be invariant with an unclipped triangle, you really need to kill the fragments in your fragment shader.
You can do this by computing the clip distances in your vertex program and passing them down as texture coordinates. You just kill the fragment if the distance is less than zero.
Clipping the geometry isn’t invariant because it changes the interpolation subtly in its LSBs.
Well, the problem with doing a kill in the fragment shader is the loss of early Z. I’m doing multipass lighting, and I need to clip each of the passes to a convex hull (a pyramid; 5 planes) that represents a shadow buffered region. Looking at the assembly output of GLSL shaders, I’ve noticed that the kill seems to come last (is this a hardware limitation?), and my shaders are pretty expensive. I could probably get around this using branching in the pixel shader, but I still have to sacrifice varyings to accomplish this.
That said, couldn’t I simply use the stencil buffer to get all of the benefits? I have Z already laid out at the time of rendering, so it seems I could render my clip planes as geometry and modify the stencil buffer so that fragments inside the volume are rendered, and fragments outside are clipped. This would still be invariant, no? Also, would this be faster than using pixel kill if rendering a single pass for each lit surface (my most common case)?
Using the stencil buffer would probably be faster than trying to do clipping and still paying the cost for your expensive lighting. I had a similar situation involving lighting passes with a shadow map for each pass, and I got a significant performance boost from rendering a mask for the unshadowed areas into the stencil buffer first, using alpha test to kill fragments that were shadowed or out of the light’s radius.
Agree with AlexN. Marking stencil is likely the best solution.
If you really only want to mark the fragments within a convex hull, you could render the convex hull with the INVERT stencil op on zpass and mark the stencil without even losing early z.