You would be forgiven for thinking any of the following were at fault:
- Polygons are too close together
- Depth equation is incorrect
- Depth buffer is too small (not enough bits)
- Near and far clipping planes are too far apart
As it turns out, the near clipping was a little too near. If you want to see this for yourself, just try modifying existing code to put the near clipping plane at 0, and watch the depth buffer squirm!
Why does this happen?
When your scene is going to be rendered, all the geometry gets passed through the various coordinate spaces, until it is mapped nicely into your viewing frustum. The frustum is effectively squished into a nice orthogonal cuboid, with your rendering viewport being one side of it.
At this point, viewport dimensions are mapped onto the X and Y (horizontal and vertical) axes -- that could be your screen resolution, for example. Meanwhile, the depth buffer is mapped onto the Z axis. The depth buffer size is usually determined when initialising OpenGL, and could be 24 bits. That would mean you could hypothetically represent around 16.7 million different depths in between your near and far clipping planes.
You might expect the depth buffer to be uniformly mapped along the Z axis of this viewing box. However, the usual mapping increases as you approach the camera. This is to allow for more detailed depth handling for polygons which are visibly 'nearer' the viewport (and therefore more noticeable).
As a result, if your near clipping is at (or very very near) a depth of 0, then your depth buffer mapping is almost entirely clustered at that depth. In other words, you end with very few bits (if any) left for the rest of your viewing frustum. The ultimate consequence is such low precision depth representation that it looks like your depth buffer is being distorted or corrupted.
Remember kids: just say "no" to near clipping planes at 0 depth. :-)
