Perspective projection: part 3
Posted by Andy Wood on May 30, 2009
In part one and part two, we derived formulas for projecting a 3d point onto the view plane, with values mapped into clip space, and depth information correctly preserved. Now we’re ready to take everything we know about vector/matrix multiplication and homogeneous coordinates, and compose the perspective projection matrix.
Let’s begin by recapping those formulas. zNear is the z value of the near plane (also called d in previous posts). zFar is the z value of the far plane. nearWidth and nearheight are the width and height of the near plane:
Notice that each one of these involves a division by z. Actually, the calculation of clip_z doesn’t really need a division by z, but as explained in the previous post, we have to use homogeneous coordinates to accomplish the division by z for x and y, and it’s an all or nothing deal. It’s amazing to me that all of this ends up working out. Thank goodness for mathematicians!
Since that division by z will not (and cannot) be carried out by the matrix multiplication itself, we can take it right out of all three equations. We just need to make sure the matrix puts the value of z into the resulting w coordinate. This leaves us with calculations that can be carried out by a single 4×4 matrix. All that’s left is to figure out where in the matrix to place the different parts.
Remember that each component of the result vector is determined by a single row of the matrix:
Row 1 determines the resulting x coordinate.
Row 2 determines the resulting y coordinate.
Row 3 determines the resulting z coordinate.
Row 4 determines the resulting w coordinate.
Let’s proceed one component at a time. We want the source x to be multiplied by . The column in row 1 of the matrix that gets multiplied by x is the first one, entry (1,1). That’s all there is to it. We put
into (1,1) and zeros in all the other columns. So the first row of the matrix is:
Calculating y is almost the same, except it’s the second column that gets multiplied by the source y. So the second row is:
For z, remember that we need to add two terms together. One is multiplied by the source z, and the other is just a constant. So the part to be multiplied by z goes in the third column, and we conveniently hijack the w column to host the constant:
That leaves w, to which we simply assign the value of the source z by placing a one in the third column:
And we’re done! The final perspective projection matrix is:
Yeah, I just figured out that WordPress supports . Awesome.
This concludes the perspective projection series. You should now be able to look at that matrix and understand exactly what it does to a 3D point.