Discarding polygons in vertex shader

if depth testing is enabled, can i discard polygons from the vertex shader by setting the Z component of a single vertex to inf/nan; or would that be vaguely undefined? It seems to work on my card, but I’m not sure if that is a good basis to do this.

You’re on the right track. In general, just move the vertex outside of the view frustum and it will be clipped. Do the same thing for all vertices in a primitive and the primitive will be culled away by the pipeline.

gl_Position is written in clip-space. Any point that is within the view frustum satisfies -w <= x,y,z <= +w (unless you’re using ARB_clip_control). So just output a position where this is not true, such as vec4(1,1,1,0).

1 Like

Setting gl_Position.w to zero should work, provided that the far distance is finite (this isn’t required; it’s entirely possible to construct a projection transformation where the far plane is at infinity). Clipping will interpolate with a ratio of k/infinity, resulting in the remaining fraction being zero.

Setting the vertex position to 0,0,0,1 should also work, regardless of the near/far distances. This approach will result in a triangle which is exactly coplanar with the viewpoint (regardless of the positions of the other two vertices), resulting in the NDC projection having zero area.

Although if anti-aliasing (GL_POLYGON_SMOOTH) is enabled, either approach might result in a visible line.

Maybe I need more caffeine this morning, but you may want to double-check that. That’s a point in the center of the frustum (NDC = (0,0,0); NDC Extents (-1…1,-1…1,-1…1))

With perspective, remember gl_Position.w == clip_space.w == -eye_space.z. This is a positive number in front of the eyepoint.

Using a negative number for clip_space.w should work though. For instance, vec4( 0,0,0,-1 ). This represents points behind the eyepoint, which are implicitly clipped by not only the near plane, but the left/right/bottom/top planes as well (in perspective).

The sort of situation i was thinking about is if any one of the vertices fails a test the entire tri is discarded; which is why i was asking about using NaN; because the interpolation math on a NaN should always result in NaN. But after further thought it wouldn’t really fix my problem anyway!

That’s… annoyingly difficult. Cull distances would allow you to discard a primitive if all of the vertices have negative cull distances. But there’s no non-Geometry Shader mechanism to cull a primitive based on just one value being out of range.

No, I’m the one who needs more caffeine; I should have clarified that I meant 0,0,0,1 in eye space. But that’s just equivalent to setting Wclip=0.

Note that if you write the Z value in your shader it will disable hardware optimization like early-z-rejection/hierarchical z-buffer, if your GPU otherwise supports/uses them.

That’s if you write Z (gl_FragDepth) in the fragment shader. This doesn’t come into play for Z updates (gl_Position) in the vertex shader.

1 Like