Faking depth values

This is going to be a short but technical post, about some information that I found surprisingly hard to find online. If your a programmer in the gaming world you’re probably pretty familiar with a depth buffer. If you’re not, you might find this post a bit confusing or tedious.

One thing you might know about depth buffers is that they don’t exactly store a simple depth value. They store a weird non-linear version of it, in a clever way to get you better depth precision closer to the camera. A good write up of the gritty details of how this works can be found at this article here called Depth Buffer – The gritty details.

Another thing you might know is that although the depth values written out are usually pretty standard (and derived from the depth of the pixel in the way described above), it’s possible to write non-standard depth values from the pixel shader. This can be useful for techniques such as imposters.

I had need recently to fake some depth values, and I was surprised that I couldn’t find the formula for converting to standard depth to depth-buffer-friendly depth. Perhaps this is because my google-fu is weak – I’m not entirely sure – but I did eventually figure out the maths required and I present it here on the off chance that someone finds it helpful.

You will need three numbers. The near and far clip distances set on your camera, and the depth of the fragment. Note that this isn’t quite the same as the distance from the camera to the fragment – it’s the distance in the direction of the camera’s forward vector (that’s what you get by multiplying the fragment’s world position by the view matrix and taking just the z component).

So to get from there to the value you write to the depth buffer, here’s what you need:

zBufferValue = (farClip / fragDistance) * ((fragDistance – nearClip) / (farClip – nearClip))

That’s it! In glsl you write that value to a built-in called gl_FragDepth – how it’s done in other shader languages is an exercise for the reader, because I have no idea.

Anyway, I realise this article falls quite a bit shy of a proper tutorial on depth buffers or imposters or whatever – maybe I’ll come back and write one of those later – but for the moment I just wanted to write down that formula. I hope somehow it is useful for someone’s particular purpose.