Simply 3D

Math for computer graphics, made simple

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:

clip\_x = x \times \dfrac{2 \times zNear}{z \times nearWidth} \\ \\ \\  clip\_y = y \times \dfrac{2 \times zNear}{z \times nearHeight} \\ \\ \\  clip\_z = (z \times \dfrac{zFar}{zFar-zNear} + \dfrac{zNear \times zFar}{zNear-zFar}) \div z

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 \dfrac{2 \times zNear}{nearWidth}.  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 \dfrac{2 \times zNear}{nearWidth} into (1,1) and zeros in all the other columns.  So the first row of the matrix is:

\begin{array}{cccc} \frac{2 \times zNear}{nearWidth} & 0 & 0 & 0 \end{array}

Calculating y is almost the same, except it’s the second column that gets multiplied by the source y.  So the second row is:

\begin{array}{cccc} 0 & \frac{2 \times zNear}{nearHeight} & 0 & 0 \end{array}

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:

\begin{array}{cccc} 0 & 0 & \frac{zFar}{zFar-zNear} & \frac{zNear \times zFar}{zNear-zFar} \end{array}

That leaves w, to which we simply assign the value of the source z by placing a one in the third column:

\begin{array}{cccc} 0 & 0 & 1 & 0 \end{array}

And we’re done!  The final perspective projection matrix is:

\left[\begin{array}{cccc}  \dfrac{2 \times zNear}{nearWidth} & 0 & 0 & 0 \\  0 & \dfrac{2 \times zNear}{nearHeight} & 0 & 0 \\  0 & 0 & \dfrac{zFar}{zFar-zNear} & \dfrac{zNear \times zFar}{zNear-zFar} \\  0 & 0 & 1 & 0  \end{array}\right]

Yeah, I just figured out that WordPress supports \LaTeX.  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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.