opengl - Getting the true z value from the depth buffer -
opengl - Getting the true z value from the depth buffer -
sampling depth buffer in shader returns values between 0 , 1, expected. given near- , far- clip planes of camera, how calculate true z value @ point, i.e. distance camera?
from http://web.archive.org/web/20130416194336/http://olivers.posterous.com/linear-depth-in-glsl-for-real
// == 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)); } [edit] here's explanation (with 2 mistakes, see christian's comment below) :
an opengl perspective matrix looks :
when multiply matrix homogeneous point [x,y,z,1], gives you: [don't care, don't care, az+b, -z] (with , b 2 big components in matrix).
opengl next perspective division: divides vector w component. operation not done in shaders (except special cases shadowmapping) in hardware; can't command it. w = -z, z value becomes -a/z -b.
we in normalized device coordinates. z value between 0 , 1. stupid reason, opengl requires should moved [-1,1] range (just x , y). scaling , offset applied.
this final value stored in buffer.
the above code exact opposite :
z_b raw value stored in buffer z_n linearly transforms z_b [-1,1] [0,1] z_e exact same fromula z_n=-a/z_e -b, solved z_e instead. it's equivalent z_e = -a / (z_n+b). , b should computed on cpu , sent uniforms, btw.the opposite function :
varying float depth; // linear depth, in world units void main(void) { float = gl_projectionmatrix[2].z; float b = gl_projectionmatrix[3].z; gl_fragdepth = 0.5*(-a*depth + b) / depth + 0.5; } opengl graphics shader
Comments
Post a Comment