Reverse Z
I recently switched the depth buffers in Flex Engine to use “reversed Z” due to the precision benefits it provides. The default way of encoding depth is from 0.0 to 1.0 as objects get further from the camera. One reason to reverse this is to spread the depth precision out more evenly across the distance of your scene. Using the default encoding, floating point precision combined with a non-linear depth results in lots of precision right next to the near plane, and little precision as things get farther away. See this for a more in-depth explanation. I also found a great explanation of the perspective projection here, which was a great refresher.
The four steps (five for OpenGL) involved in swapping to reversed Z are as follows:
- Swap near and far plane values
- Use greater than or equal as a depth comparison rather than less than or equal to (e.g. GL_GEQUAL or VK_COMPARE_OP_GREATER_OR_EQUAL in OpenGL or Vulkan respectively)
- Clear the depth value to 0.0 at the start of each frame rather than 1.0
- Ensure your depth buffer is using a floating point format
- If using OpenGL, call “glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE)” to make the depth clip range [0, 1] rather than the default of [-1, 1]. (Note that this function is provided in the “GL_ARB_clip_control” extension, which became core in version 4.5)
This change doesn’t make a visually noticeable difference, but it does allow for a lower precision depth buffer, and it should reduce the chances of any z-fighting issues for triangles with very similar positions, especially in shaders with a lot of calculations, and therefore potentially a lot of rounding errors.