Why doesn't OpenGL clip primitives from my geometry shader that lie partially outside the viewing volume?

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.

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.

Just want to make sure I'm understanding you correctly here. My depth writes occur in the fragment shader after clipping should have occurred. Once they're in the fragment shader, I can set whatever depth value I like and it behaves as I would expect.

The unexpected behavior is that the pre-processed fragments that should not go to the fragment shader in the first place are going there anyway. – Kyle Aug 2 at 2:47 I mean, I understand that in the regular pipeline, any fragments that would be removed by clipping would also fail the depth test if they weren't clipped and so it wouldn't make a difference when they were discarded (except it might save some work for the fragment processor), but is it really a corner case that I might want to alter the depth value? It's necessary for creating depth-correct impostors, for example.

– Kyle Aug 2 at 2:57 @Kyle: I call it a corner case because the problem only appears when you are depth writing and intersecting with the far or near clip planes. So you need to both be hitting near/far and be doing depth writing. Depth-correct impostors tend to be camera-aligned anyway, so either the triangle will entirely be outside the view or entirely not outside the view.

The reason for the behavior is too big for a comment, so I'll edit my answer. – Nicol Bolas Aug 2 at 3:23 Interesting. I'm using a lot of impostors and my bottleneck is in fragment shading, not geometry, so I'm aligning the geometry to take up as little screen area as possible while still containing every pixel the object will eventually cover (perspective distortion makes it tricky).

Funny thing is, this behavior actually makes it easier to simplify the geometry and keep fragments from disappearing, but I guess I shouldn't rely on behavior have goes against the spec. Instead I'll probably test for clipping plane intersection in the geometry shader and nudge my triangles around a little. Thanks!

– Kyle Aug 2 at 3:43 @Kyle: Wait a second. You wouldn't happen to have depth clamping enabled, would you? – Nicol Bolas Aug 2 at 4:22.

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: fgiesen.wordpress.com/2011/07/05/a-trip-... explains the actual border and near&far clipping very good.

1: Incorrect. The very first paragraph of section 2.19 "Primitive Clipping" of the OpenGL 3.3 core specification says, "Primitives are clipped to the view volume. In clip coordinates, the view volume is defined by."

This is followed by the X, Y and Z clipping dimensions, based on the clip-space W (which after the perspective divide, is -1, 1). So yes, the OpenGL Specification clearly states that clipping happens against all dimensions of the viewing volume, near and far included. – Nicol Bolas Aug 2 at 4:18 PS: That article specifies that this is how Direct3D defines clipping.

– Nicol Bolas Aug 2 at 4:20 Okay, OpenGL is very specific about clipping and generating new vertices. Still it is not what the GPU actual does. Yeah, they may even violating the spec.

But it didn't caused any visual difference till now - now you can use transform feedback to get the actual final vertex stream, override fragdepth in fragshaders or write to buffers in the fragment shaders. Also even when the article/blog is written with D3D10/11 in mind, it explains well what the GPU/driver actual does. – jKei Aug 2 at 4:35 I'm not sure what you're trying to say here.

Whether new vertices are actually generated or not is irrelevant; an OpenGL implementation must work as through it clipped the triangle. If it doesn't do actual clipping, it still needs to produce results as though it did; otherwise, it is a driver bug. Oh, and that Wiki article (which I happened to write, BTW), is on the OpenGL wiki.So it naturally explains what OpenGL defines.

That's what the page is for. – Nicol Bolas Aug 2 at 4:42 "it still needs to produce results as though it did" that's what I am trying to say.It might have violated the specs, but before there were fragment shaders it did produced the same results and is likely faster as you already noted. – jKei Aug 2 at 4:58.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions