1
votes

http://www.opengl.org/wiki/Rendering_Pipeline_Overview says that "primitives that lie on the boundary between the inside of the viewing volume and the outside are split into several primitives" after the geometry shader is run and before fragments are rasterized. Everything else I've ever read about OpenGL has also described the clipping process the same way. However, by setting gl_FragDepth in the fragment shader to values that are closer to the camera than the actual depth of the point on the triangle that generated it (so that the fragment passes the depth test when it would have failed if I were copying fixed-pipeline functionality), I'm finding that fragments are being generated for the entire original triangle even if it partially overlaps the far viewing plane. On the other hand, if all of the vertices are behind the plane, the whole triangle is clipped and no fragments are sent to the fragment shader (I suppose more technically you would say it is culled, not clipped).

What is going on here? Does my geometry shader replace some default functionality? Are there flags/hints I need to set or additional built-in variables that I need to write to in order for the next step of the rendering pipeline to know how to do partial clipping?

I'm using GLSL version 1.2 with the GL_EXT_geometry_shader4 extension on an NVIDIA GeForce 9400M.

2

2 Answers

1
votes

That sounds like a driver bug. If you can see results for fragments that should have been outside the viewing region (ie: if turning off your depth writes causes the fragments to disappear entirely), then that's against the spec's behavior.

Granted, it's such a corner case that I doubt anyone's going to do anything about it.

Most graphics hardware tries as hard as possible to avoid actually clipping triangles. Clipping triangles means potentially generating 3+ triangles from a single triangle. That tends to choke the pipeline (pre-tessellation at any rate). Therefore, unless the triangle is trivially rejectable (ie: outside the clip box) or incredibly large, modern GPUs just ignore it. They let the fragment culling hardware take care of it.

In this case, because your fragment shader is a depth-writing shader, it believes that it can't reject those fragments until your fragment shader has finished.


Note: I realized that if you turn on depth clamping, that turns off near and far clipping entirely. Which may be what you want. Depth values written from the fragment shader are clamped to the current glDepthRange.

Depth clamping is an OpenGL 3.2 feature, but NVIDIA has supported it for near on a decade with NV_depth_clamp. And if your drivers are recent, you should be able to use ARB_depth_clamp even if you don't get a 3.2 compatibility context.

-1
votes

If I understood you correctly, you wonder that your triangles aren't clipped against the far plane.
Afaik OpenGL just clips against the 4 border planes after the vertex assembly. The far and near clipping gets done (by spec afaik) after the fragment shader. Ie when you zoom in extremely and polygons collide with the near plane they get rendered to that point and don't pop away as a whole.
And I don't think that the specs note splitting primitives at all (even when the hw might do that in screenspace ignoring fragdepth), it just notes skipping primitives as a whole (in the case that none vertex lies in the view frustum).
Also relying on a wiki for word-exact rules is always a bad idea.

PS: http://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/ explains the actual border and near&far clipping very good.