The Projection Transform looks like this:
Let $\pvcs = (x, y, z, 1)$ and let $\pccs = (x', y', z', w')$. Then
From the transformation matrix above, $y' = F y + B z$. Consider a 2D slice at $x = 0$ through the view volume (shown on the left below) and the corresponding 2D slice at ${x' \over w'} = 0$ through the canonical view volume (shown on the right below):
Points on the top line of the view volume satisfy ${y \over -z} = {t \over n}$. That is, there points are of the form $({-tz \over n} , z)$. These points correspond to points on the top line of the canonical view volume that satisfy ${y' \over w'} = 1$.
Substitute a point $({-tz \over n} , z)$ into the $y'$ and $w'$ lines of the transformation matrix:
As stated above, the VCS point $({-tz \over n} , z)$ is transformed to a CCS point for which ${y' \over w'} = 1$. So
So we know that
By a similar argument (using VCS points $( {-b z \over n}, z )$ on the bottom line which map to CCS points for which ${y' \over w'} = -1$) we can show that
We can then solve the two equations in $F$ and $B$ to get:
This is done analagously to $y'$.
Given $\ell$ and $r$ which are the left and right limits in the $x$ direction of the view volume, we apply the same method as for $y'$ and get
VCS points on the near plane ( $z = -n$ ) map to CCS points on the line ${z' \over w'} = -1$, and VCS points on the far plane ( $z = -f$ ) map to CCS points on the line ${z' \over w'} = +1$.
From the transformation matrix:
Substitute $z = -n$ to get one equation. Substitute $z = -f$ to get another equations. The unknowns are $C$ and $D$:
Solving the equations yields:
Bringing everything together:
Other VCS-to-CCS transformation matrices exist. In particular, orthographic projection is sometimes used.
See functions frustum(), perspective(), and ortho() in 00-intro/src/linalg.cpp in openGL.zip.
Points outside the view frustum must be clipped. The clipping could be done in almost any coordinate system, but it's best to do clipping in the CCS because:
In the figure below, the segment $pq$ in the VCS is transformed to the segment $p'q'$ in the NDCS. If we clip $p'q'$, the segment will appear to be exiting the far plane of the canonical view volume. But it should really exit the top plane!
For example, if $q = [0,0,-100,1]^T$ and $n=1, f=2, r=+1, l=-1, t=+1, b=-1$ then $q$ is behind the viewpoint (as above) and the projection matrix is
$\left[\begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -3 & -4 \\ 0 & 0 & -1 & 0 \end{array}\right]$
Then $q' = P q = [x', y', z', w']^T = [0, 0, -304, -100]^T$ and, upon division by $w'$ we get $[0, 0, 3.04]^T$, which is ahead of the viewer instead of behind, as the original $q$ was.
For a better intuition, consider what happens to $q'$ as $q$ is moved along the $z$ axis of the VCS:
If the point were in NDCS, we would clip against the six planes that define the faces of the canonical view volume:
The corresponding planes in the CCS are:
Given a segment $p'q'$ in the CCS, we clip against each of the six planes. Note that these are planes in a 4D homogeneous space, but clipping works the same in any dimension, as we'll see below.
A line segment $ab$ has endpoints $a$ and $b$. It can be written in parametric form as
For $t \in [0,1]$, $\ell(t)$ is between $a$ and $b$. For $t$ outside this interval, $\ell(t)$ is not on the segment $ab$.
A plane $\pi$ is defined by a normal, $n$, and a distance from the origin, $d$. All points $x$ on the plane satisfy the implicit equation
Points above the plane (i.e. on the side of the plane that $n$ points to) will have $\pi(x) > 0$. Points below the plane will have $\pi(x) < 0$.
Segment $ab$ is clipped by the plane if and only if its endpoints lie on different sides of the plane. So compute $\pi(a)$ and $\pi(b)$. Then $ab$ intesects $\pi$ if and only if $\pi(a)$ and $\pi(b)$ have different signs. (If one or both are equal to zero, $ab$ is not clipped because it does not cross the plane.)
If $ab$ is clipped by $\pi$, we need to find the point at which $ab$ intersects $\pi$, to clip $ab$ at that point.
To find the point of intersection, substitute the parametric segment equation into the implicit plane equation and solve for the parameter $t$:
Then the intersection point is $\ell(t)$.