5

How to linearize logarithmic depth buffer?

visualization of linear depth buffer in fragment shader

  float n = 1.0; // camera z near
  float f = 27000000.0; // camera z far
  float z = texture( DepthTex, TexCoord ).x;
  float d = (2.0 * n) / (f + n - z * (f - n));
  FragColor=vec4(d,d,d,1);

sphere vertex shader

vec4 ClipCoords(vec3 position,mat4 matrix)
{
   vec4 clip = matrix * vec4(position,1.0f);
   clip.z =((2.0f * log(1.0f * clip.z + 1.0f) / log(1.0f * 27000000.0f + 1.0f)) - 1.0f) * clip.w;
   return clip;
}
 gl_Position = ClipCoords(position,matrix);

The left part shows Logarithmic depth buffer linearization or rather its lacks, while right shows linarization without log just gl_Position = matrix * vec4(position,1.0f); enter image description here

user1075940
  • 1,086
  • 2
  • 22
  • 46

1 Answers1

7

With logarithmic depth buffer, the mapping of scene (camera space) depth to values that ultimately end up in the depth buffer (0..1) is:

depth_value = log(C*z + 1) / log(C*Far + 1)

where z is the positive depth into the scene, otherwise obtainable from the w component in clip space after the projection (in your code you can use ..log(clip.w + 1.0)..).

To retrieve the camera space depth in a fragment shader, the equation needs to be inverted:

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

or equivalently

z = (pow(C*far+1,depth_value)-1)/C

To get a linear mapping from 0..far into a 0..1, just divide it by the far value.

  • What is `C` (and to a lesser extent `far`) in these equations? I'm assuming far is the FrustumFar? – Richard Tingle May 11 '14 at 18:22
  • C is a constant used to tweak the logarithmic profile. Its effect is described in http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html in comparison of logarithmic depth functions. Usually you can safely set it to 1. far corresponds to the frustum far distance. – camenomizoratojoakizunewake May 14 '14 at 14:11