glFrustum and depth values

I dont understand what happens to the z-values after a projection. According to the red book, a call to glFrustum(l,r,t,b,n,f) creates
a matrix R where:

Z-row: 0 0 -(f+n)/(f-n) -2fn/(f-n)
W-row: 0 0 -1 0

As I understand it, this matrix is a concatenation of an orthographic projection matrix
and a perspective projection matrix. It should map the perspective view volume onto the
canonical view volume (with x,y,z in [-w,w]). My problem is I dont see how this matrix maps
depth values exactly. Projecting a point p(x,y,z,1) under R gives:

p’.z = p.z * -(f+n)/(f-n) - 2fn/(f-n)
p’.w = -p.z

p’.z / p’.w = (f+n)/(f-n) + 2fn/(f-n)*p.z

Now when p.z = n (near plane) the latter formula should yield -1. It results in

p’.z / p’.w = (f+n)/(f-n) + 2f/(f-n) = (3f+n)/(f-n)

Same for p.z = f (far plane) one should get 1. It results in

p’.z / p’.w = (f+n)/(f-n) + 2n/(f-n) = (3n+f)/(f-n)

Is there a reason for this ‘wrong’ mapping? I have read some regular projection matrix derivatons and I understand them, they also
work on examples, but I dont see the logic in what opengl does with the z-values here.

Thanks for reading this long post,


You have an error in the p’.z equation. I have added parentheses for clarity.

p’.z = (p.z * -(f+n)/(f-n)) + ( p.w * (- 2fn/(f-n)))

which means

p’.z / p’.w = ((p.z * -(f+n)/(f-n)) + ( p.w * (- 2fn/(f-n)))) / - p.z

Putting the numbers in for p.z = f and p.z = n will then give you 1 and -1 respectively

Thanks for the adjustment, but I was kinda working with a p.w value of 1.0 to keep it a bit simple :slight_smile:

You have probably figured this out by now, but for the sake of completeness, here goes:

The trick is to set p.z = -n and -f. Then you get the values you expect. The direction of view is looking down the negative z-axis, so p.z must be negative for points in front of the viewer and positive for points behind. So for the standard GL projection matrix, you will only “see” points that have negative z-values.

I should also point out that GL does frustum-clipping before performing perpective division, this avoids the problem when p.z = 0.