gluPerspective question

Ok, I was trying to draw a cube using vertex arrays. I got a TON of rendering errors like an alpha blended cube that had certain triangles randomly vanishing and coming back between frames. It was a mess. I couldn’t figure out what was happening and I was looking over NeHe’s tutorial and I noticed that he said the near plane in gluPerspective to 0.1f instead of 0.0f like i did. The second i changed it, it worked like a charm. What is it about setting the near plane to 0.0f that messes OpenGL up?

  • Halcyon

The closer that the near plane is to 0, the less effective precision you have for distant depth values. A near plane of 0 reaches the limit where all the precision of 0 to 1 depth values has been crammed into the distance range from 0 to 0, and the rest of the distances get clamped to 1.

Essentially, a near plane of 0 causes all depth values to be identical, making the depth buffer useless. This is why the docs for gluPerspective say that near should always be positive instead of saying that it should always be non-negative.

[This message has been edited by Coriolis (edited 01-11-2003).]

Thanks man. Wow, your explanation was really good and quite clear! The only think i dont understand is…well i guess i was thinking this the wrong way…i thought OpenGL used the near and far plane to calculate the depth buffer. So the furthest depth you could go to be rendered would be the far plane and the closest would be the near plane.

Sorry, i haven’t reached linear algebra and all this stuff i just ran across learning by myself. So I’m bound to have gotten a lot of things mixed up! Thanks for your help.

-Halcyon

The value written into the depth buffer is the transformed Z divided by the transformed W. If you look at glFrustum (which gluPerspective effectively calls) and do the matrix multiply with [X Y Z W], you’ll see that for a near plane distance N and far plane F:

Z’ = -(F + N) / (F - N) * Z + 2 * F * N / (F - N) * W
W’ = -Z

Doing the perspective divide, you get the depth value is:

Depth = (F + N) / (F - N) - 2 * F * N / (F - N) * W / Z

If N == 0, then

Depth = (F + 0) / (F - 0) - 2 * F * 0 / (F - 0) * W / Z

Which simplifies to

Depth = 1

EDIT: fixed a sign error.

[This message has been edited by Coriolis (edited 01-11-2003).]

Oops, I didn’t completely answer your question. Let’s back up to the first depth equation and assume W = 1 (which is almost always the case):

Depth = (F + N) / (F - N) - 2 * F * N / (F - N) * 1 / Z

For Z == N, this gives you:
Depth = (F + N) / (F - N) - 2 * F / (F - N) = (-F + N) / (F - N) = -1

For Z == F, this gives you:
Depth = (F + N) / (F - N) - 2 * N / (F - N) = (F - N) / (F - N) = 1

So, the depth value is in the range [-1, 1], assuming that N != 0. If N == 0, then you have 0/0, which calculus says can be any number depending, so the [-1, 1] range conclusion doesn’t hold.

This depth value is used for the clipping cube. Once all depth values have been clipped to this range, they then get rescaled by the range in glDepthRange, so that -1 maps to the near depth range and +1 maps to the far depth range. (The depth range is [0, 1] by default.) This is the value that ultimately gets written to the depth buffer. If the near plane is 0, then the depth value written is always the furthest value in the depth range, which is 1 by default.

Wow! You really know your stuff! Thanks for taking the time to answer my question

  • Halcyon

You’re welcome