Perspective projection

Perspective projection #

To get the gist of perspective projection consider the following image:

perspective projection

Given the Point \(P(p_x, p_y, p_z)\) what is are the coordinates of the projected point \(P'(p'_x,p'_y,p'_z)\) ?

\[p'_x = d \frac{p_x}{p_z}\] \[p'_y = d \frac{p_y}{p_z}\] \[p'_z = d\]

If \(d = 1\) then the problem simplifies to just dividing by the z-coordinate. And this is what the whole magic about perspective projection is all about. It is just dividing by \(z\) .

Now you do we put this into a matrix \(M_P\) ?

\[ M_P \cdot P = P''\] \[ \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} p_x \\ p_y \\ p_z \\ 1 \end{pmatrix} = \begin{pmatrix} p''_x \\ p''_y \\ p''_z \\ p''_w \end{pmatrix}\]

Applying homogeneous division results in:

\[ p'_x = \frac{p''_x}{p''_z}\] \[ p'_y = \frac{p''_y}{p''_z}\] \[ p'_z = 1\]

Field of view #

What is the field of view here (FOV)? \(90°\) . Why? Consider the following sketch:

fov

Assuming that \(d=1\) and the horizontal field of view is \(\frac{h_{FOV}}{2}\) from trigonometry we know:

\[ \tan(\frac{h_{FOV}}{2}) = \frac{S}{1}\]

What should we do if we want to have a different FOV?

We can simple scale by the inverse of S:

\[ M_S = \begin{pmatrix} \frac{1}{S} & 0 & 0 & 0 \\ 0 & \frac{1}{S} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}\]

Which leads for an angle \(h_{FOV}\) to the projection matrix \(P\) :

\[ P = M_S \cdot M_P\]

Z Precission #

In 3D computer graphics when talking about perspective projection we have often the concept of a near- and a far clipping plane. Thereby \(n\) is the distance of the near clipping to the projection center, and \(f\) is the distance to the far clipping plane. This makes especially in terms of rasterization where we utilize a Z-Buffer sense. Hereby we want to map viewable object between the near- and far clipping plane into the range \([0,1]\) . In ray tracing this is less of importance.

For the sake of completeness here is a mapping for a linear z-Buffer:

\[ p_z' = \frac{p_z-n}{f-n}\]

Assuming \(n = 10\) and \(f = 100\) the liniar z-Buffer distribution looks like this:

linearZBuffer

A non linear z-Buffer distribution can be achieved for example by:

\[ p_z' = \frac{f(p_z-n)}{p_z(f-n)}\]

The graph here look like this:

nonLinearZBuffer

PBRT uses in its perspective projection matrix a non-linear z-Buffer. In the end it does not play a role.

To encoded this non linear z-Buffer we can write change the \(M_P\) matrix this way:

\[ M_P = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{f}{f-n} & -\frac{fn}{f-n} \\ 0 & 0 & 1 & 0 \end{pmatrix}\]

Maybe you wonder how to derive this matrix. Assuming we are given the view frustum \(n = 100\) , \(f = 500\) and \(fov = 30°\)

\[ p'_z=\frac{f(p_z-n)}{p_z(f-n)} = \frac{p_zf-fn}{p_z(f-n)} = \frac{p_zf}{p_z(f-n)} - \frac{fn}{p_z(f-n)} = \frac{f}{f-n} - \frac{fn}{p_z(f-n)} =\] \[ \frac{1}{p_z}(p_z\frac{f}{f-n}-\frac{fn}{f-n})=\frac{p_z\frac{f}{f-n}-\frac{fn}{f-n}}{p_z}\]

The matrix \(M_P\) transforms a view frustum to a canonical view frustum. Given a view frustum with the parameters \(n = 10\) , \(f = 100\) and \(fov = 30°\) looks like this:

Examples #

Task 1: Given: \(n = 10\) , \(f = 100\) and \(\texttt{fov} = 90°\)

Question 1.1: How does the perspective projection matrix with a non-linear z-buffer depth value distribution look like?

Answer 1.1:

\[ P = M_S \cdot M_P \]

Since

\[ S = tan(90°/2) = 1\]

it follows

\[ P = M_S \cdot M_P = M_P = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{f}{f-n} & -\frac{fn}{f-n} \\ 0 & 0 & 1 & 0 \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{10}{9} & -\frac{100}{9} \\ 0 & 0 & 1 & 0 \end{pmatrix} \]

Question 1.2: To which z-value is the point \(P(0, 0, 10)\) mapped/projected?

Answer 1.2: \(p'_z = 0\)

Question 1.3: To which z-value is the point \(P(0, 0, 100)\) mapped/projected?

Answer 1.3: \(p'_z = 1\)

Task 2: Given: \(n = 100\) , \(f = 500\) and \(\texttt{fov} = 30°\)

Question 2.1: How does the perspective projection matrix with a non-linear z-buffer depth value distribution look like?

Answer 2.1: \[ S = tan(h_{Fov}/2) = 2 - \sqrt 3\]

\[ P = M_S * M_P = \begin{pmatrix} \frac{1}{2 - \sqrt 3} & 0 & 0 & 0 \\ 0 & \frac{1}{2 - \sqrt 3} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{5}{4} & -\frac{500}{4} \\ 0 & 0 & 1 & 0 \end{pmatrix} \]

Question 2.2: How does the view frustum look like before the projection? Plot a 2D graph in the z,y-Plane (x is assumed to be \(0\) ) of the view frustum.

Answer 2.2:

View frustum

Question 2.3: How does the view frustum look like after it is multiplied with the projection matrix? Plot a 2D graph in the z,y-Plane (x is assumed to be \(0\) ) of the view frustum.

Answer 2.3:

View frustum after perspective projection

Question 2.4: How does the view frustum look like after it is multiplied with the projection matrix and division by \(w\) is applied? Plot a 2D graph in the z,y-Plane (x is assumed to be \(0\) ) of the view frustum.

View frustum after perspective projection and homogeneous division

Note: Since the homogenous coordinate \((0,500,500,500)\) can be considered to be the same as \((0,1,1,1)\) the picture of Answer 2.3 would also be correct as an answer here. In this case the homogenous values for the coordinates should be annotated. Otherwise it will be unclear what is the value of \(w\) in (0, 500, 500, w).

Question 2.5: How does the bunny look like after the perspective projection matrix with a non-linear z-buffer has been applied?

Frustum with bunny

Answer 2.5:

Frustum with bunny after projection

Further reading #