# How does this simple fragment shader function work?

• 10-01-2012, 02:13 PM
Nick Wiggill
How does this simple fragment shader function work?
This code is used in a DoF blur fragment shader I found online (I am trying to make one of my own):

Code :

```uniform sampler2D gdepth; //<- the depth buffer? How/where is this set? float getDepth(vec2 coord) { return 2.0 * near * far / (far + near - (2.0 * texture2D(gdepth, coord).x - 1.0) * (far - near)); //is gdepth equivalent to gl_FragCoord.z? }```

How do the mathematics in this depth retrieval function work? I assume it's converting from screen to world space. The terms look strikingly like those found in the projection matrix I ended up using in my CPU-side code:

Code :

```public static Matrix4 getProjectionMatrix(float fovYDeg, float aspectRatio, float near, float far) { Matrix4 result = new Matrix4();   float fovYRad = fovYDeg * (float)PI / 180f; float e = 1f/(float)(tan(fovYRad / 2)); //focal length   result.val[Matrix4.M00] = e / aspectRatio; result.val[Matrix4.M11] = e; result.val[Matrix4.M22] = (far + near) / (near - far); result.val[Matrix4.M23] = (2 * far * near) / (near - far); result.val[Matrix4.M32] = -1f; result.val[Matrix4.M33] = 0f;   return result; }```

I really can't just keep letting this stuff go over my head.

PS. The original shader code is here.
• 10-01-2012, 05:45 PM
Dark Photon
Quote:

Originally Posted by Nick Wiggill
Code :

`2.0 * near * far / (far + near - (2.0 * texture2D(gdepth, coord).x - 1.0) * (far - near));`

How do the mathematics in this depth retrieval function work?

This computes the negative of eye-space Z (so +near..+far) from window-space Z (0..1) with the assumptions: 1) a perspective projection was used for rendering, 2) glDepthRange == 0..1, and 3) w_eye == 1 (true for a point). Add a leading negative to it and it computes eye-space Z (i.e. -near..-far).

(No, I didn't just figure that out -- have read that and done it before :-)

Yeah, you can get this from the perspective projection matrix, which takes you from eye-space to clip-space. To get from clip-space to NDC space, divide by w. To get from NDC to window-space, shift/scale -1..1 to 0..1.

Here's the jist of it:

Code :

```// First, multiply (0,0,z_eye,1) by projection matrix to get z_clip and w_clip), then just plug them into // the following equation, as we'll do below:   z_ndc = z_clip / w_clip z_ndc = [ z_eye*gl_ProjectionMatrix[2].z + gl_ProjectionMatrix[3].z ] / -z_eye```

Solve the above for z_eye, and you get:

Code :

`float z_eye = gl_ProjectionMatrix[3].z/(-z_ndc - gl_ProjectionMatrix[2].z);`

Typically your glDepthRange is 0..1, so z_ndc = z_window * 2 - 1, so plugging that in...

Code :

`float z_eye = gl_ProjectionMatrix[3].z/(z_window * -2.0 + 1.0 - gl_ProjectionMatrix[2].z);`

Substitute the terms from the projection matrix, and there you go.