Logarithmic Depth value

I have been using the logarithmic depth buffer for a while, and I have written a shader that reads the buffer per pixel. I need to re-generate a valid depth value from the depth pixel value but I cant seem to get anything that is either accurate, or makes much sense.

Theres a couple of discussions on stack-overflow that I tried, but they didnt work. I read the log depth buffer shader and even tried reversing that, but it seems like something else is happening that Im not sure of.

Could someone explain how I can take a log depth pixel value and covert it back into an accurate Z-float value (from the camera). Thanks for reading.

Does it help:

?

No. I tried this, and this is for Outerra - which uses a similar but different method.
It should be close to

z = (exp(depth_value*log(C*far+1)) - 1)/C

But like I said I cant seem to get it close enough to be usable.
Sorry. I should note, I specifically need a solution for threejs. I think it may not be completely able to be reversed. But it would be good to know if this were the case.

For anyone looking for the answer to this:

Depending on the WebGL version and/or available extensions, there are diffferent ways to calculate the view space z value from the depth texture. This is because Three.js has different ways of interpreting and storing the depth values.

To better understand this, have a look at the four logdepthbuf_*.glsl.js related shader chunks in the ShaderChunks folder.

These are included in many of the materials, including the MeshDepthMaterial (shader at src/renderers/shaders/ShaderLib/depth.glsl.js).

The solutions below follow the implementation of the depth texture example.

Assuming the renderer’s logarithmicDepthBuffer is true, there are two scenarios:

Scenario 1: Your browser has WebGL2 support

// Inside fragment shader
vec4 fragCoord = texture2D( tDepth, vUv );
float logDepthBufFC = 2.0 / ( log( cameraFar + 1.0 ) / log(2.0) );
float viewZ = -1.0 * (exp2(fragCoord.x / (logDepthBufFC * 0.5)) - 1.0);

Scenario 2: Your browser has WebGL1 and extension EXT_frag_depth / WEBGL_depth_texture support

// Inside fragment shader
vec4 fragCoord = texture2D( tDepth, vUv );
float logDepthBufFC = 2.0 / ( log( cameraFar + 1.0 ) / log(2.0) );
float viewZ = -1.0 * (exp2((fragCoord.x + 1.0) / logDepthBufFC) - 1.0);

(Note: I could not test this one, so maybe it’s incorrect.)

You can now use viewZToOrthographicDepth() or viewZToPerspectiveDepth() from the packing.glsl.js shader chunk with viewZ to get the value corresponding to the current camera’s projection.

Example for comparison
Have a look at the JSFiddle I made:
Reading depth buffers normal vs logarithmic

1 Like

Thanks for this, it fixed having extreme values of camera near and far with a logarithmic depth buffer in a WebGL2 environment while I was using the formulas here to get the world position from UV and depth in a post-processing depth shader. For the record, one can find the logDepthBufFC - aka the logarithmic depth buffer float constant, I suppose - formula in the source code of the WebGLRenderer on GitHub here (permalink here).

A simplified way of writing the WebGL2 variant above after reduction would be:

return 1.0 - exp2(texture2D(tDepth, vUv).x * log(cameraFar + 1.0) / log(2.0));

even though the way you wrote it is more explicit and flexible in case some of the involved values change in the future.