0
votes

Ive coded tons of shaders but Ive stumbled into something I never realized before.

I needed a vertex + fragment shader with a simple orthographic projection, with no depth test.

The camera is Z-aligned with the origin.

I disabled GL_DEPTH_TEST, and masked depth writes. It was so simple infact, that I decided I didnt even need a projection matrix. In my complete ignorance and ingenuity, I thought that for any triangle vertex, the vertex shader would simply pass x,y(,z = <whatever>,w = 1) to the fragment shader.

I actually thought the fragment shader would just need x,y coordinates, because since we're talking about orthographic projection, w = 1 (no perspective division), and since depth buffer is useless, and depth writes disabled, z could literally be anything, doesnt matter.

Of course I was wrong. I quickly found that the z component is quite used by the rasterizer, infact, I have tons of triangles that simply dont get rasterized.

I also found that tweaking the z component would dramatically change the rendered triangles. So I implemented a regular orthographic projection matrix, and that of course solved the issue, now everything is properly rasterized.

Now, out of pure curiosity, I started playing with a orthographic projection matrix and see what really produced for different input vectors, with different values for near and far clipping planes, and I really cant understand. Ok, x,y and w are all as expected, but I get completely different z values based on my near/far clip planes.

The question is: the fragment shader doesnt know anything about clip planes and projection matrices, it just gets a bunch of x,y,z,w... what is the role of the z component in the rasterization process? how does it know if something is inside the viewing frustrum or not?

I mean, for any given near/far plane in the orthographic projection matrix, I get z values that are valid for a given projection matrix, and invalid for others. Since the fragment shader has no way to know which planes were used in the matrix, how can it discards fragments? Is there a relationship between every vertex of the same primitive?

PS: I know the fragment shader is not even invoked, as I setup a SSBO + Atomic Counter and checked both are unchanged.

1
Rasterisation performed before fragment shader stage - it is actually what generates fragments. Znear/Zfar alignes your min/max values to match z=1 and z=-1 in clip space. Just clip everyting that doesn't fit in unit cube (in clip space - after projection and perspective division) and all is fine.keltar
What's your resulting matrix? Why your Zfar is greater than Znear? Z axis comes from depth to camera in opengl. Quick calculation on paper gives me ~ 0.7317 for z=300 and given znear/zfar (inverted, of course).keltar
you're right.. I deleted my previuos incorrect example, I recalculated everything and I had a sign error.. you're right..it just scales everything from -1 to +1 if inside the frustrum.. if you post an answer I will acceopt it. Thank you.user815129

1 Answers

2
votes

Vertex shader transforms vertices from model-local coordinate system to clip space. If your coordinates exceeds unit cube after perspective division (cube with [-1;1] sizes for each dimension, or [-W;W] before division), then this fragments would be clipped.

If you don't care about Z and really don't want to set correct ortho projection (e.g. you don't know Z values range and hence cannot set appropriate clip planes), you can correct Z in vertex shader by clamping it to (-W; W) range (or just setting it 0).