Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>From <a href="http://web.archive.org/web/20130416194336/http://olivers.posterous.com/linear-depth-in-glsl-for-real" rel="nofollow noreferrer">http://web.archive.org/web/20130416194336/http://olivers.posterous.com/linear-depth-in-glsl-for-real</a></p> <pre><code>// == Post-process frag shader =========================================== uniform sampler2D depthBuffTex; uniform float zNear; uniform float zFar; varying vec2 vTexCoord; void main(void) { float z_b = texture2D(depthBuffTex, vTexCoord).x; float z_n = 2.0 * z_b - 1.0; float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)); } </code></pre> <p>[edit] So here's the explanation (with 2 mistakes, see Christian's comment below) :</p> <p>An OpenGL perspective matrix looks like this : <img src="https://i.stack.imgur.com/mN7ke.png" alt="from songho.ca"></p> <p>When you multiply this matrix by an homogeneous point [x,y,z,1], it gives you: [don't care, don't care, Az+B, -z] (with A and B the 2 big components in the matrix).</p> <p>OpenGl next does the perspective division: it divides this vector by its w component. This operation is not done in shaders (except special cases like shadowmapping) but in hardware; you can't control it. w = -z, so the Z value becomes -A/z -B.</p> <p>We are now in Normalized Device Coordinates. The Z value is between 0 and 1. For some stupid reason, OpenGL requires that it should be moved to the [-1,1] range (just like x and y). A scaling and offset is applied.</p> <p>This final value is then stored in the buffer.</p> <p>The above code does the exact opposite : </p> <ul> <li>z_b is the raw value stored in the buffer</li> <li>z_n linearly transforms z_b from [-1,1] to [0,1]</li> <li>z_e is the same formula as z_n=-A/z_e -B, but solved for z_e instead. It's equivalent to z_e = -A / (z_n+B). A and B should be computed on the CPU and sent as uniforms, btw.</li> </ul> <p>The opposite function is :</p> <pre><code>varying float depth; // Linear depth, in world units void main(void) { float A = gl_ProjectionMatrix[2].z; float B = gl_ProjectionMatrix[3].z; gl_FragDepth = 0.5*(-A*depth + B) / depth + 0.5; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload