Skip to article frontmatterSkip to article content

A Comprehensive Guide To Projection Matrices In Computer Graphics

Constructing Projection Matrices Using Matrix Representations Of Projective Transformations In Real Projective Space

Abstract

We derive perspective projection and orthographic projection matrices from first principles using projective geometry. After establishing the topological manifold structure of real projective space, we find matrix representations for linear, affine, and projective transformations in real projective space. We then formulate the projection specifications in a coordinate-independent manner, leading to general formulas for perspective and orthographic projection matrices. Finally, we apply these results to succinctly calculate the projection matrices for OpenGL, Vulkan, Metal, and DirectX. This process illustrates why real projective space is a convenient setting for solving computer graphics problems.

Keywords:computer-graphicscomputer-sciencelinear-algebrarenderingcomputer-visiongeometric-modelingprojective-geometryapplied-computing

Introduction

We construct the perspective and orthographic projection matrices common to computer graphics in a very general way. The usual parametrizations are defined with respect to specific coordinate system and a specific canonical view volume, such that the view volume parameters define the view volume planes directly in terms of coordinates. This is how most computer graphics books construct the projection transformations.

Rendering is done in the manifold RP3\mathbb{RP}^{3} in homogeneous coordinates for multiple reasons:

  1. Affine transformations become linear transformations one dimension higher, so translations can be treated like any other linear transformations.
  2. Transformations in RP3\mathbb{RP}^{3} are well-defined under changes in scale, so we can handle projective transformations in a unified fashion with affine transformations.
  3. Coordinate systems and scales become equivalent, allowing spatial simulation problems to be expressed directly in a coordinate independent way.
  4. We can change coordinate systems to whatever coordinate system makes the problem at hand convenient to work with.
  5. For very practical reasons, we can express the problem in a coordinate system that affords the best numerical precision possible on the hardware.

A platform such as OpenGL, Vulkan, DirectX, Metal, or WebGPU typically defines its normalized device coordinate system as one that is a numerically favorable coordinate system. Any spatial computing domain whose problems are formulated in Euclidean space can take advantage of the manifold RP3\mathbb{RP}^{3}. Such domains include computer graphics, computer vision, geometric modeling, and robotics. In the context of computer graphics, the platform coordinate system is whichever one maps the view volume in the viewing space to the canonical view volume defined by the platform interface. In particular, the canonical view volume tends to be parametrized by either [1,1]×[1,1]×[1,1][-1, 1] \times [-1, 1] \times [-1, 1] or [1,1]× [1,1]×[0,1][-1, 1] \times \ [-1, 1] \times [0, 1]. In either case, transforming the problem to a unit interval adds one free bit of extra precision when working with floating point numbers. This maximizes the accuracy of floating point computations on the GPU, including tasks such as intersection testing, depth testing, texture sampling, and clipping algorithms.

We parametrize the view space view volume in a slightly different way than the usual one to make the perspective view volume specification coordinate independent. This allows us to construct the matrices for any specific view space coordinate system, perspective view volume, orthographic view volume, normalized device coordinate system, and canonical view volume. We define a canonical set of transformations where the view space is a left-handed orthonormal frame where the horizontal axis points right, the vertical axis points up, and the depth axis points into the view volume, and a clip coordinate system with a left-handed orthonormal frame where the horizontal axis points right, the vertical axis points up, and the depth axis points into the view volume. We show how to construct a general perspective projection or orthographic projection from any source view coordinate system to any target clip coordinate system.

The Topological Manifold Structure Of Real Projective Space

This section establishes the topological structure and manifold structure of the real projective space RP3\mathbb{RP}^{3}. It can be skipped if the reader so desires.

We define real projective space RP3\mathbb{RP}^{3} as follows. Define w1w2\mathbf{w_{1}} \sim \mathbf{w_{2}} if an only if there exists a nonzero real number λR{0}\lambda \in \mathbb{R} - \{0\} such that w1=λw2\mathbf{w_{1}} = \lambda \mathbf{w_{2}}. The relation \sim is an equivalence relation. To prove this, we need to show that \sim is reflexive, symmetric, and transitive. For reflexivity, trivially w=w\mathbf{w} = \mathbf{w} so we can take λ=1\lambda = 1 which shows that ww\mathbf{w} \sim \mathbf{w}. To show symmetry, suppose that w1w2\mathbf{w}_{1} \sim \mathbf{w}_{2}. Then there exists λR{0}\lambda \in \mathbb{R} - \{ 0 \} such that w2=λw1\mathbf{w}_{2} = \lambda \mathbf{w}_{1} implying that w1=1λw2\mathbf{w}_{1} = \frac{1}{\lambda} \mathbf{w}_{2} hence w2w1\mathbf{w}_{2} \sim \mathbf{w}_{1}. Now it remains to prove that \sim is transitive. Suppose that w1w2\mathbf{w}_{1} \sim \mathbf{w}_{2} and w2w3\mathbf{w}_{2} \sim \mathbf{w}_{3}. Then there exist real numbers λ,μR{0}\mathbf{\lambda}, \mathbf{\mu} \in \mathbb{R} - \{ 0 \} such that w2=λw1\mathbf{w}_{2} = \lambda \mathbf{w}_{1} and w3=μw2\mathbf{w}_{3} = \mu \mathbf{w}_{2}. This implies that

w3=μw2=μ(λw1)=(μλ)w1=μλw1\mathbf{w}_{3} = \mu \mathbf{w}_{2} = \mu \left( \lambda \mathbf{w}_{1} \right) = \left( \mu \lambda \right) \mathbf{w}_{1} = \mu \lambda \mathbf{w}_{1}

implying that w1w3\mathbf{w}_{1} \sim \mathbf{w}_{3}. This proves transitivity. Therefore, \sim is and equivalence relation.

We define the real projective space by RP3=(R4{0})/\mathbb{RP}^{3} = ( \mathbb{R}^{4} - \{ \mathbf{0}\} )/\sim. The real projective space identifies lines through the origin in R3\mathbb{R}^{3} with points in RP3\mathbb{RP}^{3}.

Define a map π:R4{0}RP3\pi : \mathbb{R}^{4} - \{\mathbf{0}\} \rightarrow \mathbb{RP}^{3} by

π(P)=[P]\pi\left( P \right) = \begin{bmatrix} P \end{bmatrix}

where [.][.] on the right-hand side indicates the equivalence class of (PT,w)T\begin{pmatrix} P^{T}, w \end{pmatrix}^{T}. The function π\pi is surjective. To show this, suppose that [P][P] is a homogeneous point in RP3\mathbb{RP}^{3}. Since [P][P] is an equivalence class, it is nonempty, so there is at least one element in [P][P], namely PP itself. Since the map π\pi maps elements to its equivalence class, we obtain π(P)=[P]\pi(P) = [P]. Since the equivalence class [P][P] was chosen arbitrarily, the function π\pi is surjective.

Now that we have established that π\pi is surjective, we can use π\pi to define a topology on RP3\mathbb{RP}^{3}. We say that a set URP3U \subset \mathbb{RP}^{3} is open if and only if the inverse image π1(U)\pi^{-1}(U) is open in R4\mathbb{R}^{4}. In particular, we define the topology of RP3\mathbb{RP}^{3} to be the quotient topology induced by π\pi. The real projective space RP3\mathbb{RP}^{3} in conjunction with the quotient toplogy induced by π\pi is a topological space. The quotient topology automatically makes the surjection π\pi a continuous function.

Now we want to create a topological manifold out of RP3\mathbb{RP}^{3}. We need to define an atlas, then show that the charts in the atlas are homeomorphic to open subsets of R3{0}\mathbb{R}^{3} - \{ \mathbf{0} \}. Then we need to show that the resulting atlas makes RP3\mathbb{RP}^{3} locally Euclidean. That is, every point in RP3\mathbb{RP}^{3} has an open neighborhood homeomorphic to R3{0}\mathbb{R}^{3} - \{ \mathbf{0} \}. After that, we show that RP3\mathbb{RP}^{3} is Hausdorff and second countable. All of this together shows that RP3\mathbb{RP}^{3} is a topological 3-manifold.

For every i{0,1,2,3}i \in \{ 0, 1, 2, 3 \}, define the set UiU_{i} by

Ui={xR4{0}xi0}U_{i} = \{ \mathbf{x} \in \mathbb{R}^{4} - \{ \mathbf{0} \} \mid x_{i} \neq 0 \}

The set UiU_{i} is an open set in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. To prove this, we will show that UiU_{i} can be covered by open balls of elements in UiU_{i}. Suppose that pUi\mathbf{p} \in U_{i}. Let h=pe^i=pih = |\mathbf{p} \cdot \mathbf{\hat{e}}_{i}| = |p_{i}| be the distance of the point p\mathbf{p} from the hyperplane defined by xi=0x_{i} = 0. Let d=p=p0d = \Vert \mathbf{p} \Vert = \Vert \mathbf{p} - \mathbf{0} \Vert be the Euclidean norm of the vector p\mathbf{p}. Let r=min{d,h}r = \min \{ d, h \} and consider the open ball Br(p)B_{r}(\mathbf{p}) in R4\mathbb{R}^{4}. Choose qBr(p)\mathbf{q} \in B_{r}(\mathbf{p}). By the triangle inequality

qpqp>drdd2=d2>0.\Vert \mathbf{q} \Vert \geq \Vert \mathbf{p} \Vert - \Vert \mathbf{q} - \mathbf{p} \Vert > d - r \geq d - \frac{d}{2} = \frac{d}{2} > 0.

Hence qR4{0}\mathbf{q} \in \mathbb{R}^{4} - \{ \mathbf{0} \}. Since q\mathbf{q} was chosen arbitrarily, this implies that Br(p)R4{0}B_{r}(\mathbf{p}) \subset \mathbb{R}^{4} - \{ \mathbf{0} \}. Applying the triangle inequality again,

qipiqipi>hrhh2=h2>0.|q_{i}| \geq |p_{i}| - |q_{i} - p_{i}| > h - r \geq h - \frac{h}{2} = \frac{h}{2} > 0.

Thus q\mathbf{q} does not lie on the hyperplane defined by xi=0x_{i} = 0. Therefore qUi\mathbf{q} \in U_{i} implying that Br(p)UiB_{r}(\mathbf{p}) \subset U_{i}. Since the vector pUi\mathbf{p} \in U_{i} was arbitrary, every point in UiU_{i} lies in an open neighborhood that contains only elements of UiU_{i}, we see that

pUiBr(p)(p)=Ui.\bigcup_{\mathbf{p} \in U_{i}} B_{r(\mathbf{p})}(\mathbf{p}) = U_{i}.

The open balls constructed above cover UiU_{i} in open sets. Since R4\mathbb{R}^{4} is a topological space, and UiU_{i} is the union of open sets in the topology of R4\mathbb{R}^{4}, then UiU_{i} is an open set in R4\mathbb{R}^{4}. Moreover, since R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} is an open set in R4\mathbb{R}^{4}, the set UiU_{i} is an open set of R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} in the subspace topology that R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} inherits from R4\mathbb{R}^{4}.

Define the set ViRP3V_{i} \subset \mathbb{RP}^{3} by Vi=π(Ui)V_{i} = \pi\left(U_{i}\right). The set ViV_{i} is open in RP3\mathbb{RP}^{3}. To show this, observe the following equalities

π1(Vi)=π1(π(Ui))={pR4{0}π(p)Vi}={pR4{0}λR{0}such thatpλUi}=Ui\begin{align*} \pi^{-1}\left( V_{i} \right) &= \pi^{-1}\left( \pi\left( U_{i} \right) \right) \\ &= \{ \mathbf{p} \in \mathbb{R}^{4} - \{ \mathbf{0} \} \mid \pi\left( \mathbf{p} \right) \in V_{i} \} \\ &= \{ \mathbf{p} \in \mathbb{R}^{4} - \{ \mathbf{0} \} \mid \exists \lambda \in \mathbb{R} - \{ 0 \} \hspace{4 pt} \text{such that} \hspace{4 pt} \mathbf{p} \in \lambda U_{i} \} \\ &= U_{i} \end{align*}

where the last equality follows because the preimage of any element in ViV_{i} contains all nonzero multiples of an element of UiU_{i}, which are still an elements of UiU_{i}. Therefore, the set π1(Vi)\pi^{-1}(V_{i}) is an open set in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}, which makes ViV_{i} an open set in RP3\mathbb{RP}^{3} under the quotient topology.

For each i{0,1,2,3}i \in \{ 0, 1, 2, 3 \} define the map πi:UiVi\pi_{i} : U_{i} \rightarrow V_{i} by πi=πUi\pi_{i} = \pi|_{U_{i}}. Since the map πi\pi_{i} is the restriction of a continuous map, it is also a continuous map. It is surjective by definition, since the codomain is the image π(Ui)\pi(U_{i}). To show that πi\pi_{i} is a quotient map, we must prove that a subset WViW \subset V_{i} is open in ViV_{i} if and only if πi1(W)\pi^{-1}_{i}(W) is open in UiU_{i}. Suppose that WW is open in ViV_{i}. Then the inverse image of WW under π\pi is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. Since UiU_{i} is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} we see that πi1(W)=π1(W)Ui\pi^{-1}_{i}(W) = \pi^{-1}(W) \cap U_{i}. Since WW is open in ViV_{i}, there exists an open set XRP3X \subset \mathbb{RP}^{3} such that W=XViW = X \cap V_{i}. Since π\pi is continuous, π1(X)\pi^{-1}(X) is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}, which implies that π1(X)Ui\pi^{-1}(X) \cap U_{i} is open in UiU_{i}. But

π1(X)Ui=π1(XVi)Ui=π1(W)Ui=πi1(W)\pi^{-1}\left( X \right) \cap U_{i} = \pi^{-1}\left( X \cap V_{i} \right) \cap U_{i} = \pi^{-1}\left( W \right) \cap U_{i} = \pi^{-1}_{i}\left( W \right)

which is an open set in UiU_{i}. Thus πi1(W)\pi^{-1}_{i}(W) is an open set in UiU_{i}. This proves that if WViW \subset V_{i} is open, then π1(W)Ui\pi^{-1}(W) \subset U_{i} is open. Conversely, suppose that πi1(W)\pi^{-1}_{i}(W) is open in UiU_{i}. Since UiU_{i} is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}, there exists an open set XX of R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} such that πi1(W)=XUi\pi^{-1}_{i}(W) = X \cap U_{i}. Define the set X=X((R4{0})Ui)X^{\prime} = X \cup ((\mathbb{R}^{4} - \{ \mathbf{0} \}) - U_{i}). We show that the set XX^{\prime} is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. Suppose that q(R4{0})Ui\mathbf{q} \in (\mathbb{R}^{4} - \{ \mathbf{0} \}) - U_{i}. We can find a radius r>0r > 0 such that Br(q)B_{r}(\mathbf{q}) does not intersect UiU_{i} such that Br(q)Ui=B_{r}(\mathbf{q}) \cap U_{i} = \emptyset. Indeed, we can choose rr to be less than the distance to the nearest point where the ithi^{th} coordinate is zero, i.e. r<qir < |q_{i}|. Choose r=qi/2r = |q_{i}| / 2 for concreteness. With the chosen rr, we have Br(q)R4{0}UiB_{r}(\mathbf{q}) \subset \mathbb{R}^{4} - \{ \mathbf{0} \} - U_{i} for each qR4{0}Ui\mathbf{q} \in \mathbb{R}^{4} - \{ \mathbf{0} \} - U_{i}. This shows that R4{0}Ui\mathbb{R}^{4} - \{ \mathbf{0} \} - U_{i} is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. Since XX^{\prime} is the union of two open sets, it is also open. The set XX^{\prime} is open and saturated with respect to π\pi, so that image π(X)\pi(X^{\prime}) is open in RP3\mathbb{RP}^{3} because π\pi is a quotient map. We have

W=πi(πi1(W))=πi(XUi)=π(X)Vi.W = \pi_{i}(\pi^{-1}_{i}\left( W \right)) = \pi_{i}\left( X \cap U_{i} \right) = \pi\left( X^{\prime} \right) \cap V_{i}.

and it follows that πi1(W)\pi^{-1}_{i}(W) is open in R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. This demonstrates that πi\pi_{i} is a quotient map.

We show that each set ViV_{i} is homeomorphic to R4\mathbb{R}^{4}. For each i{0,1,2,3}i \in \{ 0, 1, 2, 3 \}, define the map Hi:ViRP3H_{i} : V_{i} \rightarrow \mathbb{RP}^{3} by

Hi([(P0P1Pi1PiPi+1P3)])=[(P0/PiP1/PiPi1/Pi1Pi+1/PiP3/Pi)].H_{i} \left( \begin{bmatrix} \begin{pmatrix} P_{0} \\ P_{1} \\ \vdots \\ P_{i - 1} \\ P_{i} \\ P_{i + 1} \\ \vdots \\ P_{3} \\ \end{pmatrix} \end{bmatrix} \right) = \begin{bmatrix} \begin{pmatrix} P_{0} / P_{i} \\ P_{1} / P_{i} \\ \vdots \\ P_{i-1} / P_{i} \\ 1 \\ P_{i+1} / {P_{i}} \\ \vdots \\ P_{3} / P_{i} \\ \end{pmatrix} \end{bmatrix}.

That is, the ithi^{th} coordinate is 1, and the rest are divided by PiP_{i}. This map sends a homogeneous point to the homogeneous point with the ithi^{th} coordinate normalized. Let WiW_{i} be the set of points in RP3\mathbb{RP}^{3} whose ithi^{th} coordinate is 1. Define the map proji:RP3WiR3\text{proj}_{i} : \mathbb{RP}^{3} \supset W_{i} \rightarrow \mathbb{R}^3 by

proji([(P0P1Pi11Pi+1P3)])=(P0P1Pi1Pi+1P3)\text{proj}_{i} \left( \begin{bmatrix} \begin{pmatrix} P_{0} \\ P_{1} \\ \vdots \\ P_{i-1} \\ 1 \\ P_{i+1} \\ \vdots \\ P_{3} \\ \end{pmatrix} \end{bmatrix} \right) = \begin{pmatrix} P_{0} \\ P_{1} \\ \vdots \\ P_{i-1} \\ P_{i+1} \\ \vdots \\ P_{3} \\ \end{pmatrix}

which maps the homogeneous point to a Euclidean point with the ithi^{th} component removed. The maps proji\text{proj}_{i} and HiH_{i} together allow us to define our coordinate maps. Define the map ψi:ViR3\psi_{i} : V_{i} \rightarrow \mathbb{R}^{3} by ψi=projiHi\psi_{i} = \text{proj}_{i} \circ H_{i}, written out as

ψi([(P0P1Pi1PiPi+1P3)])=(P0/PiP1/PiPi1/PiPi+1/PiP3/Pi).\psi_{i} \left( \begin{bmatrix} \begin{pmatrix} P_{0} \\ P_{1} \\ \vdots \\ P_{i - 1} \\ P_{i} \\ P_{i + 1} \\ \vdots \\ P_{3} \\ \end{pmatrix} \end{bmatrix} \right) = \begin{pmatrix} P_{0} / P_{i} \\ P_{1} / P_{i} \\ \vdots \\ P_{i-1} / P_{i} \\ P_{i+1} / {P_{i}} \\ \vdots \\ P_{3} / P_{i} \\ \end{pmatrix}.

Let φi:UiR3\varphi_{i} : U_{i} \rightarrow \mathbb{R}^{3} be given by φi=ψiπ\varphi_{i} = \psi_{i} \circ \pi, written out as

φi((P0P1Pi1PiPi+1P3))=(P0/PiP1/PiPi1/PiPi+1/PiP3/Pi).\varphi_{i} \left( \begin{pmatrix} P_{0} \\ P_{1} \\ \vdots \\ P_{i - 1} \\ P_{i} \\ P_{i + 1} \\ \vdots \\ P_{3} \\ \end{pmatrix} \right) = \begin{pmatrix} P_{0} / P_{i} \\ P_{1} / P_{i} \\ \vdots \\ P_{i-1} / P_{i} \\ P_{i+1} / {P_{i}} \\ \vdots \\ P_{3} / P_{i} \\ \end{pmatrix}.

The map φi\varphi_{i} is continuous by the universal property of product spaces applied to R4\mathbb{R}^{4}. Since the map φi\varphi_{i} is continuous, the universal property of quotient maps implies that the map ψi\psi_{i} is continuous. We must show that ψi\psi_{i} is bijective. Let’s prove surjectivity: let (P0 P1  Pi1 Pi+1 P3)TR3\begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ P_{i+1} \ \dots & P_{3} \end{pmatrix}^{T} \in \mathbb{R}^{3}, let [(P0 P1  Pi1 1 Pi+1 P3)]TVi\begin{bmatrix} \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ 1 \ P_{i+1} \dots \ P_{3} \end{pmatrix} \end{bmatrix}^{T} \in V_{i}, From the definition of ψi\psi_{i}, we see that

ψi([(P0 P1  Pi1 1 Pi+1  P3 )]T)=(P0 P1  Pi1 Pi+1  P3 )T.\psi_{i} \left( \begin{bmatrix} \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i - 1} \ 1 \ P_{i + 1} \ \dots \ P_{3} \ \end{pmatrix} \end{bmatrix}^{T} \right) = \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ P_{i+1} \ \dots \ P_{3} \ \end{pmatrix}^{T}.

which establishes surjectivity. To show injectivity, we require the following fact: every element in ViV_{i} has a unique representative whose ithi^{th} coordinate is 1. To see this, suppose that [Q][Q] is a homogeneous point in ViV_{i} with representatives (Q0 Q1  Qi1 1 Qi+1 Q3)TR3\begin{pmatrix} Q_{0} \ Q_{1} \ \dots \ Q_{i-1} \ 1 \ Q_{i+1} \dots \ Q_{3} \end{pmatrix}^{T} \in \mathbb{R}^{3} and (Q0 Q1  Qi1 1 Qi+1 Q3)TR3\begin{pmatrix} Q^{\prime}_{0} \ Q^{\prime}_{1} \ \dots \ Q^{\prime}_{i-1} \ 1 \ Q^{\prime}_{i+1} \dots \ Q^{\prime}_{3} \end{pmatrix}^{T} \in \mathbb{R}^{3} where the ithi^{th} component is 1. Since both representatives represent the same point, they must be equivalent, i.e. there exists λR{0}\lambda \in \mathbb{R} - \{0\} such that

(Q0 Q1  Qi1 1 Qi+1 Q3)T=λ(Q0 Q1  Qi1 1 Qi+1 Q3)T.\begin{pmatrix} Q_{0} \ Q_{1} \ \dots \ Q_{i-1} \ 1 \ Q_{i+1} \dots \ Q_{3} \end{pmatrix}^{T} = \lambda \begin{pmatrix} Q^{\prime}_{0} \ Q^{\prime}_{1} \ \dots \ Q^{\prime}_{i-1} \ 1 \ Q^{\prime}_{i+1} \dots \ Q^{\prime}_{3} \end{pmatrix}^{T}.

The fact that the ithi^{th} component is 1 in both representatives implies that Qj=QjQ^{\prime}_{j} = Q_{j} for each j{0,1,2,3}j \in \{ 0, 1, 2, 3 \}. Therefore

(Q0 Q1  Qi1 1 Qi+1 Q3)T=(Q0 Q1  Qi1 1 Qi+1 Q3)T.\begin{pmatrix} Q_{0} \ Q_{1} \ \dots \ Q_{i-1} \ 1 \ Q_{i+1} \dots \ Q_{3} \end{pmatrix}^{T} = \begin{pmatrix} Q^{\prime}_{0} \ Q^{\prime}_{1} \ \dots \ Q^{\prime}_{i-1} \ 1 \ Q^{\prime}_{i+1} \dots \ Q^{\prime}_{3} \end{pmatrix}^{T}.

establishing uniqueness of the representative of [Q][Q] whose ithi^{th} component is 1. Proving the injectivity of ψi\psi_{i} becomes easy. Recall the original definition of ψi\psi_{i} as ψi=projiHi\psi_{i} = \text{proj}_{i} \circ H_{i}. Since a given homogeneous point has a unique representative whose ithi^{th} component is 1, the normalization map HiH_{i} is injective. That is, given homogeneous points [Q][Q] and [Q][Q^{\prime}] with Hi([Q])=Hi([Q])H_{i}([Q]) = H_{i}([Q^{\prime}]), we conclude [Q]=[Q][Q] = [Q^{\prime}]. Also, notice that proji\text{proj}_{i} is bijective with inverse map proji1:R3RP3\text{proj}^{-1}_{i} : \mathbb{R}^{3} \rightarrow \mathbb{RP}^{3} defined by

proji1((P0 P1  Pi1 Pi+1  P3 )T)=[(P0 P1  Pi1 1 Pi+1  P3 )T].\text{proj}^{-1}_{i} \left( \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ P_{i+1} \ \dots \ P_{3} \ \end{pmatrix}^{T} \right) = \begin{bmatrix} \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ 1 \ P_{i+1} \ \dots \ P_{3} \ \end{pmatrix}^{T} \end{bmatrix}.

Since proji\text{proj}_{i} is bijective, it is injective, and since HiH_{i} is injective, so is their composite ψi\psi_{i}. This proves that ψi\psi_{i} is bijective.

Next, we show that ψi1\psi^{-1}_{i} is continuous. Consider the map ρi:R3R4{0}\rho_{i} : \mathbb{R}^{3} \rightarrow \mathbb{R}^{4} - \{ \mathbf{0} \} given by

ρi((P0 P1  Pi1 Pi+1  P3 )T)=(P0 P1  Pi1 1 Pi+1  P3 )T.\rho_{i} \left( \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ P_{i+1} \ \dots \ P_{3} \ \end{pmatrix}^{T} \right) = \begin{pmatrix} P_{0} \ P_{1} \ \dots \ P_{i-1} \ 1 \ P_{i+1} \ \dots \ P_{3} \ \end{pmatrix}^{T}.

The map ρi\rho_{i} is continuous, its image is contained in ViV_{i}, and πiρi=ψi1\pi_{i} \circ \rho_{i} = \psi^{-1}_{i}. This implies that ψi1\psi^{-1}_{i} is continuous, since it is the composite of continuous functions. We have shown that ψi\psi_{i} is continuous, bijective, and has a continuous inverse. Therefore, it is a homeomorphism. Moreover, we can cover RP3\mathbb{RP}^{3} with the charts {(Vi,ψi)i{0,1,2,3}}\{ (V_{i}, \psi_{i}) \mid i \in \{ 0, 1, 2, 3 \} \}, which means that RP3\mathbb{RP}^{3} is locally Euclidean.

We show that RP3\mathbb{RP}^{3} is Hausdorff. Suppose that [P][P] and [Q][Q] are two distinct points in RP3\mathbb{RP}^{3}. There are two possibilities: there is an 0i20 \leq i \leq 2 such that both points lie in ViV_{i}, or no such ii exists such that both points lie in ViV_{i}. In the first case, ψi([P])\psi_{i}([P]) and ψi([Q])\psi_{i}([Q]) are distinct points in R3\mathbb{R}^{3}. Since R3\mathbb{R}^{3} is Hausdorff, there exist disjoint sets AA and BB such that ψi([P])A\psi_{i}([P]) \in A and ψi([Q])B\psi_{i}([Q]) \in B. Hence, ψi1(A)\psi^{-1}_{i}(A) and ψi1\psi^{-1}_{i} are disjoint open subsets of ViV_{i}, and hence ψi1(A)\psi^{-1}_{i}(A) and ψi1\psi^{-1}_{i} are open subsets of RP3\mathbb{RP}^{3}. This yields the first case. Consider the second case. Suppose that no such ii exists such that ψi([P])\psi_{i}([P]) and ψi([Q])\psi_{i}([Q]) are distinct points in ViV_{i}. Let (x0,x1,x2,x3)(x_{0}, x_{1}, x_{2}, x_{3}) be a representative of [P][P] and let (y0,y1,y2,y3)(y_{0}, y_{1}, y_{2}, y_{3}) be a representative of [Q][Q]. There exists iji \neq j or 0i,j30 \leq i, j \leq 3 such that xi0,yi=0x_{i} \neq 0, y_{i} = 0 and xj=0,yj0x_{j} = 0, y_{j} \neq 0. Choose a representative such that xi=1x_{i} = 1 and yj=1y_{j} = 1. Assume without loss of generality that i<ji < j, and choose 0<ϵ<10 < \epsilon < 1. The set

A={(a0 a1 ai1 1 ai+1a3)Tkiakxk<ϵ}ViA = \{ \begin{pmatrix} a_{0} \ a_{1} \ \dots a_{i-1} \ 1 \ a_{i + 1} \dots a_{3} \end{pmatrix}^{T} \mid \forall k \neq i \hspace{4 pt} \lvert a_{k} - x_{k} \rvert < \epsilon \} \subset V_{i}

is an open set containing [P][P] and the set

B={(b0 b1 bj1 1 bj+1b3)Tkibkyk<ϵ}VjB = \{ \begin{pmatrix} b_{0} \ b_{1} \ \dots b_{j-1} \ 1 \ b_{j + 1} \dots b_{3} \end{pmatrix}^{T} \mid \forall k \neq i \hspace{4 pt} \lvert b_{k} - y_{k} \rvert < \epsilon \} \subset V_{j}

is an open set containing [Q][Q]. The image ψi(A)\psi_{i}(A) is an open rectangle in R3\mathbb{R}^{3} centered on ψi([P])\psi_{i}([P]) with a side length of 2ϵ2 \epsilon. Similarly, the image ψi(B)\psi_{i}(B) is an open rectangle in R3\mathbb{R}^{3} centered on ψi([Q])\psi_{i}([Q]) with a side length of 2ϵ2 \epsilon. The sets AA and BB are disjoint. To show this, suppose AA and BB are not disjoint. Then for (a0 a1 ai1 1 ai+1a3)T=(b0 b1 bj1 1 bj+1b3)T\begin{pmatrix} a_{0} \ a_{1} \ \dots a_{i-1} \ 1 \ a_{i + 1} \dots a_{3} \end{pmatrix}^{T} = \begin{pmatrix} b_{0} \ b_{1} \ \dots b_{j-1} \ 1 \ b_{j + 1} \dots b_{3} \end{pmatrix}^{T} we must have aj0a_{j} \neq 0 and bi0b_{i} \neq 0 which implies that ajbi=1a_{j} b_{i} = 1. But this is impossible, because aj<1\lvert a_{j} \rvert < 1 and bi<1\lvert b_{i} \rvert < 1. Therefore, the sets AA and BB must be disjoint. This proves that RP3\mathbb{RP}^{3} is Hausdorff.

Finally, second countability follows from the fact that R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \} is second countable. More precisely, let B\mathcal{B} be a countable base for the topology on R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}. The set

B={π(U)UB}\mathcal{B}^{\prime} = \{ \pi\left( U \right) \mid U \in \mathcal{B} \}

is a countable set of open sets in RP3\mathbb{RP}^{3} because π\pi is saturated. Since π\pi is surjective, BBB=RP3\cup_{B \in \mathcal{B}^{\prime}} B = \mathbb{RP}^{3}, i.e. the set B\mathcal{B}^{\prime} covers RP3\mathbb{RP}^{3}. Hence RP3\mathbb{RP}^{3} is second countable. Note that second countability implies that RP3\mathbb{RP}^{3} is compact. We sketch a proof here. It comes from the fact that the 3-sphere S3S^{3} is a compact subset of R4\mathbb{R}^{4}, that the canonical surjection πS3\pi_{S^{3}} is continuous, and that the image of a compact set by a continuous map is compact. Since πS3(S3)\pi_{S^{3}}(S^{3}) is compact, and πS3(S3)=RP3\pi_{S^{3}}(S^{3}) = \mathbb{RP}^{3} we immediately infer that RP3\mathbb{RP}^{3} is compact.

We have topologized real projective space, and proven that RP3\mathbb{RP}^{3} is second countable, Hausdorff and locally Euclidean. Therefore RP3\mathbb{RP}^{3} is a topological 3-manifold (or we just say that it is a 3-manifold, or a manifold). Finally, RP3\mathbb{RP}^{3} is compact, so it is a nice setting to work with topologically.

Representing Transformations In Real Projective Space

Any orthonormal frame (O~frame,(u^h,u^v,u^d))(\tilde{O}_{frame}, \left( \mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d} \right)) on E3\mathbb{E}^{3} induces a coordinate chart as follows. A point P~E3\tilde{P} \in \mathbb{E}^{3} is written as

P~=O~frame+Phu^h+Pvu^v+Pdu^d\tilde{P} = \tilde{O}_{frame} + P_{h} \mathbf{\hat{u}}_{h} + P_{v} \mathbf{\hat{u}}_{v} + P_{d} \mathbf{\hat{u}}_{d}

and the orthonormal frame (O~frame,(u^h,u^v,u^d))(\tilde{O}_{frame}, \left( \mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d} \right)) defines a coordinate chart φframe:E3R3\varphi_{frame} : \mathbb{E}^{3} \rightarrow \mathbb{R}^{3} by φframe(P~)=P~O~\varphi_{frame}( \tilde{P} ) = \tilde{P} - \tilde{O}. Written out

P=φframe(P~)P~O~frame=Phu^h+Pvu^v+Pdu^dP = \varphi_{frame}(\tilde{P}) \equiv \tilde{P} - \tilde{O}_{frame} = P_{h} \mathbf{\hat{u}}_{h} + P_{v} \mathbf{\hat{u}}_{v} + P_{d} \mathbf{\hat{u}}_{d}

is the representation of P~\tilde{P} in R3\mathbb{R}^{3}. Also, the coordinate chart φframe\varphi_{frame} maps the origin O~frame\tilde{O}_{frame} of the view coordinate system in E3\mathbb{E}^{3} to 0\mathbf{0}: OframeO_{frame} = φframe(O~frame)=O~frameO~frame=0\varphi_{frame}(\tilde{O}_{frame}) = \tilde{O}_{frame} - \tilde{O}_{frame} = \mathbf{0}. This shows that the view space frame origin in E3\mathbb{E}^{3} indeed maps to the vector space origin 0\mathbf{0} in R3\mathbb{R}^{3}.

Recall that the definition of real projective space defines the manifold structure using the surjection π:R4{0}RP3\pi : \mathbb{R}^{4} - \{\mathbf{0}\} \rightarrow \mathbb{RP}^{3} given by

π((Pw))=[(Pw)]\pi\left( \begin{pmatrix} P \\ w \\ \end{pmatrix} \right) = \begin{bmatrix} \begin{pmatrix} P \\ w \\ \end{pmatrix} \end{bmatrix}

where [.][.] on the right-hand side indicates the equivalence class of (PT,w)T\begin{pmatrix} P^{T}, w \end{pmatrix}^{T}.

Define a map ρ:R3R4{0}\rho : \mathbb{R}^{3} \rightarrow \mathbb{R}^{4} - \{\mathbf{0}\} by

ρ(P)=(P1)\rho\left( P \right) = \begin{pmatrix} P \\ 1 \\ \end{pmatrix}

The maps π\pi and ρ\rho together allow us to map from view space to projective view space with the camera orthonormal frame by

(πρ)(P)=π(ρ(P))=π((P1))=[(P1)].\left(\pi \circ \rho\right)\left(P\right) = \pi\left( \rho\left( P \right) \right) = \pi\left( \begin{pmatrix} P \\ 1 \\ \end{pmatrix} \right) = \begin{bmatrix} \begin{pmatrix} P \\ 1 \\ \end{pmatrix} \end{bmatrix}.

The map ρ\rho defines an embedding (injection) of R3\mathbb{R}^{3} into R4{0}\mathbb{R}^{4} - \{ \mathbf{0} \}, because each element in ρ(R3)\rho(\mathbb{R}^{3}) has a unique elements PR3P \in \mathbb{R}^{3} such that ρ(P)=(PT 1)T\rho(P) = \begin{pmatrix} P^{T} \ 1 \end{pmatrix}^{T}. Since ρ\rho is surjective on its image, injective, and continuous with continuous inverse, it is a homeomorphism on its image, hence an embedding. Since every element of R3\mathbb{R}^{3} has a unique homogeneous point QQ such that Q=[(PT 1)T]Q = [\begin{pmatrix} P^{T} \ 1 \end{pmatrix}^{T}], the map πρ\pi \circ \rho is also an embedding. The set π(ρ(R3))\pi(\rho(\mathbb{R}^{3})) is sometimes called the affine patch or Euclidean patch of RP3\mathbb{RP}^{3}.

We can lift points in E3\mathbb{E}^{3} into RP3\mathbb{RP}^{3}. Let’s do the same for transformations. Suppose that A:R3R3A : \mathbb{R}^{3} \rightarrow \mathbb{R}^{3} is an affine map. We define the lifted map of AA over to RP3\mathbb{RP}^{3} to be the map A^:RP3RP3\hat{A} : \mathbb{RP}^{3} \rightarrow \mathbb{RP}^{3} such that

(ρA)(P)=(A^ρ)(P).\left( \rho \circ A \right)\left( P \right) = \left( \hat{A} \circ \rho \right) \begin{pmatrix} P \end{pmatrix}.

Recall that an affine map has the form A(P)=L(P)+tA(P) = L(P) + \mathbf{t} where L:R3R3L : \mathbb{R}^{3} \rightarrow \mathbb{R}^{3} is a linear map, and t\mathbf{t} is a vector, i.e. a linear map plus a translation term. Expanding this out, the left-hand side of (27) becomes

(ρA)(P)=(A(P)1)=(L(P)+t1)=[Lt0T1](P1)\left( \rho \circ A \right)\left( P \right) = \begin{pmatrix} A\left( P \right) \\ 1 \\ \end{pmatrix} = \begin{pmatrix} L\left( P \right) + \mathbf{t} \\ 1 \\ \end{pmatrix} = \begin{bmatrix} L & \mathbf{t} \\ \mathbf{0}^{T} & 1 \\ \end{bmatrix} \begin{pmatrix} P \\ 1 \\ \end{pmatrix}

and on the right-hand side we have

(A^ρ)(P)=A^(ρ(P))=A^((P1)).\left( \hat{A} \circ \rho \right) \left( P \right) = \hat{A} \left(\rho \left( P \right) \right) = \hat{A} \left( \begin{pmatrix} P \\ 1 \\ \end{pmatrix} \right).

Equating both sides of (27) we have

A^((P1))=[Lt0T1](P1)\hat{A} \left( \begin{pmatrix} P \\ 1 \\ \end{pmatrix} \right) = \begin{bmatrix} L & \mathbf{t} \\ \mathbf{0}^{T} & 1 \\ \end{bmatrix} \begin{pmatrix} P \\ 1 \\ \end{pmatrix}

or

A^=[Lt0T1]\hat{A} = \begin{bmatrix} L & \mathbf{t} \\ \mathbf{0}^{T} & 1 \\ \end{bmatrix}

so that A^\hat{A} is unique. An affine map in R3\mathbb{R}^{3} becomes a linear map in RP3\mathbb{RP}^{3}. In the case of a linear map LL, t=0\mathbf{t} = \mathbf{0} and

L^=[L00T1].\hat{L} = \begin{bmatrix} L & \mathbf{0} \\ \mathbf{0}^{T} & 1 \\ \end{bmatrix}.

Now suppose that T:R3R3T : \mathbb{R}^{3} \rightarrow \mathbb{R}^{3} is a projective transformation. A projective transformation is a map of the form

T(P)=(1g(P))A(P)=(1g(P))(L(P)+t)T \left( P \right) = \left( \frac{1}{g(P)} \right) A \left( P \right) = \left( \frac{1}{g(P)} \right) \left( L(P) + \mathbf{t} \right)

where AA is an affine map and g:R3Rg : \mathbb{R}^{3} \rightarrow \mathbb{R} is an affine scalar function. This means that gg has the form g(P)=cP+hg(P) = \mathbf{c} \cdot P + h. We define the lifted map of TT over to RP3\mathbb{RP}^{3} to be the map T^:RP3RP3\hat{T} : \mathbb{RP}^{3} \rightarrow \mathbb{RP}^{3} such that

g(P)(ρT)(P)=(T^ρ)(P)g\left( P \right) \left( \rho \circ T \right) \left( P \right) = \left( \hat{T} \circ \rho \right) \left( P \right)

Expanding out the right-hand side of (34)

(T^ρ)(P)=T^(ρ(P))=T^(P1).\left( \hat{T} \circ \rho \right) \left( P \right) = \hat{T} \left( \rho \left( P \right) \right) = \hat{T} \begin{pmatrix} P \\ 1 \end{pmatrix}.

More interestingly, expanding out the left-hand side of (34) gives

g(P)(ρT)(P)=g(P)(T(P)1)=(g(P)T(P)g(P))=(A(P)g(P))=(L(P)+tg(P))=(L(P)+tcP+h)=[LtcTh](P1)\begin{align*} g\left( P \right) \left( \rho \circ T \right) \left( P \right) &= g\left( P \right) \begin{pmatrix} T(P) \\ 1 \end{pmatrix} \\ &= \begin{pmatrix} g\left( P \right) T(P) \\ g\left( P \right) \end{pmatrix} \\ &= \begin{pmatrix} A(P) \\ g\left( P \right) \end{pmatrix} \\ &= \begin{pmatrix} L(P) + \mathbf{t} \\ g\left( P \right) \end{pmatrix} \\ &= \begin{pmatrix} L(P) + \mathbf{t} \\ \mathbf{c} \cdot P + h \end{pmatrix} \\ &= \begin{bmatrix} L & \mathbf{t} \\ \mathbf{c}^{T} & h \\ \end{bmatrix} \begin{pmatrix} P \\ 1 \\ \end{pmatrix} \end{align*}

where the third equality follows from the definition of the projective transformation. Combining (35) and (36) back into (34) yields

T^(P1)=[LtcTh](P1)\hat{T} \begin{pmatrix} P \\ 1 \end{pmatrix} = \begin{bmatrix} L & \mathbf{t} \\ \mathbf{c}^{T} & h \\ \end{bmatrix} \begin{pmatrix} P \\ 1 \\ \end{pmatrix}

and therefore

T^=[LtcTh].\hat{T} = \begin{bmatrix} L & \mathbf{t} \\ \mathbf{c}^{T} & h \\ \end{bmatrix}.

This is a unique representation of the projective transformation TT lifted over to RP3\mathbb{RP}^{3}. Here is a wonderful discovery: in RP3\mathbb{RP}^{3} where all coordinate scales are treated as equivalent, we can work with linear, affine, and projective transformations in a unified setting by going one dimension higher in our representation from T:R3R3T : \mathbb{R}^{3} \rightarrow \mathbb{R}^{3} to its lifted counterpart T^:RP3RP3\hat{T} : \mathbb{RP}^{3} \rightarrow \mathbb{RP}^{3}.

The punchline is that we can lift the Euclidean space E3\mathbb{E}^{3} into real projective space, in such a way that each point in E3\mathbb{E}^{3} has a corresponding unique point in the affine subspace of RP3\mathbb{RP}^{3} under any coordinate chart. This lift allows us to construct our projections between different coordinate systems in real projective space in a coherent and well-defined manner. Via the embedding πρ\pi \circ \rho, the manifold structure of RP3\mathbb{RP}^{3} allows us to scale our coordinates in any way we like, because in projective coordinates we don’t care about scaling. We can also lift transformations from E3\mathbb{E}^{3} to RP3\mathbb{RP}^{3} as a consequence of the embedding πρ\pi \circ \rho too. This setting makes it convenient to construct perspective and orthographic projections, because at the end, we are back in the affine portion of RP3\mathbb{RP}^{3} after normalization, so we can map back out of RP3\mathbb{RP}^{3} again by choosing a chart on RP3\mathbb{RP}^{3} and applying it.

We have shown how to map Euclidean space to real projective space, and how to represent linear, affine, and projective transformations as linear transformations in linear projective space. It remains to apply these developments to our primary goal: constructing orthographic and perspective projection matrices in homogeneous coordinates.

Specifying Projection Matrices

To define a projection matrix, we need two coordinate systems: the view coordinate system, and the normalized device coordinate system. The view coordinate system is where the view volume is defined. The normalized device coordinate system is where the canonical view volume is defined. The task of the projection transformation is to map the view volume to the canonical view volume.

To understand what the projection matrices do, we must understand the coordinate systems that we map between at each step in the pipeline leading from the view space to the canonical view volume. The transformations stem from choosing a convenient coordinate system in which to render computer graphics. The convenient coordinate system we choose is often called normalized device coordinates, defined in the following. The canonical coordinate system differs from platform to platform. The other coordinates systems exist to articulate a clear path from projective view coordinates to normalized device coordinates. First we must define the view space and the view coordinates.

The view coordinate system for Euclidean space E3\mathbb{E}^{3} is given by the orthonormal frame (O~view,Bview)(\tilde{O}_{view}, \mathcal{B}_{view}) where (1) the origin of the orthonormal frame is the point O~viewE3\tilde{O}_{view} \in \mathbb{E}^{3}; (2) the basis of the orthonormal frame is Bview=(u^h,u^v,u^d)\mathcal{B}_{view} = (\mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d}) where the basis vector u^h\mathbf{\hat{u}}_{h} points to the right, the basis vector u^v\mathbf{\hat{u}}_{v} points up, and the basis vector u^d\mathbf{\hat{u}}_{d} points into the view volume or out of the view volume, depending on the choice of orientation; (3) the view volume in this coordinate system is called the view volume (or in the case of perspective projection, the perspective view volume).

The projected coordinate system for Euclidean space E3\mathbb{E}^{3} is given by the orthonormal frame (O~proj,Bproj)(\tilde{O}_{proj}, \mathcal{B}_{proj}) where (1) the origin of the orthonormal frame is the point O~projE3\tilde{O}_{proj} \in \mathbb{E}^{3}; (2) the basis of the orthonormal frame is Bproj=(u^proj,h,u^proj,v,u^proj,d)\mathcal{B}_{proj} = (\mathbf{\hat{u}}_{proj,h}, \mathbf{\hat{u}}_{proj,v}, \mathbf{\hat{u}}_{proj,d}) where the basis vector u^proj,h\mathbf{\hat{u}}_{proj,h} points to the right, the basis vector u^proj,v\mathbf{\hat{u}}_{proj,v} points up, and the basis vector u^proj,d\mathbf{\hat{u}}_{proj,d} points into the view volume or out of the view volume, depending on the choice of orientation; (3) the view volume in this coordinate system is called the projected view volume (or in the case of perspective projection, the perspective projected view volume).

The clip coordinate system for Euclidean space E3\mathbb{E}^{3} is given by the orthonormal frame (O~clip,Bclip)(\tilde{O}_{clip}, \mathcal{B}_{clip}) defined on E3\mathbb{E}^{3} where (1) the origin of the orthonormal frame (O~clip,Bclip)(\tilde{O}_{clip}, \mathcal{B}_{clip}) is the point O~clipE3\tilde{O}_{clip} \in \mathbb{E}^{3}; (2) the basis of the orthonormal frame is Bclip=(u^clip,h,u^clip,v,u^clip,d)\mathcal{B}_{clip} = (\mathbf{\hat{u}}_{clip,h}, \mathbf{\hat{u}}_{clip,v}, \mathbf{\hat{u}}_{clip,d}) where the basis vector u^clip,h\mathbf{\hat{u}}_{clip,h} points to the right, the basis vector u^clip,v\mathbf{\hat{u}}_{clip,v} points up, and the basis vector u^clip,d\mathbf{\hat{u}}_{clip,d} points into the view volume, or out of the view volume depending on the choice or orientation; (3) the view volume in this coordinate system is called the orthographic view volume.

The normalized device coordinate system for Euclidean space E3\mathbb{E}^{3} is given by the orthonormal frame (O~ndc,Bndc)(\tilde{O}_{ndc}, \mathcal{B}_{ndc}) defined on E3\mathbb{E}^{3} where (1) The origin of the orthonormal frame (O~ndc,Bndc)(\tilde{O}_{ndc}, \mathcal{B}_{ndc}) is the point O~ndcE3\tilde{O}_{ndc} \in \mathbb{E}^{3}; (2) The basis of the orthonormal frame is Bndc=(u^ndc,h,u^ndc,v,u^ndc,d)\mathcal{B}_{ndc} = (\mathbf{\hat{u}}_{ndc,h}, \mathbf{\hat{u}}_{ndc,v}, \mathbf{\hat{u}}_{ndc,d}) where the basis vector u^ndc,h\mathbf{\hat{u}}_{ndc,h} points to the right, the basis vector u^ndc,v\mathbf{\hat{u}}_{ndc,v} points up, and the basis vector u^ndc,d\mathbf{\hat{u}}_{ndc,d} points into the view volume, or out of the view volume depending on the choice or orientation; (3) The view volume in this coordinate system is called the canonical view volume.

The view coordinate system, projected coordinate system, clip coordinate system, and normalized device coordinate system induce coordinate charts via φview(P~)=P~O~view\varphi_{view}(\tilde{P}) = \tilde{P} - \tilde{O}_{view}, φproj(P~)=P~O~proj\varphi_{proj}(\tilde{P}) = \tilde{P} - \tilde{O}_{proj}, φclip(P~)=P~O~clip\varphi_{clip}(\tilde{P}) = \tilde{P} - \tilde{O}_{clip}, and φndc(P~)=P~O~ndc\varphi_{ndc}(\tilde{P}) = \tilde{P} - \tilde{O}_{ndc}, respectively.

The projection transformations are parametrized by two set of parameters. The first one is the view volume parameters ll, rr, bb, tt, nn, ff where l>0l > 0, r>0r > 0, b>0b > 0, t>0t > 0, and f>n>0f > n > 0 such that the view volume is parametrized by [l,r]×[b,t]×[n,f][-l, r] \times [-b, t] \times [n, f]. The second one is the canonical view volume parametrized by [αmin,αmax]×[βmin,βmax]×[γmin,γmax][\alpha_{min}, \alpha_{max}] \times [\beta_{min}, \beta_{max}] \times [\gamma_{min}, \gamma_{max}]. where αmax>αmin\alpha_{max} > \alpha_{min}, βmax>βmin\beta_{max} > \beta_{min}, and γmax>γmin\gamma_{max} > \gamma_{min}.

The Canonical Projection Matrices

In this section, we construct the canonical projection matrices. We call them canonical because each of the projections has the same output coordinate system as the input coordinate system. So it is particularly convenient to work with.

The Canonical Coordinate System

We choose a canonical set of coordinate systems to construct the canonical projective transformations that will be used to derive the projective transformations in specific settings.

The canonical view coordinates is the view space coordinate system with orthonormal frame (O~view,Bview)(\tilde{O}_{view}, \mathcal{B}_{view}) where Bview=(u^h,u^v,u^d)\mathcal{B}_{view} = (\mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d}) such that the depth frame vector u^d\mathbf{\hat{u}}_{d} points into the view volume. This gives the canonical view space a left-handed orientation. The canonical projected coordinates coordinate system is the projected coordinate system with the same orthonormal frame as the canonical view coordinates. The canonical clip coordinates coordinate system is the clip coordinate system with the same orthonormal frame as the canonical view coordinate system. The canonical normalized device coordinates coordinate system is the normalized device coordinate system with the same orthonormal frame as in canonical view coordinates. In particular, each coordinate system uses the same orthonormal frame, and has a left-handed orientation.

It is not strictly required that each space have the same orthonormal frame, but using the same coordinate system in each step makes it easier to see what is going on in the transformation pipeline. Since we derive each transformation between the coordinate systems above, we can always transform any one of them with a combination of orthogonal transformations and changes of orientation to get the desired ones. It is also much less error-prone with fewer pesky signs to deal with.

The Canonical Perspective Projection Matrix

With these considerations, we construct the canonical perspective projection matrix for the frame (O~view,(u^h,u^v,u^d))(\tilde{O}_{view}, (\mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d})) with the perspective view volume parametrized by [l,r]×[b,t]×[n,f][-l, r] \times [-b, t] \times [n, f] and the canonical view volume parametrized by [αmin,αmax]×[βmin,βmax]×[γmin,γmax][\alpha_{min}, \alpha_{max}] \times [\beta_{min}, \beta_{max}] \times [\gamma_{min}, \gamma_{max}]. Let PR3P \in \mathbb{R}^{3} be a point given by P=Phu^h+Pvu^v+Pdu^dP = P_{h} \mathbf{\hat{u}}_{h} + P_{v} \mathbf{\hat{u}}_{v} + P_{d} \mathbf{\hat{u}}_{d}. We derive the perspective projected horizontal and vertical components.

Using similar triangles for the horizontal component, we have

PhPd=Pu^hPu^d=Pproju^hn=Pproj,hn\frac{P_{h}}{P_{d}} = \frac{P \cdot \mathbf{\hat{u}}_{h}}{P \cdot \mathbf{\hat{u}}_{d}} = \frac{P^{\prime}_{proj} \cdot \mathbf{\hat{u}}_{h}}{n} = \frac{P^{\prime}_{proj,h}}{n}

which yields

Pproj,h=nPh(1Pd).P^{\prime}_{proj,h} = n P_{h} \left( \frac{1}{P_{d}} \right).

Analagously for the vertical component, applying similar triangles gives us

PvPd=Pu^vPu^d=Pproju^vn=Pproj,vn\frac{P_{v}}{P_{d}} = \frac{P \cdot \mathbf{\hat{u}}_{v}}{P \cdot \mathbf{\hat{u}}_{d}} = \frac{P^{\prime}_{proj} \cdot \mathbf{\hat{u}}_{v}}{n} = \frac{P^{\prime}_{proj,v}}{n}

implying that

Pproj,v=nPv(1Pd).P^{\prime}_{proj,v} = n P_{v} \left( \frac{1}{P_{d}} \right).

Observe that the horizontal and vertical components both transform as projective transformations. Indeed, the perspective projection transformation is a projective transformation where the affine function is given by PdP_{d}. In other words, the perspective projection is dividing by depth. Using our reasoning about representing projective transformations that lead to the matrix representation (38), we can deduce the lifted mapping by rearranging the perspective equations

PdPproj,h=nPhPdPproj,v=nPvP_{d} P^{\prime}_{proj,h} = n P_{h} \\ P_{d} P^{\prime}_{proj,v} = n P_{v} \\

suggestively. The right hand side in both cases are affine transformations. This suggests to form of the transformation for the depth component. We define our projected coordinate system components as follows. Let Pproj,h=PdPproj,hP_{proj,h} = P_{d} P^{\prime}_{proj,h} and Pproj,v=PdPproj,vP_{proj,v} = P_{d} P^{\prime}_{proj,v}. Since the affine scalar function is perspective division, we immediately see that Pproj,w=PdP_{proj,w} = P_{d}. This leaves the depth component. The depth component does not directly participate in depth normalization, and since our coordinate system is orthogonal, so Pproj,dP_{proj,d} cannot depend on PhP_{h} or PvP_{v}. This implies that Pproj,dP_{proj,d} must be a function of PdP_{d} and PwP_{w}. Since the transformation is projective, the depth component must transform affinely. Since Pw=1P_{w} = 1. This leaves

Pproj,d=θ(Pd)=APd+B.P_{proj,d} = \theta \left( P_{d} \right) = A^{\prime} P_{d} + B^{\prime}.

Taken together, the projected coordinates components of the perspective transformation are

Pproj,h=nPhPproj,v=nPvPproj,d=θ(Pd)=APd+BPproj,w=Pd\begin{align*} P_{proj,h} &= n P_{h} \\ P_{proj,v} &= n P_{v} \\ P_{proj,d} &= \theta \left ( P_{d} \right) = A^{\prime} P_{d} + B^{\prime} \\ P_{proj,w} &= P_{d} \\ \end{align*}

where we solve for the constants AA^{\prime} and BB^{\prime} later.

After projection, we must map the projected coordinates to clip coordinates. To obtain the right clip coordinates, we need to consider normalized device coordinates. This is necessary since the mapping from projected coordinates to clip coordinates depends on the choice of parametrization of the canonical view volume. The resulting transformation is an orthographic transformation that maps the orthographic view volume [l,r]×[b,t]×[n,f][-l, r] \times [-b, t] \times [n, f] to the canonical view volume [αmin,αmax]×[βmin,βmax]×[γmin,γmax][\alpha_{min}, \alpha_{max}] \times [\beta_{min}, \beta_{max}] \times [\gamma_{min}, \gamma_{max}]. The map from projected coordinates to clip coordinates is a linear map in RP3\mathbb{RP}^{3}, so the coordinates must transform affinely.

We need a set of maps ϕh,ϕv,ϕd,ϕw:R3R\phi_{h}, \phi_{v}, \phi_{d}, \phi_{w} : \mathbb{R}^{3} \rightarrow \mathbb{R} such that

Pndc,h=Pclip,hPclip,w=(Hwϕh)(Pproj)=ϕh(Pproj)(1ϕw(Pproj))ξh(P)Pndc,v=Pclip,vPclip,w=(Hwϕv)(Pproj)=ϕv(Pproj)(1ϕw(Pproj))ξv(P)Pndc,d=Pclip,dPclip,w=(Hwϕd)(Pproj)=ϕd(Pproj)(1ϕw(Pproj))ξd(P)Pndc,w=Pclip,wPclip,w=(Hwϕw)(Pproj)=ϕw(Pproj)(1ϕw(Pproj))=1\begin{align*} P_{ndc,h} &= \frac{P_{clip,h}}{P_{clip,w}} &&= \left( H_{w} \circ \phi_{h} \right) \left( P_{proj} \right) &&= \phi_{h} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) &&\equiv \xi_{h} \left( P \right) \\ P_{ndc,v} &= \frac{P_{clip,v}}{P_{clip,w}} &&= \left( H_{w} \circ \phi_{v} \right) \left( P_{proj} \right) &&= \phi_{v} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) &&\equiv \xi_{v} \left( P \right) \\ P_{ndc,d} &= \frac{P_{clip,d}}{P_{clip,w}} &&= \left( H_{w} \circ \phi_{d} \right) \left( P_{proj} \right) &&= \phi_{d} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) &&\equiv \xi_{d} \left( P \right) \\ P_{ndc,w} &= \frac{P_{clip,w}}{P_{clip,w}} &&= \left( H_{w} \circ \phi_{w} \right) \left( P_{proj} \right) &&= \phi_{w} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right)} \right) &&= 1 \\ \end{align*}

where PprojP_{proj} denotes a point PR3P \in \mathbb{R}^{3} in projected coordinates, Pclip,w=ϕw(Pproj)P_{clip,w} = \phi_{w}(P_{proj}) is an affine scalar function, and Hw:R4R4H_{w} : \mathbb{R}^{4} \rightarrow \mathbb{R}^{4} denotes homogenization by the ww component. Observe that the functions ξh,ξv,ξd:R3R\xi_{h}, \xi_{v}, \xi_{d} : \mathbb{R}^{3} \rightarrow \mathbb{R} on the right-hand side of (49) are projective functions of the view space point PP. This implies that the clip coordinates must be affine functions of PprojP_{proj}. In particular,

Pclip,h=ϕh(Pproj)Pclip,v=ϕv(Pproj)Pclip,d=ϕd(Pproj)Pclip,w=ϕw(Pproj)\begin{align*} P_{clip,h} &= \phi_{h} \left( P_{proj} \right) \\ P_{clip,v} &= \phi_{v} \left( P_{proj} \right) \\ P_{clip,d} &= \phi_{d} \left( P_{proj} \right) \\ P_{clip,w} &= \phi_{w} \left( P_{proj} \right) \\ \end{align*}

is the form of the clip components. Since the purpose of the ww coordinate is to perform perspective division, this implies that

ϕw(Pproj)=Pd\phi_{w} \left( P_{proj} \right) = P_{d}

so that the equations in (49) become

Pndc,h=ξh(P)=ϕh(Pproj)(1Pd)Pndc,v=ξv(P)=ϕv(Pproj)(1Pd)Pndc,d=ξd(P)=ϕd(Pproj)(1Pd)\begin{align*} P_{ndc,h} &= \xi_{h} \left( P \right) = \phi_{h} \left( P_{proj} \right) \left( \frac{1}{ P_{d} } \right) \\ P_{ndc,v} &= \xi_{v} \left( P \right) = \phi_{v} \left( P_{proj} \right) \left( \frac{1}{ P_{d} } \right) \\ P_{ndc,d} &= \xi_{d} \left( P \right) = \phi_{d} \left( P_{proj} \right) \left( \frac{1}{ P_{d} } \right) \\ \end{align*}

To derive the perspective projection matrix, we solve for the clip coordinate functions ϕh,ϕv,ϕd\phi_{h}, \phi_{v}, \phi_{d} indirectly using the auxiliary functions ξh,ξv,ξd\xi_{h}, \xi_{v}, \xi_{d} in (52), and use the constraints on the orthographic view volume to compute the auxiliary functions. To establish constraints, we need to talk about some well chosen points. We need to construct the maps ξh,ξv,ξd\xi_{h}, \xi_{v}, \xi_{d} such that the parametrization of the orthographic view volume maps to the parametrization of the canonical view volume. That it, such that coordinates map as lαmin,rαmax,bβmin,tβmax,nγmin,fγmax-l \mapsto \alpha_{min}, r \mapsto \alpha_{max}, -b \mapsto \beta_{min}, t \mapsto \beta_{max}, n \mapsto \gamma_{min}, f \mapsto \gamma_{max}. Consider the points in view coordinates

Qleft=lu^h+nu^dQright=ru^h+nu^dQbottom=bu^v+nu^dQtop=tu^v+nu^dQnear=nu^dQfar=fu^d\begin{align*} Q_{left} &= -l \mathbf{\hat{u}}_{h} + n \mathbf{\hat{u}}_{d} \\ Q_{right} &= r \mathbf{\hat{u}}_{h} + n \mathbf{\hat{u}}_{d} \\ Q_{bottom} &= -b \mathbf{\hat{u}}_{v} + n \mathbf{\hat{u}}_{d} \\ Q_{top} &= t \mathbf{\hat{u}}_{v} + n \mathbf{\hat{u}}_{d} \\ Q_{near} &= n \mathbf{\hat{u}}_{d} \\ Q_{far} &= f \mathbf{\hat{u}}_{d} \\ \end{align*}

The points QnearQ_{near} and QfarQ_{far} are the points along the viewing axis that intersect the near plane and the far plane, respectively, of the perspective view volume. The point QleftQ_{left} represents the point of intersection of the left plane, near plane, and the horizontal-vertical plane of the view volume. The point QrightQ_{right} represents the point of intersection of the right plane, near plane, and the horizontal-vertical plane of the view volume. The point QbottomQ_{bottom} represents the point of intersection of the bottom plane, near plane, and depth-vertical plane of the view volume. The point QtopQ_{top} represents the point of intersection of the top plane, near plane, and the depth-vertical plane of the view volume. In short, the points QnearQ_{near} and QfarQ_{far} are the origins of the near and far planes, respectively. The other four points and points chosen along the edge of the viewport in the near plane that allow us to easily set up the boundary conditions to compute the functions ξh,ξv,ξd\xi_{h}, \xi_{v}, \xi_{d}.

We now calculate the auxiliary functions. Consider the map ξh\xi_{h}, where

ξh(P)=(APproj,h+BPproj,v+CPproj,d+D)(1Pd)=(APproj,h+BPproj,v+Cθ(Pd)+D)(1Pd)=(APproj,h+BPproj,v+C(APd+B)+D)(1Pd)=(APproj,h+BPproj,v+CAPd+CB+D)(1Pd)=(APproj,h+BPproj,v+(CA)Pd+(CB+D))(1Pd)=(APproj,h+BPproj,v+CPd+D)(1Pd)=(AnPh+BnPv+CPd+D)(1Pd)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd)\begin{align*} \xi_{h} \left( P \right) &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} P_{proj,d} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \theta \left( P_{d} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \left( A^{\prime} P_{d} + B^{\prime} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} A^{\prime} P_{d} + C^{\prime} B^{\prime} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + \left( C^{\prime} A^{\prime} \right) P_{d} + \left( C^{\prime} B^{\prime} + D^{\prime} \right) \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A n P_{h} + B n P_{v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right) \\ \end{align*}

where C=CAC = C^{\prime} A^{\prime} and D=CB+DD = C^{\prime} B^{\prime} + D^{\prime}, so that

ξh(P)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd).\xi_{h} \left( P \right) = A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right).

Define the boundary conditions for our chosen points

ξh(Qleft)=αminξh(Qright)=αmaxξh(Qbottom)=0ξh(Qtop)=0ξh(Qnear)=0ξh(Qfar)=0\begin{align*} \xi_{h} \left( Q_{left} \right) &= \alpha_{min} \\ \xi_{h} \left( Q_{right} \right) &= \alpha_{max} \\ \xi_{h} \left( Q_{bottom} \right) &= 0 \\ \xi_{h} \left( Q_{top} \right) &= 0 \\ \xi_{h} \left( Q_{near} \right) &= 0 \\ \xi_{h} \left( Q_{far} \right) &= 0 \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ξh\xi_{h} should only be a function of the horizontal component and not the vertical component. The points Qbottom,Qtop,Qnear,QfarQ_{bottom}, Q_{top}, Q_{near}, Q_{far} lie on the depth-vertical plane, which have a zero horizontal component, so they should keep a zero horizontal component after transformation.

Applying the boundary conditions, we have

ξh(Qleft)=An(l)(1n)+Bn0(1n)+C+D(1n)=Al+C+D(1n)=αminξh(Qright)=Anr(1n)+Bn0(1n)+C+D(1n)=Ar+C+D(1n)=αmaxξh(Qbottom)=An0(1n)+Bn(b)(1n)+C+D(1n)=Bb+C+D(1n)=0ξh(Qtop)=An0(1n)+Bnt(1n)+C+D(1n)=Bt+C+D(1n)=0ξh(Qnear)=An0(1n)+Bn0(1n)+C+D(1n)=C+D(1n)=0ξh(Qfar)=An0(1f)+Bn0(1f)+C+D(1f)=C+D(1f)=0\begin{align*} \xi_{h} \left( Q_{left} \right) &= A n \cdot \left( -l \right) \cdot\left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -A l + C + D \left( \frac{1}{n} \right) \\ &= \alpha_{min} \\ \xi_{h} \left( Q_{right} \right) &= A n \cdot r \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= A r + C + D \left( \frac{1}{n} \right) \\ &= \alpha_{max} \\ \xi_{h} \left( Q_{bottom} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot \left( -b \right) \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -B b + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{h} \left( Q_{top} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot t \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= B t + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{h} \left( Q_{near} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{h} \left( Q_{far} \right) &= A n \cdot 0 \cdot \left( \frac{1}{f} \right) + B n \cdot 0 \cdot \left( \frac{1}{f} \right) + C + D \left( \frac{1}{f} \right) \\ &= C + D \left( \frac{1}{f} \right) \\ &= 0 \\ \end{align*}

so that

ξh(Qleft)=Al+C+D(1n)=αminξh(Qright)=Ar+C+D(1n)=αmaxξh(Qbottom)=Bb+C+D(1n)=0ξh(Qtop)=Bt+C+D(1n)=0ξh(Qnear)=C+D(1n)=0ξh(Qfar)=C+D(1f)=0\begin{align*} \xi_{h} \left( Q_{left} \right) &= -A l + C + D \left( \frac{1}{n} \right) &&= \alpha_{min} \\ \xi_{h} \left( Q_{right} \right) &= A r + C + D \left( \frac{1}{n} \right) &&= \alpha_{max} \\ \xi_{h} \left( Q_{bottom} \right) &= -B b + C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{h} \left( Q_{top} \right) &= B t + C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{h} \left( Q_{near} \right) &= C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{h} \left( Q_{far} \right) &= C + D \left( \frac{1}{f} \right) &&= 0 \\ \end{align*}

and now we compute the constants. Subtracting ξh(Qright)\xi_{h} \left( Q_{right} \right) from ξh(Qleft)\xi_{h} \left( Q_{left} \right) in (58) yields

ξh(Qright)ξh(Qleft)=[Ar+C+D(1n)][Al+C+D(1n)]=Ar(Al)=A(r(l))=αmaxαmin.\begin{align*} \xi_{h} \left( Q_{right} \right) - \xi_{h} \left( Q_{left} \right) &= \left[ A r + C + D \left( \frac{1}{n} \right) \right] - \left[ -A l + C + D \left( \frac{1}{n} \right) \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= \alpha_{max} - \alpha_{min}. \end{align*}

Solving for AA, we see that

A=αmaxαminr(l).A = \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)}.

Subtracting ξh(Qtop)\xi_{h} \left( Q_{top} \right) from ξh(Qbottom)\xi_{h} \left( Q_{bottom} \right) in (58) yields

ξh(Qtop)ξh(Qbottom)=[Bt+C+D(1n)][Bb+C+D(1n)]=BtB(b)=B(t(b))=0.\begin{align*} \xi_{h} \left( Q_{top} \right) - \xi_{h} \left( Q_{bottom} \right) &= \left[ B t + C + D \left( \frac{1}{n} \right) \right] - \left[ -B b + C + D \left( \frac{1}{n} \right) \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= 0. \end{align*}

Solving for BB, we see that

B=0B = 0

since t(b)=t+b0t - (-b) = t + b \neq 0. Subtracting ξh(Qfar)\xi_{h} \left( Q_{far} \right) from ξh(Qnear)\xi_{h} \left( Q_{near} \right) in (58) yields

ξh(Qfar)ξh(Qnear)=[C+D(1f)][C+D(1n)]=D(1f1n)=0.\begin{align*} \xi_{h} \left( Q_{far} \right) - \xi_{h} \left( Q_{near} \right) &= \left[ C + D \left( \frac{1}{f} \right) \right] - \left[ C + D \left( \frac{1}{n} \right) \right] \\ &= D \left( \frac{1}{f} - \frac{1}{n} \right) \\ &= 0. \end{align*}

Solving for DD, we see that

D=0D = 0

since 1f1n0\frac{1}{f} - \frac{1}{n} \neq 0. Substituting the constants (60), (62), and (64) back into ξh(Qright)\xi_{h}(Q_{right}) in (58) gives us

ξh(Qright)=Ar+C+D(1n)=Ar+C=(αmaxαminr(l))r+C=αmax.\xi_{h} \left( Q_{right} \right) = A r + C + D \left( \frac{1}{n} \right) = A r + C = \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) r + C = \alpha_{max}.

Solving for CC, we see that

C=αmax(αmaxαminr(l))r=αmax(αmaxαminr+l)r=αmax(r+l)(αmaxαmin)rr+l=αmaxr+αmaxlαmaxr+αminrr+l=αmaxr+αmaxlαmaxr+αminrr+l=αmaxl+αminrr+l=αminrαmax(l)r(l)\begin{align*} C &= \alpha_{max} - \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) r \\ &= \alpha_{max} - \left( \frac{\alpha_{max} - \alpha_{min}}{r + l} \right) r \\ &= \frac{\alpha_{max} \left( r + l \right) - \left( \alpha_{max} - \alpha_{min} \right) r}{r + l} \\ &= \frac{\alpha_{max} r + \alpha_{max} l - \alpha_{max} r + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{max} r + \alpha_{max} l - \alpha_{max} r + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{max} l + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)} \\ \end{align*}

therefore

C=αminrαmax(l)r(l).C = \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)}.

Assembling the constants (60), (62), (67), (64) back into (55) we have the complete formula for the auxiliary function ξh\xi_{h}

ξh(P)=((αmaxαmin)nr(l))Ph(1Pd)+αminrαmax(l)r(l).\xi_{h} \left( P \right) = \left( \frac{ \left( \alpha_{max} - \alpha_{min} \right) n }{ r - \left( -l \right)} \right) P_{h} \left( \frac{1}{P_{d}} \right) + \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)}.

Consider the map ξv\xi_{v}, where

ξv(P)=(APproj,h+BPproj,v+CPproj,d+D)(1Pd)=(APproj,h+BPproj,v+Cθ(Pd)+D)(1Pd)=(APproj,h+BPproj,v+C(APd+B)+D)(1Pd)=(APproj,h+BPproj,v+CAPd+CB+D)(1Pd)=(APproj,h+BPproj,v+(CA)Pd+(CB+D))(1Pd)=(APproj,h+BPproj,v+CPd+D)(1Pd)=(AnPh+BnPv+CPd+D)(1Pd)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd)\begin{align*} \xi_{v} \left( P \right) &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} P_{proj,d} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \theta \left( P_{d} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \left( A^{\prime} P_{d} + B^{\prime} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} A^{\prime} P_{d} + C^{\prime} B^{\prime} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + \left( C^{\prime} A^{\prime} \right) P_{d} + \left( C^{\prime} B^{\prime} + D^{\prime} \right) \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A n P_{h} + B n P_{v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right) \\ \end{align*}

where C=CAC = C^{\prime} A^{\prime} and D=CB+DD = C^{\prime} B^{\prime} + D^{\prime}, so that

ξv(P)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd).\xi_{v} \left( P \right) = A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right).

Define the boundary conditions for our chosen points

ξv(Qleft)=0ξv(Qright)=0ξv(Qbottom)=βminξv(Qtop)=βmaxξv(Qnear)=0ξv(Qfar)=0\begin{align*} \xi_{v} \left( Q_{left} \right) &= 0 \\ \xi_{v} \left( Q_{right} \right) &= 0 \\ \xi_{v} \left( Q_{bottom} \right) &= \beta_{min} \\ \xi_{v} \left( Q_{top} \right) &= \beta_{max} \\ \xi_{v} \left( Q_{near} \right) &= 0 \\ \xi_{v} \left( Q_{far} \right) &= 0 \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ξv\xi_{v} should only be a function of the vertical component and not the horizontal component. The points Qleft,Qright,Qnear,QfarQ_{left}, Q_{right}, Q_{near}, Q_{far} lie on the depth-horizontal plane, which have a zero vertical component, so they should keep a zero vertical component after transformation.

Applying the boundary conditions, we have

ξv(Qleft)=An(l)(1n)+Bn0(1n)+C+D(1n)=Al+C+D(1n)=0ξv(Qright)=Anr(1n)+Bn0(1n)+C+D(1n)=Ar+C+D(1n)=0ξv(Qbottom)=An0(1n)+Bn(b)(1n)+C+D(1n)=Bb+C+D(1n)=βminξv(Qtop)=An0(1n)+Bnt(1n)+C+D(1n)=Bt+C+D(1n)=βmaxξv(Qnear)=An0(1n)+Bn0(1n)+C+D(1n)=C+D(1n)=0ξv(Qfar)=An0(1f)+Bn0(1f)+C+D(1f)=C+D(1f)=0\begin{align*} \xi_{v} \left( Q_{left} \right) &= A n \cdot \left( -l \right) \cdot\left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -A l + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{v} \left( Q_{right} \right) &= A n \cdot r \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= A r + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{v} \left( Q_{bottom} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot \left( -b \right) \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -B b + C + D \left( \frac{1}{n} \right) \\ &= \beta_{min} \\ \xi_{v} \left( Q_{top} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot t \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= B t + C + D \left( \frac{1}{n} \right) \\ &= \beta_{max} \\ \xi_{v} \left( Q_{near} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{v} \left( Q_{far} \right) &= A n \cdot 0 \cdot \left( \frac{1}{f} \right) + B n \cdot 0 \cdot \left( \frac{1}{f} \right) + C + D \left( \frac{1}{f} \right) \\ &= C + D \left( \frac{1}{f} \right) \\ &= 0 \\ \end{align*}

so that

ξv(Qleft)=Al+C+D(1n)=0ξv(Qright)=Ar+C+D(1n)=0ξv(Qbottom)=Bb+C+D(1n)=βminξv(Qtop)=Bt+C+D(1n)=βmaxξv(Qnear)=C+D(1n)=0ξv(Qfar)=C+D(1f)=0\begin{align*} \xi_{v} \left( Q_{left} \right) &= -A l + C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{v} \left( Q_{right} \right) &= A r + C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{v} \left( Q_{bottom} \right) &= -B b + C + D \left( \frac{1}{n} \right) &&= \beta_{min} \\ \xi_{v} \left( Q_{top} \right) &= B t + C + D \left( \frac{1}{n} \right) &&= \beta_{max} \\ \xi_{v} \left( Q_{near} \right) &= C + D \left( \frac{1}{n} \right) &&= 0 \\ \xi_{v} \left( Q_{far} \right) &= C + D \left( \frac{1}{f} \right) &&= 0 \\ \end{align*}

and now we compute the constants. Subtracting ξv(Qright)\xi_{v} \left( Q_{right} \right) from ξv(Qleft)\xi_{v} \left( Q_{left} \right) in (73) yields

ξv(Qright)ξv(Qleft)=[Ar+C+D(1n)][Al+C+D(1n)]=Ar(Al)=A(r(l))=0.\begin{align*} \xi_{v} \left( Q_{right} \right) - \xi_{v} \left( Q_{left} \right) &= \left[ A r + C + D \left( \frac{1}{n} \right) \right] - \left[ -A l + C + D \left( \frac{1}{n} \right) \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= 0. \end{align*}

Solving for AA, we see that

A=0A = 0

since r(l)=r+l0r - (-l) = r + l \neq 0. Subtracting ξv(Qtop)\xi_{v} \left( Q_{top} \right) from ξv(Qbottom)\xi_{v} \left( Q_{bottom} \right) in (73) yields

ξv(Qtop)ξv(Qbottom)=[Bt+C+D(1n)][Bb+C+D(1n)]=BtB(b)=B(t(b))=βmaxβmin.\begin{align*} \xi_{v} \left( Q_{top} \right) - \xi_{v} \left( Q_{bottom} \right) &= \left[ B t + C + D \left( \frac{1}{n} \right) \right] - \left[ -B b + C + D \left( \frac{1}{n} \right) \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= \beta_{max} - \beta_{min}. \end{align*}

Solving for BB, we have

B=βmaxβmint(b).B = \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)}.

Subtracting ξv(Qfar)\xi_{v} \left( Q_{far} \right) from ξv(Qnear)\xi_{v} \left( Q_{near} \right) in (73) yields

ξv(Qfar)ξv(Qnear)=[C+D(1f)][C+D(1n)]=D(1f1n)=0.\begin{align*} \xi_{v} \left( Q_{far} \right) - \xi_{v} \left( Q_{near} \right) &= \left[ C + D \left( \frac{1}{f} \right) \right] - \left[ C + D \left( \frac{1}{n} \right) \right] \\ &= D \left( \frac{1}{f} - \frac{1}{n} \right) \\ &= 0. \end{align*}

Solving for DD, we see that

D=0D = 0

since 1f1n0\frac{1}{f} - \frac{1}{n} \neq 0. Substituting the constants (75), (77), and (79) back into ξv(Qright)\xi_{v}(Q_{right}) in (73) gives us

ξv(Qtop)=Bt+C+D(1n)=Bt+C=(βmaxβmint(b))t+C=βmax.\xi_{v} \left( Q_{top} \right) = B t + C + D \left( \frac{1}{n} \right) = B t + C = \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) t + C = \beta_{max}.

Solving for CC, we see that

C=βmax(βmaxβmint(b))t=βmax(βmaxβmint+b)t=βmax(t+b)(βmaxβmin)tt+b=βmaxt+βmaxbβmaxt+βmintt+b=βmaxt+βmaxbβmaxt+βmintt+b=βmaxb+βmintt+b=βmintβmax(b)t(b)\begin{align*} C &= \beta_{max} - \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) t \\ &= \beta_{max} - \left( \frac{\beta_{max} - \beta_{min}}{t + b} \right) t \\ &= \frac{\beta_{max} \left( t + b \right) - \left( \beta_{max} - \beta_{min} \right) t}{t + b} \\ &= \frac{\beta_{max} t + \beta_{max} b - \beta_{max} t + \beta_{min} t}{t + b} \\ &= \frac{\beta_{max} t + \beta_{max} b - \beta_{max} t + \beta_{min} t}{t + b} \\ &= \frac{\beta_{max} b + \beta_{min} t}{t + b} \\ &= \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)} \\ \end{align*}

therefore

C=βmintβmax(b)t(b).C = \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)}.

Assembling the constants (75), (77), (82), (79) back into (70) we have the complete formula for the auxiliary function ξv\xi_{v}

ξv(P)=((βmaxβmin)nt(b))Pv(1Pd)+βmintβmax(b)t(b).\xi_{v} \left( P \right) = \left( \frac{ \left( \beta_{max} - \beta_{min} \right) n }{ t - \left( -b \right)} \right) P_{v} \left( \frac{1}{P_{d}} \right) + \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)}.

Consider the map ξd\xi_{d}, where

ξd(P)=(APproj,h+BPproj,v+CPproj,d+D)(1Pd)=(APproj,h+BPproj,v+Cθ(Pd)+D)(1Pd)=(APproj,h+BPproj,v+C(APd+B)+D)(1Pd)=(APproj,h+BPproj,v+CAPd+CB+D)(1Pd)=(APproj,h+BPproj,v+(CA)Pd+(CB+D))(1Pd)=(APproj,h+BPproj,v+CPd+D)(1Pd)=(AnPh+BnPv+CPd+D)(1Pd)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd)\begin{align*} \xi_{d} \left( P \right) &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} P_{proj,d} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \theta \left( P_{d} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} \left( A^{\prime} P_{d} + B^{\prime} \right) + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C^{\prime} A^{\prime} P_{d} + C^{\prime} B^{\prime} + D^{\prime} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + \left( C^{\prime} A^{\prime} \right) P_{d} + \left( C^{\prime} B^{\prime} + D^{\prime} \right) \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A P_{proj,h} + B P_{proj,v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= \left( A n P_{h} + B n P_{v} + C P_{d} + D \right) \left( \frac{1}{P_{d}} \right) \\ &= A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right) \\ \end{align*}

where C=CAC = C^{\prime} A^{\prime} and D=CB+DD = C^{\prime} B^{\prime} + D^{\prime}, so that

ξd(P)=AnPh(1Pd)+BnPv(1Pd)+C+D(1Pd).\xi_{d} \left( P \right) = A n P_{h} \left( \frac{1}{P_{d}} \right) + B n P_{v} \left( \frac{1}{P_{d}} \right) + C + D \left( \frac{1}{P_{d}} \right).

Define the boundary conditions for our chosen points

ξd(Qleft)=0ξd(Qright)=0ξd(Qbottom)=0ξd(Qtop)=0ξd(Qnear)=γminξd(Qfar)=γmax\begin{align*} \xi_{d} \left( Q_{left} \right) &= 0 \\ \xi_{d} \left( Q_{right} \right) &= 0 \\ \xi_{d} \left( Q_{bottom} \right) &= 0 \\ \xi_{d} \left( Q_{top} \right) &= 0 \\ \xi_{d} \left( Q_{near} \right) &= \gamma_{min} \\ \xi_{d} \left( Q_{far} \right) &= \gamma_{max} \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ξd\xi_{d} should only be a function of the depth component and not the horizontal or vertical components. The points Qleft,Qright,Qbottom,QtopQ_{left}, Q_{right}, Q_{bottom}, Q_{top} lie on the near plane, which have a depth component of nn. Since perspective projection projects depth components onto the near plane, points already on the near plane should stay on the near plane. Similarly, points on the far plane should stay on the far plane. Consequently, the depth component should have no dependence on the horizontal or vertical components, only a depth term and an affine translation term.

Applying the boundary conditions, we have

ξd(Qleft)=An(l)(1n)+Bn0(1n)+C+D(1n)=Al+C+D(1n)=0ξd(Qright)=Anr(1n)+Bn0(1n)+C+D(1n)=Ar+C+D(1n)=0ξd(Qbottom)=An0(1n)+Bn(b)(1n)+C+D(1n)=Bb+C+D(1n)=0ξd(Qtop)=An0(1n)+Bnt(1n)+C+D(1n)=Bt+C+D(1n)=0ξd(Qnear)=An0(1n)+Bn0(1n)+C+D(1n)=C+D(1n)=γminξd(Qfar)=An0(1f)+Bn0(1f)+C+D(1f)=C+D(1f)=γmax\begin{align*} \xi_{d} \left( Q_{left} \right) &= A n \cdot \left( -l \right) \cdot\left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -A l + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{d} \left( Q_{right} \right) &= A n \cdot r \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= A r + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{d} \left( Q_{bottom} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot \left( -b \right) \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= -B b + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{d} \left( Q_{top} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot t \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= B t + C + D \left( \frac{1}{n} \right) \\ &= 0 \\ \xi_{d} \left( Q_{near} \right) &= A n \cdot 0 \cdot \left( \frac{1}{n} \right) + B n \cdot 0 \cdot \left( \frac{1}{n} \right) + C + D \left( \frac{1}{n} \right) \\ &= C + D \left( \frac{1}{n} \right) \\ &= \gamma_{min} \\ \xi_{d} \left( Q_{far} \right) &= A n \cdot 0 \cdot \left( \frac{1}{f} \right) + B n \cdot 0 \cdot \left( \frac{1}{f} \right) + C + D \left( \frac{1}{f} \right) \\ &= C + D \left( \frac{1}{f} \right) \\ &= \gamma_{max} \\ \end{align*}

so that

ξd(Qleft)=Al+C+D(1n)=γminξd(Qright)=Ar+C+D(1n)=γminξd(Qbottom)=Bb+C+D(1n)=γminξd(Qtop)=Bt+C+D(1n)=γminξd(Qnear)=C+D(1n)=γminξd(Qfar)=C+D(1f)=γmax\begin{align*} \xi_{d} \left( Q_{left} \right) &= -A l + C + D \left( \frac{1}{n} \right) &&= \gamma_{min} \\ \xi_{d} \left( Q_{right} \right) &= A r + C + D \left( \frac{1}{n} \right) &&= \gamma_{min} \\ \xi_{d} \left( Q_{bottom} \right) &= -B b + C + D \left( \frac{1}{n} \right) &&= \gamma_{min} \\ \xi_{d} \left( Q_{top} \right) &= B t + C + D \left( \frac{1}{n} \right) &&= \gamma_{min} \\ \xi_{d} \left( Q_{near} \right) &= C + D \left( \frac{1}{n} \right) &&= \gamma_{min} \\ \xi_{d} \left( Q_{far} \right) &= C + D \left( \frac{1}{f} \right) &&= \gamma_{max} \\ \end{align*}

and now we compute the constants. and now we compute the constants. Subtracting ξd(Qright)\xi_{d} \left( Q_{right} \right) from ξd(Qleft)\xi_{d} \left( Q_{left} \right) in (88) yields

ξd(Qright)ξd(Qleft)=[Ar+C+D(1n)][Al+C+D(1n)]=Ar(Al)=A(r(l))=γminγmin=0.\begin{align*} \xi_{d} \left( Q_{right} \right) - \xi_{d} \left( Q_{left} \right) &= \left[ A r + C + D \left( \frac{1}{n} \right) \right] - \left[ -A l + C + D \left( \frac{1}{n} \right) \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= \gamma_{min} - \gamma_{min} \\ &= 0. \end{align*}

Solving for AA, we see that

A=0A = 0

since r(l)=r+l0r - (-l) = r + l \neq 0. Subtracting ξd(Qtop)\xi_{d} \left( Q_{top} \right) from ξd(Qbottom)\xi_{d} \left( Q_{bottom} \right) in (58) yields

ξd(Qtop)ξd(Qbottom)=[Bt+C+D(1n)][Bb+C+D(1n)]=BtB(b)=B(t(b))=γminγmin=0.\begin{align*} \xi_{d} \left( Q_{top} \right) - \xi_{d} \left( Q_{bottom} \right) &= \left[ B t + C + D \left( \frac{1}{n} \right) \right] - \left[ -B b + C + D \left( \frac{1}{n} \right) \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= \gamma_{min} - \gamma_{min} \\ &= 0. \end{align*}

Solving for BB, we see that

B=0B = 0

since t(b)=t+b0t - (-b) = t + b \neq 0. Subtracting ξd(Qfar)\xi_{d} \left( Q_{far} \right) from ξd(Qnear)\xi_{d} \left( Q_{near} \right) in (88) yields

ξd(Qfar)ξd(Qnear)=[C+D(1f)][C+D(1n)]=D(1f1n)=D(nffn)=D(fnfn)=γmaxγmin.\begin{align*} \xi_{d} \left( Q_{far} \right) - \xi_{d} \left( Q_{near} \right) &= \left[ C + D \left( \frac{1}{f} \right) \right] - \left[ C + D \left( \frac{1}{n} \right) \right] \\ &= D \left( \frac{1}{f} - \frac{1}{n} \right) \\ &= D \left( \frac{n - f}{f n} \right) \\ &= D \left( -\frac{f - n}{f n} \right) \\ &= \gamma_{max} - \gamma_{min}. \end{align*}

Solving for DD, we see that

D=(γmaxγmin)fnfn.D = -\frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{f - n}.

Substituting the constants (90), (92), and (94) back into ξd(Qfar)\xi_{d}(Q_{far}) in (88) gives us

ξd(Qfar)=C+D(1f)=C+((γmaxγmin)fnfn)(1f)=C+((γmaxγmin)nfn)=γmax.\begin{align*} \xi_{d} \left( Q_{far} \right) &= C + D \left( \frac{1}{f} \right) \\ &= C + \left( -\frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \right) \left( \frac{1}{f} \right) \\ &= C + \left( -\frac{ \left( \gamma_{max} - \gamma_{min} \right) n }{f - n} \right) \\ &= \gamma_{max}. \end{align*}

Solving for CC

C=γmax+((γmaxγmin)nfn)=γmax(fn)+(γmaxγmin)nfn=γmaxfγmaxn+γmaxnγminnfn=γmaxfγminnfn\begin{align*} C &= \gamma_{max} + \left( \frac{ \left( \gamma_{max} - \gamma_{min} \right) n }{f - n} \right) \\ &= \frac{\gamma_{max} \left( f - n \right) + \left( \gamma_{max} - \gamma_{min} \right) n}{f - n} \\ &= \frac{\gamma_{max} f - \gamma_{max} n + \gamma_{max} n - \gamma_{min} n}{f - n} \\ &= \frac{\gamma_{max} f - \gamma_{min} n}{f - n} \\ \end{align*}

we have

C=γmaxfγminnfn.C = \frac{\gamma_{max} f - \gamma_{min} n}{f - n}.

Assembling the constants (90), (92), (97), (94) back into (85) we have the complete formula for the auxiliary function ξd\xi_{d}

ξd(P)=γmaxfγminnfn((γmaxγmin)fnfn)(1Pd).\xi_{d} \left( P \right) = \frac{\gamma_{max} f - \gamma_{min} n}{f - n} - \left( \frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \right) \left( \frac{1}{P_{d}} \right).

Now we return to the definitions for the clip space functions. Recall from (49) that

Pndc,hξh(P)ϕh(Pproj)(1ϕw(Pproj))=Pclip,hPclip,wPndc,vξv(P)ϕv(Pproj)(1ϕw(Pproj))=Pclip,vPclip,wPndc,dξd(P)ϕd(Pproj)(1ϕw(Pproj))=Pclip,dPclip,w\begin{align*} P_{ndc,h} \equiv \xi_{h} \left( P \right) &\equiv \phi_{h} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) = \frac{P_{clip,h}}{P_{clip,w}} \\ P_{ndc,v} \equiv \xi_{v} \left( P \right) &\equiv \phi_{v} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) = \frac{P_{clip,v}}{P_{clip,w}} \\ P_{ndc,d} \equiv \xi_{d} \left( P \right) &\equiv \phi_{d} \left( P_{proj} \right) \left( \frac{1}{\phi_{w} \left( P_{proj} \right) } \right) = \frac{P_{clip,d}}{P_{clip,w}} \\ \end{align*}

where PprojP_{proj} denotes a point PR3P \in \mathbb{R}^{3} in projected coordinates, and Pclip,w=ϕw(Pproj)=PdP_{clip,w} = \phi_{w}(P_{proj}) = P_{d} is an affine scalar function. We now derive the clip coordinate functions ϕh,ϕv,ϕd\phi_{h}, \phi_{v}, \phi_{d} given by

Pclip,h=ϕh(Pproj)Pclip,v=ϕv(Pproj)Pclip,d=ϕd(Pproj)\begin{align*} P_{clip,h} &= \phi_{h} \left( P_{proj} \right) \\ P_{clip,v} &= \phi_{v} \left( P_{proj} \right) \\ P_{clip,d} &= \phi_{d} \left( P_{proj} \right) \\ \end{align*}

by comparing the equations in (52) with (68), (83), and (98). Consider the affine map ϕh\phi_{h}. Rearranging terms in (68), we have

Pndc,h=(αmaxαminr(l))Pproj,h+αminrαmin(l)r(l)=(αmaxαminr(l))nPh(1Pd)+αminrαmin(l)r(l)=(αmaxαminr(l))nPh(1Pd)+(αminrαmin(l)r(l))Pd(1Pd)=((αmaxαmin)nr(l))Ph(1Pd)+(αminrαmin(l)r(l))Pd(1Pd)=[((αmaxαmin)nr(l))Ph+(αminrαmin(l)r(l))Pd](1Pd).\begin{align*} P_{ndc,h} &= \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) P_{proj,h} + \frac{\alpha_{min} r - \alpha_{min} \left( -l \right)}{r - \left( -l \right)} \\ &= \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) n P_{h} \left( \frac{1}{P_{d}} \right) + \frac{\alpha_{min} r - \alpha_{min} \left( -l \right)}{r - \left( -l \right)} \\ &= \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) n P_{h} \left( \frac{1}{P_{d}} \right) + \left( \frac{ \alpha_{min} r - \alpha_{min} \left( -l \right) }{r - \left( -l \right)} \right) P_{d} \left( \frac{1}{P_{d}} \right) \\ &= \left( \frac{ \left( \alpha_{max} - \alpha_{min} \right) n }{r - \left( -l \right)} \right) P_{h} \left( \frac{1}{P_{d}} \right) + \left( \frac{ \alpha_{min} r - \alpha_{min} \left( -l \right) }{r - \left( -l \right)} \right) P_{d} \left( \frac{1}{P_{d}} \right) \\ &= \left[ \left( \frac{ \left( \alpha_{max} - \alpha_{min} \right) n }{r - \left( -l \right)} \right) P_{h} + \left( \frac{ \alpha_{min} r - \alpha_{min} \left( -l \right) }{r - \left( -l \right)} \right) P_{d} \right] \left( \frac{1}{P_{d}} \right). \end{align*}

Comparing (101) with (52), we see that

Pclip,h=ϕh(Pproj)=((αmaxαmin)nr(l))Ph+(αminrαmin(l)r(l))Pd.P_{clip,h} = \phi_{h} \left( P_{proj} \right) = \left( \frac{ \left( \alpha_{max} - \alpha_{min} \right) n }{r - \left( -l \right)} \right) P_{h} + \left( \frac{ \alpha_{min} r - \alpha_{min} \left( -l \right) }{r - \left( -l \right)} \right) P_{d}.

Consider the affine map ϕv\phi_{v}. Rearranging terms in (83) we have

Pndc,v=(βmaxβmint(b))Pproj,v+βmintβmin(b)t(b)=(βmaxβmint(b))nPv(1Pd)+βmintβmin(b)t(b)=(βmaxβmint(b))nPv(1Pd)+(βmintβmin(b)t(b))Pd(1Pd)=((βmaxβmin)nt(b))Pv(1Pd)+(βmintβmin(b)t(b))Pd(1Pd)=[((βmaxβmin)nt(b))Pv+(βmintβmin(b)t(b))Pd](1Pd).\begin{align*} P_{ndc,v} &= \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) P_{proj,v} + \frac{\beta_{min} t - \beta_{min} \left( -b \right)}{t - \left( -b \right)} \\ &= \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) n P_{v} \left( \frac{1}{P_{d}} \right) + \frac{\beta_{min} t - \beta_{min} \left( -b \right)}{t - \left( -b \right)} \\ &= \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) n P_{v} \left( \frac{1}{P_{d}} \right) + \left( \frac{ \beta_{min} t - \beta_{min} \left( -b \right) }{t - \left( -b \right)} \right) P_{d} \left( \frac{1}{P_{d}} \right) \\ &= \left( \frac{ \left( \beta_{max} - \beta_{min} \right) n }{t - \left( -b \right)} \right) P_{v} \left( \frac{1}{P_{d}} \right) + \left( \frac{ \beta_{min} t - \beta_{min} \left( -b \right) }{t - \left( -b \right)} \right) P_{d} \left( \frac{1}{P_{d}} \right) \\ &= \left[ \left( \frac{ \left( \beta_{max} - \beta_{min} \right) n }{t - \left( -b \right)} \right) P_{v} + \left( \frac{ \beta_{min} t - \beta_{min} \left( -b \right) }{t - \left( -b \right)} \right) P_{d} \right] \left( \frac{1}{P_{d}} \right). \end{align*}

Comparing (103) with (52) we see that

Pclip,v=ϕv(Pproj)=((βmaxβmin)nt(b))Pv+(βmintβmin(b)t(b))Pd.P_{clip,v} = \phi_{v} \left( P_{proj} \right) = \left( \frac{ \left( \beta_{max} - \beta_{min} \right) n }{t - \left( -b \right)} \right) P_{v} + \left( \frac{ \beta_{min} t - \beta_{min} \left( -b \right) }{t - \left( -b \right)} \right) P_{d}.

Finally, consider the affine map ϕd\phi_{d}. Rearranging terms in (98) we have

Pndc,d=γmaxfγminnfn((γmaxγmin)fnfn)(1Pd)=[(γmaxfγminnfn)Pd(γmaxγmin)fnfn](1Pd)\begin{align*} P_{ndc,d} &= \frac{\gamma_{max} f - \gamma_{min} n}{f - n} - \left( \frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \right) \left( \frac{1}{P_{d}} \right) \\ &= \left[ \left( \frac{\gamma_{max} f - \gamma_{min} n}{f - n} \right) P_{d} - \frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{ f - n } \right] \left( \frac{1}{P_{d}} \right) \\ \end{align*}

Comparing (105) with (52) we see that

Pclip,d=ϕd(Pproj)=(γmaxfγminnfn)Pd(γmaxγmin)fnfn.P_{clip,d} = \phi_{d} \left( P_{proj} \right) = \left( \frac{\gamma_{max} f - \gamma_{min} n}{f - n} \right) P_{d} - \frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{ f - n }.

Since ϕh\phi_{h}, ϕv\phi_{v}, and ϕd\phi_{d} are the components of an affine transformation, and normalized device coordinates are a projective function of the view coordinates with ϕw(Pproj)=Pd\phi_{w}(P_{proj}) = P_{d} as the denominator, the perspective projection transformation has the form of the matrix in (38) lifted into RP3\mathbb{RP}^{3}. The resulting matrix equation for the matrix representation is then

[Pclip,hPclip,vPclip,dPclip,w]=[(αmaxαmin)nr(l)0αminrαmax(l)r(l)00(βmaxβmin)nt(b)βmintβmax(b)t(b)000γmaxfγminnfn(γmaxγmin)fnfn0010][PhPvPdPw].\begin{bmatrix} P_{clip,h} \\ P_{clip,v} \\ P_{clip,d} \\ P_{clip,w} \\ \end{bmatrix} = \begin{bmatrix} \frac{\left( \alpha_{max} - \alpha_{min} \right) n }{r - \left( -l \right)} & 0 & \frac{\alpha_{min}r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{\left( \beta_{max} - \beta_{min} \right) n }{t - \left( -b \right)} & \frac{\beta_{min}t - \beta_{max} \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{\gamma_{max}f - \gamma_{min}n}{f - n} & -\frac{\left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} P_{h} \\ P_{v} \\ P_{d} \\ P_{w} \\ \end{bmatrix}.

This yields the first major result, the canonical perspective projection matrix MperCM^{C}_{per}.

This completes the derivation of the perspective projection matrix.

The Canonical Orthographic Projection Matrix

We now construct the canonical orthographic projection matrix for the frame (O~view,(u^h,u^v,u^d))(\tilde{O}_{view}, (\mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d})) with the orthographic view volume parametrized by [l,r]×[b,t]×[n,f][-l, r] \times [-b, t] \times [n, f] and the canonical view volume parametrized by [αmin,αmax]×[βmin,βmax]×[γmin,γmax][\alpha_{min}, \alpha_{max}] \times [\beta_{min}, \beta_{max}] \times [\gamma_{min}, \gamma_{max}].

An orthographic projection works by removing the component parallel to the direction normal to the plane of projection in three dimensions. Orthographic projections preserve the lengths of lines parallel to the projection plane. It produces the component of a geometric figure that is parallel to the plane of projection. Unlike perspective projection, there is no depth distortion. In terms of our orthonormal frame, an orthographic projection removes the depth component from a vector. Let P~E3\tilde{P} \in \mathbb{E}^{3} be a point. The orthographic projection is a map Torth:E3E3T^{\prime}_{orth} : \mathbb{E}^{3} \rightarrow \mathbb{E}^{3} given by

Torth(P~)=P~((P~O~view)n^)n^.T^{\prime}_{orth} \left( \tilde{P} \right) = \tilde{P} - \left( \left( \tilde{P} - \tilde{O}_{view} \right) \cdot \mathbf{\hat{n}} \right) \mathbf{\hat{n}}.

In the coordinate frame (O~view,(u^h,u^v,u^d))(\tilde{O}_{view}, (\mathbf{\hat{u}}_{h}, \mathbf{\hat{u}}_{v}, \mathbf{\hat{u}}_{d})) let P=P~O~viewP = \tilde{P} - \tilde{O}_{view} be a representation of the point PP given by P=Phu^h+Pvu^v+Pdu^dP = P_{h} \mathbf{\hat{u}}_{h} + P_{v} \mathbf{\hat{u}}_{v} + P_{d} \mathbf{\hat{u}}_{d}. The orthographic projection has the form

Torth(P)=P(Pu^d)u^d=PPdu^d=Phu^h+Pvu^vT^{\prime}_{orth} \left( P \right) = P - \left( P \cdot \mathbf{\hat{u}}_{d} \right) \mathbf{\hat{u}}_{d} = P - P_{d} \mathbf{\hat{u}}_{d} = P_{h} \mathbf{\hat{u}}_{h} + P_{v} \mathbf{\hat{u}}_{v}

so that TorthT^{\prime}_{orth} indeed projects out the depth component as claimed. This is the usual definition of orthographic projection. The problem is that we still need depth information for rendering, so this information must be preserved in our true projection. Since orthographic projection does not distort depth in any way, and indeed has no denominator, it is an affine transformation. Thus the orthographic projection needs to carry depth information. We need to add the depth information along the normal vector to the projection plane into the transformation to get our projected coordinates. Let Torth:E3E3T_{orth} : \mathbb{E}^{3} \rightarrow \mathbb{E}^{3} be the transformation given by

Torth(P~)=Torth(P~)+((P~O~view)n^)n^.T_{orth} \left( \tilde{P} \right) = T^{\prime}_{orth} \left( \tilde{P} \right) + \left( \left( \tilde{P} - \tilde{O}_{view} \right) \cdot \mathbf{\hat{n}} \right) \mathbf{\hat{n}}.

Expanding out the definition

Torth(P~)=P~((P~O~view)n^)n^+((P~O~view)n^)n^=P~=I(P)T_{orth} \left( \tilde{P} \right) = \tilde{P} - \left( \left( \tilde{P} - \tilde{O}_{view} \right) \cdot \mathbf{\hat{n}} \right) \mathbf{\hat{n}} + \left( \left( \tilde{P} - \tilde{O}_{view} \right) \cdot \mathbf{\hat{n}} \right) \mathbf{\hat{n}} = \tilde{P} = I \left( P \right)

where II denotes the identity map I:E3E3I : \mathbb{E}^{3} \rightarrow \mathbb{E}^{3}. We see that the orthographic projection is simply the identity map when the depth information if factored back in. In components,

Torth(P)=I(P)=PT_{orth} \left( P \right) = I \left( P \right) = P

so that

Pproj,h=PhPproj,v=PvPproj,d=PdPproj,w=1\begin{align*} P_{proj,h} &= P_{h} \\ P_{proj,v} &= P_{v} \\ P_{proj,d} &= P_{d} \\ P_{proj,w} &= 1 \\ \end{align*}

gives our projected coordinates. Thus we map directly to clip coordinates from view coordinates. To complete the orthographic projection transformation, we need an affine transformation that maps the orthographic view volume to the canonical view volume in normalized device coordinates. Just like the perspective projection earlier, we infer the orthographic projection matrix indirectly using constraints on how the orthographic view volume transforms into the canonical view volume. We require affine maps ϕh,ϕv,ϕd,ϕw:R3R\phi_{h}, \phi_{v}, \phi_{d}, \phi_{w} : \mathbb{R^{3}} \rightarrow \mathbb{R} such that

Pclip,h=ϕh(Pproj)Pclip,v=ϕv(Pproj)Pclip,d=ϕd(Pproj)Pclip,w=ϕw(Pproj)\begin{align*} P_{clip,h} &= \phi_{h} \left( P_{proj} \right) \\ P_{clip,v} &= \phi_{v} \left( P_{proj} \right) \\ P_{clip,d} &= \phi_{d} \left( P_{proj} \right) \\ P_{clip,w} &= \phi_{w} \left( P_{proj} \right) \\ \end{align*}

where we get ϕw\phi_{w} immediately because orthographic projections are affine maps. That is

ϕw(P)=1.\phi_{w} \left( P \right) = 1.

where we use the fact that Pproj=PP_{proj} = P. Since affine transformations do not perform depth normalization, we see that

Pndc,h=Pclip,hPndc,v=Pclip,vPndc,d=Pclip,dPndc,w=Pclip,w\begin{align*} P_{ndc,h} &= P_{clip,h} \\ P_{ndc,v} &= P_{clip,v} \\ P_{ndc,d} &= P_{clip,d} \\ P_{ndc,w} &= P_{clip,w} \\ \end{align*}

therefore

Pndc,h=ϕh(Pproj)=ϕh(P)Pndc,v=ϕv(Pproj)=ϕv(P)Pndc,d=ϕd(Pproj)=ϕd(P)\begin{align*} P_{ndc,h} &= \phi_{h} \left( P_{proj} \right) &= \phi_{h} \left( P \right) \\ P_{ndc,v} &= \phi_{v} \left( P_{proj} \right) &= \phi_{v} \left( P \right) \\ P_{ndc,d} &= \phi_{d} \left( P_{proj} \right) &= \phi_{d} \left( P \right) \\ \end{align*}

are the equations we need to solve for. As with the perspective projection transformation, we use the constraints on the orthographic view volume to compute the functions. To establish constraints, we need to talk about some well chosen points. We need to construct the maps ϕh,ϕv,ϕd\phi_{h}, \phi_{v}, \phi_{d} such that the parametrization of the orthographic view volume maps to the parametrization of the canonical view volume. That it, such that coordinates map as lαmin-l \mapsto \alpha_{min}, rαmaxr \mapsto \alpha_{max}, bβmin-b \mapsto \beta_{min}, tβmaxt \mapsto \beta_{max}, nγminn \mapsto \gamma_{min}, fγmaxf \mapsto \gamma_{max}. Consider the points in view coordinates

Qleft=lu^h+nu^dQright=ru^h+nu^dQbottom=bu^v+nu^dQtop=tu^v+nu^dQnear=nu^dQfar=fu^d\begin{align*} Q_{left} &= -l \mathbf{\hat{u}}_{h} + n \mathbf{\hat{u}}_{d} \\ Q_{right} &= r \mathbf{\hat{u}}_{h} + n \mathbf{\hat{u}}_{d} \\ Q_{bottom} &= -b \mathbf{\hat{u}}_{v} + n \mathbf{\hat{u}}_{d} \\ Q_{top} &= t \mathbf{\hat{u}}_{v} + n \mathbf{\hat{u}}_{d} \\ Q_{near} &= n \mathbf{\hat{u}}_{d} \\ Q_{far} &= f \mathbf{\hat{u}}_{d} \\ \end{align*}

The points QnearQ_{near} and QfarQ_{far} are the points along the viewing axis that intersect the near plane and the far plane, respectively, of the orthographic view volume. The point QleftQ_{left} represents the point of intersection of the left plane, near plane, and the horizontal-vertical plane of the view volume. The point QrightQ_{right} represents the point of intersection of the right plane, near plane, and the horizontal-vertical plane of the view volume. The point QbottomQ_{bottom} represents the point of intersection of the bottom plane, near plane, and depth-vertical plane of the view volume. The point QtopQ_{top} represents the point of intersection of the top plane, near plane, and the depth-vertical plane of the view volume. In short, the points QnearQ_{near} and QfarQ_{far} are the origins of the near and far planes, respectively. The other four points and points chosen along the edge of the viewport in the near plane that allow us to easily set up the boundary conditions to compute the functions ϕh,ϕv,ϕd\phi_{h}, \phi_{v}, \phi_{d}.

Consider the map ϕh\phi_{h}, where

ϕh(P)=APh+BPv+CPd+D\phi_{h} \left( P \right) = A P_{h} + B P_{v} + C P_{d} + D

Define the boundary conditions for our chosen points

ϕh(Qleft)=αminϕh(Qright)=αmaxϕh(Qbottom)=0ϕh(Qtop)=0ϕh(Qnear)=0ϕh(Qfar)=0\begin{align*} \phi_{h} \left( Q_{left} \right) &= \alpha_{min} \\ \phi_{h} \left( Q_{right} \right) &= \alpha_{max} \\ \phi_{h} \left( Q_{bottom} \right) &= 0 \\ \phi_{h} \left( Q_{top} \right) &= 0 \\ \phi_{h} \left( Q_{near} \right) &= 0 \\ \phi_{h} \left( Q_{far} \right) &= 0 \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ϕh\phi_{h} should only be a function of the horizontal component and not the vertical component. The points Qbottom,Qtop,Qnear,QfarQ_{bottom}, Q_{top}, Q_{near}, Q_{far} lie on the depth-vertical plane, which have a zero horizontal component, so they should keep a zero horizontal component after transformation.

Applying the boundary conditions, we have

ϕh(Qleft)=A(l)+B0+Cn+D=Al+Cn+D=αminϕh(Qright)=Ar+B0+Cn+D=Ar+Cn+D=αmaxϕh(Qbottom)=A0+B(b)+Cn+D=Bb+Cn+D=0ϕh(Qtop)=A0+Bt+Cn+D=Bt+Cn+D=0ϕh(Qnear)=A0+B0+Cn+D=Cn+D=0ϕh(Qfar)=A0+B0+Cf+D=Cf+D=0\begin{align*} \phi_{h} \left( Q_{left} \right) &= A \cdot \left( -l \right) + B \cdot 0 + C n + D &&= -A l + C n + D &&= \alpha_{min} \\ \phi_{h} \left( Q_{right} \right) &= A \cdot r + B \cdot 0 + C n + D &&= A r + C n + D &&= \alpha_{max} \\ \phi_{h} \left( Q_{bottom} \right) &= A \cdot 0 + B \cdot \left( -b \right) + C n + D &&= -B b + C n + D &&= 0 \\ \phi_{h} \left( Q_{top} \right) &= A \cdot 0 + B \cdot t + C n + D &&= B t + C n + D &&= 0 \\ \phi_{h} \left( Q_{near} \right) &= A \cdot 0 + B \cdot 0 + C n + D &&= C n + D &&= 0 \\ \phi_{h} \left( Q_{far} \right) &= A \cdot 0 + B \cdot 0 + C f + D &&= C f + D &&= 0 \\ \end{align*}

so that

ϕh(Qleft)=Al+Cn+D=αminϕh(Qright)=Ar+Cn+D=αmaxϕh(Qbottom)=Bb+Cn+D=0ϕh(Qtop)=Bt+Cn+D=0ϕh(Qnear)=Cn+D=0ϕh(Qfar)=Cf+D=0\begin{align*} \phi_{h} \left( Q_{left} \right) &= -A l + C n + D &&= \alpha_{min} \\ \phi_{h} \left( Q_{right} \right) &= A r + C n + D &&= \alpha_{max} \\ \phi_{h} \left( Q_{bottom} \right) &= -B b + C n + D &&= 0 \\ \phi_{h} \left( Q_{top} \right) &= B t + C n + D &&= 0 \\ \phi_{h} \left( Q_{near} \right) &= C n + D &&= 0 \\ \phi_{h} \left( Q_{far} \right) &= C f + D &&= 0 \\ \end{align*}

and now we compute the constants. Subtracting ϕh(Qright)\phi_{h} \left( Q_{right} \right) from ϕh(Qleft)\phi_{h} \left( Q_{left} \right) in (123) yields

ϕh(Qright)ϕh(Qleft)=[Ar+Cn+D][Al+Cn+D]=Ar(Al)=A(r(l))=αmaxαmin.\begin{align*} \phi_{h} \left( Q_{right} \right) - \phi_{h} \left( Q_{left} \right) &= \left[ A r + C n + D \right] - \left[ -A l + C n + D \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= \alpha_{max} - \alpha_{min}. \end{align*}

Solving for AA, we see that

A=αmaxαminr(l).A = \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)}.

Subtracting ϕh(Qtop)\phi_{h} \left( Q_{top} \right) from ϕh(Qbottom)\phi_{h} \left( Q_{bottom} \right) in (123) yields

ϕh(Qtop)ϕh(Qbottom)=[Bt+Cn+D][Bb+Cn+D]=BtB(b)=B(t(b))=0.\begin{align*} \phi_{h} \left( Q_{top} \right) - \phi_{h} \left( Q_{bottom} \right) &= \left[ B t + C n + D \right] - \left[ -B b + C n + D \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= 0. \end{align*}

Solving for BB, we see that

B=0B = 0

since t(b)=t+b0t - (-b) = t + b \neq 0. Subtracting ϕh(Qfar)\phi_{h} \left( Q_{far} \right) from ϕh(Qnear)\phi_{h} \left( Q_{near} \right) in (123) yields

ϕh(Qfar)ϕh(Qnear)=[Cf+D][Cn+D]=CfCn=C(fn)=0.\begin{align*} \phi_{h} \left( Q_{far} \right) - \phi_{h} \left( Q_{near} \right) &= \left[ C f + D \right] - \left[ C n + D \right] \\ &= C f - C n \\ &= C \left( f - n \right) \\ &= 0. \end{align*}

Solving for CC, we see that

C=0C = 0

since fn0f - n \neq 0. Substituting the constants (125), (127), and (129) back into ϕh(Qright)\phi_{h}(Q_{right}) in (123) gives us

ϕh(Qright)=Ar+Cn+D=Ar+D=(αmaxαminr(l))r+D=αmax.\phi_{h} \left( Q_{right} \right) = A r + C n + D = A r + D = \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) r + D = \alpha_{max}.

Solving for DD

D=αmax(αmaxαminr(l))r=αmax(αmaxαminr+l)r=αmax(r+l)(αmaxαmin)rr+l=αmaxr+αmaxlαmaxr+αminrr+l=αmaxr+αmaxlαmaxr+αminrr+l=αmaxl+αminrr+l=αminrαmax(l)r(l)\begin{align*} D &= \alpha_{max} - \left( \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} \right) r \\ &= \alpha_{max} - \left( \frac{\alpha_{max} - \alpha_{min}}{r + l} \right) r \\ &= \frac{\alpha_{max} \left( r + l \right) - \left( \alpha_{max} - \alpha_{min} \right) r}{r + l} \\ &= \frac{\alpha_{max} r + \alpha_{max} l - \alpha_{max} r + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{max} r + \alpha_{max} l - \alpha_{max} r + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{max} l + \alpha_{min} r}{r + l} \\ &= \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)} \\ \end{align*}

we have

D=αminrαmax(l)r(l).D = \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)}.

Assembling the constants (125), (127), (129), (132) back into (120) we have the complete formula for the function ϕh\phi_{h}

ϕh(P)=(αmaxαminr(l))Ph+αminrαmax(l)r(l).\phi_{h} \left( P \right) = \left( \frac{ \alpha_{max} - \alpha_{min} }{ r - \left( -l \right)} \right) P_{h} + \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)}.

Consider the map ϕv\phi_{v}, where

ϕv(P)=APh+BPv+CPd+D\phi_{v} \left( P \right) = A P_{h} + B P_{v} + C P_{d} + D

Define the boundary conditions for our chosen points

ϕv(Qleft)=0ϕv(Qright)=0ϕv(Qbottom)=βminϕv(Qtop)=βmaxϕv(Qnear)=0ϕv(Qfar)=0\begin{align*} \phi_{v} \left( Q_{left} \right) &= 0 \\ \phi_{v} \left( Q_{right} \right) &= 0 \\ \phi_{v} \left( Q_{bottom} \right) &= \beta_{min} \\ \phi_{v} \left( Q_{top} \right) &= \beta_{max} \\ \phi_{v} \left( Q_{near} \right) &= 0 \\ \phi_{v} \left( Q_{far} \right) &= 0 \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ϕv\phi_{v} should only be a function of the vertical component and not the horizontal component. The points Qleft,Qright,Qnear,QfarQ_{left}, Q_{right}, Q_{near}, Q_{far} lie on the depth-horizontal plane, which have a zero vertical component, so they should keep a zero vertical component after transformation.

Applying the boundary conditions, we have

ϕv(Qleft)=A(l)+B0+Cn+D=Al+Cn+D=0ϕv(Qright)=Ar+B0+Cn+D=Ar+Cn+D=0ϕv(Qbottom)=A0+B(b)+Cn+D=Bb+Cn+D=βminϕv(Qtop)=A0+Bt+Cn+D=Bt+Cn+D=βmaxϕv(Qnear)=A0+B0+Cn+D=Cn+D=0ϕv(Qfar)=A0+B0+Cf+D=Cf+D=0\begin{align*} \phi_{v} \left( Q_{left} \right) &= A \cdot \left( -l \right) + B \cdot 0 + C n + D &&= -A l + C n + D &&= 0 \\ \phi_{v} \left( Q_{right} \right) &= A \cdot r + B \cdot 0 + C n + D &&= A r + C n + D &&= 0 \\ \phi_{v} \left( Q_{bottom} \right) &= A \cdot 0 + B \cdot \left( -b \right) + C n + D &&= -B b + C n + D &&= \beta_{min} \\ \phi_{v} \left( Q_{top} \right) &= A \cdot 0 + B \cdot t + C n + D &&= B t + C n + D &&= \beta_{max} \\ \phi_{v} \left( Q_{near} \right) &= A \cdot 0 + B \cdot 0 + C n + D &&= C n + D &&= 0 \\ \phi_{v} \left( Q_{far} \right) &= A \cdot 0 + B \cdot 0 + C f + D &&= C f + D &&= 0 \\ \end{align*}

so that

ϕv(Qleft)=Al+Cn+D=0ϕv(Qright)=Ar+Cn+D=0ϕv(Qbottom)=Bb+Cn+D=βminϕv(Qtop)=Bt+Cn+D=βmaxϕv(Qnear)=Cn+D=0ϕv(Qfar)=Cf+D=0\begin{align*} \phi_{v} \left( Q_{left} \right) &= -A l + C n + D &&= 0 \\ \phi_{v} \left( Q_{right} \right) &= A r + C n + D &&= 0 \\ \phi_{v} \left( Q_{bottom} \right) &= -B b + C n + D &&= \beta_{min} \\ \phi_{v} \left( Q_{top} \right) &= B t + C n + D &&= \beta_{max} \\ \phi_{v} \left( Q_{near} \right) &= C n + D &&= 0 \\ \phi_{v} \left( Q_{far} \right) &= C f + D &&= 0 \\ \end{align*}

and now we compute the constants. Subtracting ϕv(Qright)\phi_{v} \left( Q_{right} \right) from ϕv(Qleft)\phi_{v} \left( Q_{left} \right) in (137) yields

ϕv(Qright)ϕv(Qleft)=[Ar+Cn+D][Al+Cn+D]=Ar(Al)=A(r(l))=0.\begin{align*} \phi_{v} \left( Q_{right} \right) - \phi_{v} \left( Q_{left} \right) &= \left[ A r + C n + D \right] - \left[ -A l + C n + D \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= 0. \end{align*}

Solving for AA, we see that

A=0A = 0

since r(l)=r+l0r - (-l) = r + l \neq 0. Subtracting ϕv(Qtop)\phi_{v} \left( Q_{top} \right) from ϕv(Qbottom)\phi_{v} \left( Q_{bottom} \right) in (137) yields

ϕv(Qtop)ϕv(Qbottom)=[Bt+Cn+D][Bb+Cn+D]=BtB(b)=B(t(b))=βmaxβmin.\begin{align*} \phi_{v} \left( Q_{top} \right) - \phi_{v} \left( Q_{bottom} \right) &= \left[ B t + C n + D \right] - \left[ -B b + C n + D \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= \beta_{max} - \beta_{min}. \end{align*}

Solving for BB, we see that

B=βmaxβmint(b).B = \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)}.

Subtracting ϕv(Qfar)\phi_{v} \left( Q_{far} \right) from ϕv(Qnear)\phi_{v} \left( Q_{near} \right) in (137) yields

ϕv(Qfar)ϕv(Qnear)=[Cf+D][Cn+D]=CfCn=C(fn)=0.\begin{align*} \phi_{v} \left( Q_{far} \right) - \phi_{v} \left( Q_{near} \right) &= \left[ C f + D \right] - \left[ C n + D \right] \\ &= C f - C n \\ &= C \left( f - n \right) \\ &= 0. \end{align*}

Solving for CC, we see that

C=0C = 0

since fn0f - n \neq 0. Substituting the constants (139), (141), and (143) back into ϕv(Qtop)\phi_{v}(Q_{top}) in (137) gives us

ϕv(Qtop)=Bt+Cn+D=Bt+D=(βmaxβmint(b))t+D=βmax.\phi_{v} \left( Q_{top} \right) = B t + C n + D = B t + D = \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) t + D = \beta_{max}.

Solving for DD

D=βmax(βmaxβmint(b))t=βmax(βmaxβmint+b)t=βmax(t+b)(βmaxβmin)tt+b=βmaxt+βmaxbβmaxt+βmintt+b=βmaxt+βmaxbβmaxt+βmintt+b=βmaxb+βmintt+b=βmintβmax(b)t(b)\begin{align*} D &= \beta_{max} - \left( \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} \right) t \\ &= \beta_{max} - \left( \frac{\beta_{max} - \beta_{min}}{t + b} \right) t \\ &= \frac{\beta_{max} \left( t + b \right) - \left( \beta_{max} - \beta_{min} \right) t}{t + b} \\ &= \frac{\beta_{max} t + \beta_{max} b - \beta_{max} t + \beta_{min} t}{t + b} \\ &= \frac{\beta_{max} t + \beta_{max} b - \beta_{max} t + \beta_{min} t}{t + b} \\ &= \frac{\beta_{max} b + \beta_{min} t}{t + b} \\ &= \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)} \\ \end{align*}

we have

D=βmintβmax(b)t(b).D = \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)}.

Assembling the constants (139), (141), (143), (146) back into (134) we have the complete formula for the function ϕv\phi_{v}

ϕv(P)=(βmaxβmint(b))Pv+βmintβmax(b)t(b).\phi_{v} \left( P \right) = \left( \frac{ \beta_{max} - \beta_{min} }{ t - \left( -b \right)} \right) P_{v} + \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)}.

Consider the map ϕd\phi_{d}, where

ϕd(P)=APh+BPv+CPd+D\phi_{d} \left( P \right) = A P_{h} + B P_{v} + C P_{d} + D

Define the boundary conditions for our chosen points

ϕd(Qleft)=γminϕd(Qright)=γminϕd(Qbottom)=γminϕd(Qtop)=γminϕd(Qnear)=γminϕd(Qfar)=γmax\begin{align*} \phi_{d} \left( Q_{left} \right) &= \gamma_{min} \\ \phi_{d} \left( Q_{right} \right) &= \gamma_{min} \\ \phi_{d} \left( Q_{bottom} \right) &= \gamma_{min} \\ \phi_{d} \left( Q_{top} \right) &= \gamma_{min} \\ \phi_{d} \left( Q_{near} \right) &= \gamma_{min} \\ \phi_{d} \left( Q_{far} \right) &= \gamma_{max} \\ \end{align*}

which we need to justify. The view coordinates are orthogonal to each other, and the normalized device coordinates are also orthogonal to each other. This means that ϕd\phi_{d} should only be a function of the depth component and not the horizontal or vertical components. The points Qleft,Qright,Qbottom,QtopQ_{left}, Q_{right}, Q_{bottom}, Q_{top} lie on the near plane, which have a depth component of nn. Since orthographic projection is just the identity, points already on the near plane should stay on the near plane. Similarly, points on the far plane should stay on the far plane. Consequently, the depth component should have no dependence on the horizontal or vertical components, only a depth term and an affine translation term.

Applying the boundary conditions, we have

ϕd(Qleft)=A(l)+B0+Cn+D=Al+Cn+D=γminϕd(Qright)=Ar+B0+Cn+D=Ar+Cn+D=γminϕd(Qbottom)=A0+B(b)+Cn+D=Bb+Cn+D=0ϕd(Qtop)=A0+Bt+Cn+D=Bt+Cn+D=0ϕd(Qnear)=A0+B0+Cn+D=Cn+D=γminϕd(Qfar)=A0+B0+Cf+D=Cf+D=γmax\begin{align*} \phi_{d} \left( Q_{left} \right) &= A \cdot \left( -l \right) + B \cdot 0 + C n + D &&= -A l + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{right} \right) &= A \cdot r + B \cdot 0 + C n + D &&= A r + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{bottom} \right) &= A \cdot 0 + B \cdot \left( -b \right) + C n + D &&= -B b + C n + D &&= 0 \\ \phi_{d} \left( Q_{top} \right) &= A \cdot 0 + B \cdot t + C n + D &&= B t + C n + D &&= 0 \\ \phi_{d} \left( Q_{near} \right) &= A \cdot 0 + B \cdot 0 + C n + D &&= C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{far} \right) &= A \cdot 0 + B \cdot 0 + C f + D &&= C f + D &&= \gamma_{max} \\ \end{align*}

so that

ϕd(Qleft)=Al+Cn+D=γminϕd(Qright)=Ar+Cn+D=γminϕd(Qbottom)=Bb+Cn+D=γminϕd(Qtop)=Bt+Cn+D=γminϕd(Qnear)=Cn+D=γminϕd(Qfar)=Cf+D=γmax\begin{align*} \phi_{d} \left( Q_{left} \right) &= -A l + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{right} \right) &= A r + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{bottom} \right) &= -B b + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{top} \right) &= B t + C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{near} \right) &= C n + D &&= \gamma_{min} \\ \phi_{d} \left( Q_{far} \right) &= C f + D &&= \gamma_{max} \\ \end{align*}

and now we compute the constants. Subtracting ϕd(Qright)\phi_{d} \left( Q_{right} \right) from ϕd(Qleft)\phi_{d} \left( Q_{left} \right) in (151) yields

ϕd(Qright)ϕd(Qleft)=[Ar+Cn+D][Al+Cn+D]=Ar(Al)=A(r(l))=γminγmin=0.\begin{align*} \phi_{d} \left( Q_{right} \right) - \phi_{d} \left( Q_{left} \right) &= \left[ A r + C n + D \right] - \left[ -A l + C n + D \right] \\ &= A r - \left( - A l \right) \\ &= A \left( r - \left( -l \right) \right) \\ &= \gamma_{min} - \gamma_{min} \\ &= 0. \end{align*}

Solving for AA, we see that

A=0A = 0

since r(l)=r+l0r - (-l) = r + l \neq 0. Subtracting ϕd(Qtop)\phi_{d} \left( Q_{top} \right) from ϕd(Qbottom)\phi_{d} \left( Q_{bottom} \right) in (151) yields

ϕd(Qtop)ϕd(Qbottom)=[Bt+Cn+D][Bb+Cn+D]=BtB(b)=B(t(b))=γminγmin=0.\begin{align*} \phi_{d} \left( Q_{top} \right) - \phi_{d} \left( Q_{bottom} \right) &= \left[ B t + C n + D \right] - \left[ -B b + C n + D \right] \\ &= B t - B \left( -b \right) \\ &= B \left( t - \left( -b \right) \right) \\ &= \gamma_{min} - \gamma_{min} \\ &= 0. \end{align*}

Solving for BB, we see that

B=0B = 0

since t(b)=t+b0t - (-b) = t + b \neq 0. Subtracting ϕd(Qfar)\phi_{d} \left( Q_{far} \right) from ϕd(Qnear)\phi_{d} \left( Q_{near} \right) in (151) yields

ϕd(Qfar)ϕd(Qnear)=[Cf+D][Cn+D]=CfCn=C(fn)=γmaxγmin.\begin{align*} \phi_{d} \left( Q_{far} \right) - \phi_{d} \left( Q_{near} \right) &= \left[ C f + D \right] - \left[ C n + D \right] \\ &= C f - C n \\ &= C \left( f - n \right) \\ &= \gamma_{max} - \gamma_{min}. \end{align*}

Solving for CC, we see that

C=γmaxγminfnC = \frac{ \gamma_{max} - \gamma_{min} }{f - n}

Substituting the constants (153), (155), and (157) back into ϕd(Qfar)\phi_{d}(Q_{far}) in (151) gives us

ϕd(Qfar)=Cf+D=(γmaxγminfn)f+D=γmax.\begin{align*} \phi_{d} \left( Q_{far} \right) &= C f + D &= \left( \frac{\gamma_{max} - \gamma_{min}}{f - n} \right) f + D &= \gamma_{max}. \end{align*}

Solving for DD

D=γmax(γmaxγminfn)f=γmax(fn)(γmaxγmin)ffn=γmaxfγmaxnγmaxf+γminffn=γminfγmaxnfn\begin{align*} D &= \gamma_{max} - \left( \frac{\gamma_{max} - \gamma_{min}}{f - n} \right) f \\ &= \frac{\gamma_{max} \left( f - n \right) - \left( \gamma_{max} - \gamma_{min} \right) f}{f - n} \\ &= \frac{\gamma_{max} f - \gamma_{max} n - \gamma_{max} f + \gamma_{min}f}{f - n} \\ &= \frac{\gamma_{min} f - \gamma_{max} n}{f - n} \\ \end{align*}

we have

D=γminfγmaxnfn.D = \frac{\gamma_{min} f - \gamma_{max} n}{f - n}.

Assembling the constants (153), (155), (157), (160) back into (148) we have the complete formula for the function ϕd\phi_{d}

ϕd(P)=(γmaxγminfn)Pd+γminfγmaxnfn.\phi_{d} \left( P \right) = \left( \frac{\gamma_{max} - \gamma_{min}}{f - n} \right) P_{d} + \frac{ \gamma_{min} f - \gamma_{max} n }{f - n}.

Finally, we substitute (133), (147), and (161) back into (115) to get

Pclip,h=ϕh(P)=(αmaxαminr(l))Ph+αminrαmax(l)r(l)Pclip,v=ϕv(P)=(βmaxβmint(b))Pv+βmintβmax(b)t(b)Pclip,d=ϕd(P)=(γmaxγminfn)Pd+γminfγmaxnfnPclip,w=ϕw(P)=1\begin{align*} P_{clip,h} &= \phi_{h} \left( P \right) &&= \left( \frac{ \alpha_{max} - \alpha_{min} }{ r - \left( -l \right)} \right) P_{h} + \frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)} \\ P_{clip,v} &= \phi_{v} \left( P \right) &&= \left( \frac{ \beta_{max} - \beta_{min} }{ t - \left( -b \right)} \right) P_{v} + \frac{\beta_{min} t - \beta_{max} \left( -b \right)}{t - \left( -b \right)} \\ P_{clip,d} &= \phi_{d} \left( P \right) &&= \left( \frac{\gamma_{max} - \gamma_{min}}{f - n} \right) P_{d} + \frac{ \gamma_{min} f - \gamma_{max} n }{f - n} \\ P_{clip,w} &= \phi_{w} \left( P \right) &&= 1 \\ \end{align*}

Assembling the clip space components into the resulting matrix equation, we have

[Pclip,hPclip,vPclip,dPclip,w]=[αmaxαminr(l)00αminrαmax(l)r(l)0βmaxβmint(b)0βmintβmax(b)t(b)00γmaxγminfnγminfγmaxnfn0001][PhPvPdPw].\begin{bmatrix} P_{clip,h} \\ P_{clip,v} \\ P_{clip,d} \\ P_{clip,w} \\ \end{bmatrix} = \begin{bmatrix} \frac{\alpha_{max} - \alpha_{min}}{r - \left( -l \right)} & 0 & 0 & \frac{\alpha_{min}r - \alpha_{max} \left(-l \right) }{r - \left( -l \right)} \\ 0 & \frac{\beta_{max} - \beta_{min}}{t - \left( -b \right)} & 0 & \frac{\beta_{min}t - \beta_{max}\left( -b \right) }{t - \left(-b \right)} \\ 0 & 0 & \frac{\gamma_{max} - \gamma_{min} }{f - n} & \frac{\gamma_{min}f - \gamma_{max}n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} P_{h} \\ P_{v} \\ P_{d} \\ P_{w} \\ \end{bmatrix}.

This yields the second major result, the canonical orthographic projection matrix MorthCM^{C}_{orth}.

This completes the derivation of the canonical orthographic projection matrix.

The Canonical Perspective Matrix

Now that we have the canonical perspective projection matrix and the canonical orthographic projection matrix, we can work out the canonical perspective matrix. The canonical perspective matrix maps from view coordinates to projected coordinates. We show that the perspective projection transformation consists of a perspective transformation multiplied by an orthographic projection, we can get the perspective matrix by premultiplying (108) by (MorthC)1(M^{C}_{orth})^{-1} given by

(MorthC)1=[r+lαmaxαmin00αminrαmax(l)αmaxαmin0t+bβmaxβmin0βmintβmax(b)βmaxβmin00fnγmaxγminγminfγmaxnγmaxγmin0001].\left(M^{C}_{orth}\right)^{-1} = \begin{bmatrix} \frac{r + l}{\alpha_{max} - \alpha_{min}} & 0 & 0 & -\frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{\alpha_{max} - \alpha_{min}} \\ 0 & \frac{t + b}{\beta_{max} - \beta_{min}} & 0 & -\frac{\beta_{min} t - \beta_{max} \left( -b \right)}{\beta_{max} - \beta_{min}} \\ 0 & 0 & \frac{f - n}{\gamma_{max} - \gamma_{min}} & -\frac{\gamma_{min} f - \gamma_{max} n}{\gamma_{max} - \gamma_{min}} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Premultiplying MperCM^{C}_{per} by (MorthC)1(M^{C}_{orth})^{-1} gives

MprojC=(MorthC)1MperC=[r+lαmaxαmin00αminrαmax(l)αmaxαmin0t+bβmaxβmin0βmintβmax(b)βmaxβmin00fnγmaxγminγminfγmaxnγmaxγmin0001][(αmaxαmin)nr(l)0αminrαmax(l)r(l)00(βmaxβmin)nt(b)βmintβmax(b)t(b)000γmaxfγminnfn(γmaxγmin)fnfn0010]=[r+lαmaxαmin00αminr+αmaxlαmaxαmin0t+bβmaxβmin0βmint+βmaxbβmaxβmin00fnγmaxγminγminfγmaxnγmaxγmin0001][(αmaxαmin)nr+l0αminr+αmaxlr+l00(βmaxβmin)nt+bβmint+βmaxbt+b000γmaxfγminnfn(γmaxγmin)fnfn0010]=[n0000n0000f+nfn0010]\begin{align*} M^{C}_{proj} &= \left(M^{C}_{orth}\right)^{-1} M^{C}_{per} \\ &= \begin{bmatrix} \frac{r + l}{\alpha_{max} - \alpha_{min}} & 0 & 0 & -\frac{\alpha_{min} r - \alpha_{max} \left( -l \right)}{\alpha_{max} - \alpha_{min}} \\ 0 & \frac{t + b}{\beta_{max} - \beta_{min}} & 0 & -\frac{\beta_{min} t - \beta_{max} \left( -b \right)}{\beta_{max} - \beta_{min}} \\ 0 & 0 & \frac{f - n}{\gamma_{max} - \gamma_{min}} & -\frac{\gamma_{min} f - \gamma_{max} n}{\gamma_{max} - \gamma_{min}} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{\left( \alpha_{max} - \alpha_{min} \right) n }{r - \left( -l \right)} & 0 & \frac{\alpha_{min}r - \alpha_{max} \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{\left( \beta_{max} - \beta_{min} \right) n }{t - \left( -b \right)} & \frac{\beta_{min}t - \beta_{max} \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{\gamma_{max}f - \gamma_{min}n}{f - n} & -\frac{\left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{r + l}{\alpha_{max} - \alpha_{min}} & 0 & 0 & -\frac{ \alpha_{min} r + \alpha_{max} l }{ \alpha_{max} - \alpha_{min} } \\ 0 & \frac{t + b}{\beta_{max} - \beta_{min}} & 0 & -\frac{ \beta_{min} t + \beta_{max} b }{ \beta_{max} - \beta_{min} } \\ 0 & 0 & \frac{ f - n }{ \gamma_{max} - \gamma_{min} } & -\frac{ \gamma_{min} f - \gamma_{max} n }{ \gamma_{max} - \gamma_{min} } \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ \left( \alpha_{max} - \alpha_{min} \right) n }{ r + l } & 0 & \frac{ \alpha_{min} r + \alpha_{max} l }{ r + l } & 0 \\ 0 & \frac{ \left( \beta_{max} - \beta_{min} \right) n }{ t + b } & \frac{ \beta_{min} t + \beta_{max} b }{ t + b } & 0 \\ 0 & 0 & \frac{ \gamma_{max} f - \gamma_{min} n }{ f - n } & -\frac{ \left( \gamma_{max} - \gamma_{min} \right) f n }{ f - n } \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & f + n & -f n \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

which yields the third major result, the perspective matrix.

This shows that the perspective projection matrix MperCM^{C}_{per} is indeed the product of a projective transformation and an orthographic transformation

MperC=MorthCMprojC.M^{C}_{per} = M^{C}_{orth} M^{C}_{proj}.

Notice that the perspective matrix passes along the input depth coordinate undistorted via the ww component, but nonlinearly distorts the output depth component. Finally, recall the equation (48) for the perspective projection matrix where we deduced that the depth component was an affine transformation. We see from the (167) that θ(Pd)=APd+B=(f+n)Pdfn\theta(P_{d}) = A^{\prime} P_{d} + B^{\prime} = (f + n) P_{d} - f n so that the projected coordinate components from (48) become

Pproj,h=nPhPproj,v=nPvPproj,d=(f+n)PdfnPproj,w=Pd\begin{align*} P_{proj,h} &= n P_{h} \\ P_{proj,v} &= n P_{v} \\ P_{proj,d} &= \left ( f + n \right) P_{d} - f n \\ P_{proj,w} &= P_{d} \\ \end{align*}

which completes the derivation of the unknown constants AA^{\prime} and BB^{\prime} as promised. This completes the derivation of the perspective matrix.

The Canonical Symmetric Vertical Field Of View Perspective Projection Matrix

In the symmetric case, r=lr = l and t=bt = b. The width of the viewport is width=r(l)=r+l\text{width} = r - (-l) = r + l. The height of the viewport is height=t(b)=t+b\text{height} = t - (-b) = t + b. The aspect ratio, denoted aspect\text{aspect}, is given by

aspectwidthheight=r(l)t(b)=r+lt+b=r+rt+t=2r2t=rt\text{aspect} \equiv \frac{\text{width}}{\text{height}} = \frac{r - \left( -l \right)}{t - \left( -b \right)} = \frac{r + l}{t + b} = \frac{r + r}{t + t} = \frac{2 r}{2 t} = \frac{r}{t}

which implies that r=aspecttr = \text{aspect} \cdot t. Since the view volume is symmetric, the tangent of θvfov/2\theta_{vfov} / 2 is tan(θvfov/2)=t/n\tan\left( \theta_{vfov} / 2 \right) = t / n. From these facts we see that

t=b=ntan(θvfov2)r=l=aspectt=aspectntan(θvfov2)t = b = n \tan\left( \frac{\theta_{vfov}}{2} \right) \\ r = l = \text{aspect} \cdot t = \text{aspect} \cdot n \tan\left( \frac{\theta_{vfov}}{2} \right)

We now use (171) inside the general perspective projection matrix (108) to derive the symmetric vertical field of view perspective matrix. Consider the elements of the matrix MperCM^{C}_{per}. The nonzero elements of MperCM^{C}_{per} become

MperC[0,0]=(αmaxαmin)nr(l)=(αmaxαmin)nr+l=(αmaxαmin)n2r=(αmaxαmin2)nr=(αmaxαmin2)naspectntan(θvfov2)=(αmaxαmin2)1aspecttan(θvfov2)MperC[1,1]=(βmaxβmin)nt(b)=(βmaxβmin)nt+b=(βmaxβmin)n2t=(βmaxβmin2)nt=(βmaxβmin2)nntan(θvfov2)=(βmaxβmin2)1tan(θvfov2)MperC[0,2]=αminrαmax(l)r(l)=αminr+αmaxlr+l=αminr+αmaxr2r=αmin+αmax2MperC[1,2]=βmintβmax(b)t(b)=βmint+βmaxbt+b=βmint+βmaxt2t=βmin+βmax2MperC[2,2]=γmaxfγminnfnMperC[2,3]=(γmaxγmin)fnfn\begin{align*} M^{C}_{per}\left[0, 0 \right] = \frac{\left( \alpha_{max} - \alpha_{min} \right) n}{r - \left( -l \right)} &= \frac{\left( \alpha_{max} - \alpha_{min} \right) n}{r + l} \\ &= \frac{\left( \alpha_{max} - \alpha_{min} \right) n}{2 r} \\ &= \left( \frac{\alpha_{max} - \alpha_{min}}{2} \right) \frac{n}{r} \\ &= \left( \frac{\alpha_{max} - \alpha_{min}}{2} \right) \frac{n}{\text{aspect} \cdot n \tan\left( \frac{\theta_{vfov}}{2} \right)} \\ &= \left( \frac{\alpha_{max} - \alpha_{min}}{2} \right) \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} \\ M^{C}_{per}\left[1, 1 \right] = \frac{\left( \beta_{max} - \beta_{min} \right) n}{t - \left( -b \right)} &= \frac{\left( \beta_{max} - \beta_{min} \right) n}{t + b} \\ &= \frac{\left( \beta_{max} - \beta_{min} \right) n}{2 t} \\ &= \left( \frac{\beta_{max} - \beta_{min}}{2} \right) \frac{n}{t} \\ &= \left( \frac{\beta_{max} - \beta_{min}}{2} \right) \frac{n}{n \tan\left( \frac{\theta_{vfov}}{2} \right)} \\ &= \left( \frac{\beta_{max} - \beta_{min}}{2} \right) \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} \\ M^{C}_{per}\left[0, 2 \right] = \frac{\alpha_{min} r - \alpha_{max}\left( -l \right)}{r - \left( -l \right)} &= \frac{\alpha_{min} r + \alpha_{max} l}{r + l} \\ &= \frac{\alpha_{min} r + \alpha_{max} r}{2 r} \\ &= \frac{\alpha_{min} + \alpha_{max}}{2} \\ M^{C}_{per}\left[1, 2 \right] = \frac{\beta_{min} t - \beta_{max}\left( -b \right)}{t - \left( -b \right)} &= \frac{\beta_{min} t + \beta_{max} b}{t + b} \\ &= \frac{\beta_{min} t + \beta_{max} t}{2 t} \\ &= \frac{\beta_{min} + \beta_{max}}{2} \\ M^{C}_{per}\left[2, 2 \right] &= \frac{\gamma_{max} f - \gamma_{min} n}{f - n} \\ M^{C}_{per}\left[2, 3 \right] &= -\frac{\left(\gamma_{max} - \gamma_{min} \right) f n}{f - n} \end{align*}

Substituting (172) back into (108) the matrix MperCM^{C}_{per} takes the form

Mper,vfovC=[(αmaxαmin2)1aspecttan(θvfov2)0αmin+αmax200(βmaxβmin2)1tan(θvfov2)βmin+βmax2000γmaxfγminnfn(γmaxγmin)fnfn0010]M^{C}_{per,vfov} = \begin{bmatrix} \left( \frac{\alpha_{max} - \alpha_{min}}{2} \right) \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & \frac{\alpha_{min} + \alpha_{max}}{2} & 0 \\ 0 & \left( \frac{\beta_{max} - \beta_{min}}{2} \right) \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & \frac{\beta_{min} + \beta_{max}}{2} & 0 \\ 0 & 0 & \frac{\gamma_{max}f - \gamma_{min}n}{f - n} & -\frac{\left( \gamma_{max} - \gamma_{min} \right) f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}

which is the desired formula. This is the fourth major result, the canonical symmetric vertical field of view perspective projection matrix.

How Matrices Transform Under Changes In Coordinates

For any given view coordinate system and clip coordinate system, there exists a perspective projection matrix that can be expressed as Mper=Tclip1MperCTviewM_{per} = T^{-1}_{clip} M^{C}_{per} T_{view} where MperCM^{C}_{per} is the canonical perspective projection matrix. Let [Q][Q] be a homogeneous point in RP3\mathbb{RP}^3. Let QviewQ_{view} be a representive of [Q][Q] in view coordinates, QclipQ_{clip} be a representative of [Q][Q] in clip coordinates, QviewCQ^{C}_{view} be a representive of [Q][Q] in the canonically chosen view coordinate system, QclipCQ^{C}_{clip} be a representive of [Q][Q] in the canonically chosen clip coordinates, such that

QclipC=MperCQviewC.Q^{C}_{clip} = M^{C}_{per} Q^{C}_{view}.

That is, QclipCQ^{C}_{clip} represents the perspective projected point QQ. Let Tview:RP3RP3T_{view} : \mathbb{RP}^{3} \rightarrow \mathbb{RP}^{3} denote the coordinate transformation from view coordinates to the canonical view coordinates. Let Tclip:RP3RP3T_{clip} : \mathbb{RP}^{3} \rightarrow \mathbb{RP}^{3} denote the coordinate transformation from clip coordinates to canonical clip coordinates. The coordinate relations are given by QviewC=TviewQviewCQ^{C}_{view} = T_{view} Q^{C}_{view} and QclipC=TclipQclipCQ^{C}_{clip} = T_{clip} Q^{C}_{clip}. Applying these relationships in (175)

TclipQclip=MperCTviewQviewT_{clip} Q_{clip} = M^{C}_{per} T_{view} Q_{view}

or equivalently

Qclip=Tclip1MperCTviewQview=(Tclip1MperCTview)QviewQ_{clip} = T^{-1}_{clip} M^{C}_{per} T_{view} Q_{view} = \left( T^{-1}_{clip} M^{C}_{per} T_{view} \right) Q_{view}

therefore we identify

MperTclip1MperCTview.M_{per} \equiv T^{-1}_{clip} M^{C}_{per} T_{view}.

This proves the existence of a perspective projection matrix for any source view coordinate system, and any target clip coordinate system. To show uniqueness, suppose that MperM^{\prime}_{per} is another transformation that maps view coordinates to clip coordinates, such that Qclip=MperQviewQ_{clip} = M^{\prime}_{per} Q_{view}. Using the coordinate transformations again, we can write QclipC=TclipQclipQ^{C}_{clip} = T_{clip} Q_{clip} and QviewC=TviewQviewQ^{C}_{view} = T_{view} Q_{view}. Inverting these relations, we get QviewC=Tview1QviewQ^{C}_{view} = T^{-1}_{view} Q_{view} and QclipC=Tclip1QclipQ^{C}_{clip} = T^{-1}_{clip} Q_{clip}. Using the relation for MperM^{\prime}_{per} in equation (178) implies

Tclip1QclipC=MperTview1QviewCT^{-1}_{clip} Q^{C}_{clip} = M^{\prime}_{per} T^{-1}_{view} Q^{C}_{view}

or equivalently

QclipC=TclipMperTview1QviewC=(TclipMperTview1)QviewC.Q^{C}_{clip} = T_{clip} M^{\prime}_{per} T^{-1}_{view} Q^{C}_{view} = \left( T_{clip} M^{\prime}_{per} T^{-1}_{view} \right) Q^{C}_{view}.

Applying the relation for the canonical perspective projection matrix

QclipC=MperCQviewC=(TclipMperTview1)QviewCQ^{C}_{clip} = M^{C}_{per} Q^{C}_{view} = \left( T_{clip} M^{\prime}_{per} T^{-1}_{view} \right) Q^{C}_{view}

which imples that

MperC=TclipMperTview1M^{C}_{per} = T_{clip} M^{\prime}_{per} T^{-1}_{view}

or equivalently

Mper=Tclip1MperCTview=MperM^{\prime}_{per} = T^{-1}_{clip} M^{C}_{per} T_{view} = M_{per}

where the last equality in (183) follows from (178). This proves uniqueness for the perspective projection matrix.

To show that any perspective projection is well-defined, let [Q]RP3[Q] \in \mathbb{RP}^{3} be a point and let Q1Q2Q_{1} \sim Q_{2} be representatives of [Q][Q]. Then there exists λR{0}\lambda \in \mathbb{R} - \{ 0 \} such that Q2=λQ1Q_{2} = \lambda Q_{1}. By linearity of the canonical perspective projection, λMperCQ1=MperC(λQ1)=MperCQ2\lambda M^{C}_{per} Q_{1} = M^{C}_{per} ( \lambda Q_{1} ) = M^{C}_{per} Q_{2} which shows that MperCM^{C}_{per} is well-defined. By the linearity of homogeneous orthogonal transformations

λMperQ1=λTclip1MperCTviewQ1=(Tclip1MperCTview)(λQ1)=(Tclip1MperCTview)Q2=MperQ2=Mper(λQ1)\begin{align*} \lambda M_{per} Q_{1} &= \lambda T^{-1}_{clip} M^{C}_{per} T_{view} Q_{1} \\ &= \left( T^{-1}_{clip} M^{C}_{per} T_{view} \right) \left( \lambda Q_{1} \right) \\ &= \left( T^{-1}_{clip} M^{C}_{per} T_{view} \right) Q_{2} \\ &= M_{per} Q_{2} \\ &= M_{per} \left( \lambda Q_{1} \right) \\ \end{align*}

which shows that MperM_{per} is well-defined. The same argument shows that we can ge the same result for any projective matrix represented in canonical coordinates, leading to our formulas for constructing a perspective matrix, perspective projection matrix, or orthographic projection matrix from any source coordinate system to any target coordinate system which are the formulas we will use to compute the matrices for specific platforms.

Projection Matrices For Specific Software Platforms

We apply the results of the previous sections to calculate the projection matrices for specific software platforms.

OpenGL

We compute the perspective and orthographic transformation matrices for OpenGL.

The Canonical Projection Matrices

The canonical view coordinate system for OpenGL is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T}, where z^\mathbf{\hat{z}} points into the view volume. The canonical view volume in normalized device coordinates is parametrized by [1,1]×[1,1]×[1,1][-1, 1] \times [-1, 1] \times [-1, 1]. The canonical perspective projection matrix for this parametrization is given by

MperC,OpenGL=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010].M^{C, OpenGL}_{per} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

The canonical orthographic projection matrix is given by

MorthC,OpenGL=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001].M^{C, OpenGL}_{orth} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The canonical symmetric vertical field of view perspective projection matrix is given by

Mper,vfovC,OpenGL=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010].M^{C,OpenGL}_{per,vfov} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This finishes the statement of the canonical matrices for OpenGL.

Right-Handed View Space

The right-handed view coordinate system for OpenGL is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points out of the view volume towards the viewer. This is a right-handed coordinate system. The clip coordinate system for OpenGL is the canonical left-handed one. The orthogonal transformations are given by

QlhOpenGL=QrhOpenGL=IQ^{OpenGL}_{lh} = Q^{OpenGL}_{rh} = I

where II is the identity matrix. The change of orientation matrices are given by

Ωrhlh=[1000010000100001],Ωlhlh=[1000010000100001].\Omega_{rh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} , \hspace{4 pt} \Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,rhlhOpenGL=ΩlhlhQlhOpenGLMperC,OpenGLΩrhlhQrhOpenGL=(ΩlhlhQlhOpenGL)MperC,OpenGL(ΩrhlhQrhOpenGL)=(ΩlhlhI)MperC,OpenGL(ΩrhlhI)=ΩlhlhMperC,OpenGLΩrhlh=IMperC,OpenGLΩrhlh=MperC,OpenGLΩrhlh=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010][1000010000100001]=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010]\begin{align*} M^{OpenGL}_{per,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C,OpenGL}_{per} \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C,OpenGL}_{per} \left( \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,OpenGL}_{per} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,OpenGL}_{per} \Omega_{rh \rightarrow lh} \\ &= I M^{C,OpenGL}_{per} \Omega_{rh \rightarrow lh} \\ &= M^{C,OpenGL}_{per} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,rhlhOpenGL=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010].M^{OpenGL}_{per,rh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,rhlhOpenGL=ΩlhlhQlhOpenGLMorthC,OpenGLΩrhlhQrhOpenGL=(ΩlhlhQlhOpenGL)MorthC,OpenGL(ΩrhlhQrhOpenGL)=(ΩlhlhI)MorthC,OpenGL(ΩrhlhI)=ΩlhlhMorthC,OpenGLΩrhlh=IMorthC,OpenGLΩrhlh=MorthC,OpenGLΩrhlh=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001][1000010000100001]=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001]\begin{align*} M^{OpenGL}_{orth,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C, OpenGL}_{orth} \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C, OpenGL}_{orth} \left( \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, OpenGL}_{orth} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, OpenGL}_{orth} \Omega_{rh \rightarrow lh} \\ &= I M^{C, OpenGL}_{orth} \Omega_{rh \rightarrow lh} \\ &= M^{C, OpenGL}_{orth} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,rhlhOpenGL=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001].M^{OpenGL}_{orth,rh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,rhlhOpenGL=ΩlhlhQlhOpenGLMper,vfovC,OpenGLΩrhlhQrhOpenGL=(ΩlhlhQlhOpenGL)Mper,vfovC,OpenGL(ΩrhlhQrhOpenGL)=(ΩlhlhI)Mper,vfovC,OpenGL(ΩrhlhI)=ΩlhlhMper,vfovC,OpenGLΩrhlh=IMper,vfovC,OpenGLΩrhlh=Mper,vfovC,OpenGLΩrhlh=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010][1000010000100001]=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010]\begin{align*} M^{OpenGL}_{per,vfov,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C,OpenGL}_{per,vfov} \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C,OpenGL}_{per,vfov} \left( \Omega_{rh \rightarrow lh} Q^{OpenGL}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,OpenGL}_{per,vfov} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,OpenGL}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= I M^{C,OpenGL}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= M^{C,OpenGL}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,rhlhOpenGL=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010].M^{OpenGL}_{per,vfov,rh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

This completes the calculation of the matrices for the right-handed OpenGL view coordinates.

Left-Handed View Space

The left-handed view space coordinate system for OpenGL is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points into the view volume away from the viewer. This is a left-handed coordinate system. The clip coordinate system is the canonical left-handed one. The orthogonal transformation is given by

QlhOpenGL=IQ^{OpenGL}_{lh} = I

where II is the identity matrix. The change of orientation matrix are given by

Ωlhlh=[1000010000100001].\Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,lhlhOpenGL=ΩlhlhQlhOpenGLMperC,OpenGLΩlhlhQlhOpenGL=(ΩlhlhQlhOpenGL)MperC,OpenGL(ΩlhlhQlhOpenGL)=(ΩlhlhI)MperC,OpenGL(ΩlhlhI)=ΩlhlhMperC,OpenGLΩlhlh=IMperC,OpenGLI=MperC,OpenGL=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010]\begin{align*} M^{OpenGL}_{per,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C,OpenGL}_{per} \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C,OpenGL}_{per} \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,OpenGL}_{per} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,OpenGL}_{per} \Omega_{lh \rightarrow lh} \\ &= I M^{C,OpenGL}_{per} I \\ &= M^{C,OpenGL}_{per} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,lhlhOpenGL=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000f+nfn2fnfn0010].M^{OpenGL}_{per,lh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,lhlhOpenGL=ΩlhlhQlhOpenGLMorthC,OpenGLΩlhlhQlhOpenGL=(ΩlhlhQlhOpenGL)MorthC,OpenGL(ΩlhlhQlhOpenGL)=(ΩlhlhI)MorthC,OpenGL(ΩlhlhI)=ΩlhlhMorthC,OpenGLΩlhlh=IMorthC,OpenGLI=MorthC,OpenGL=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001]\begin{align*} M^{OpenGL}_{orth,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C, OpenGL}_{orth} \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C, OpenGL}_{orth} \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, OpenGL}_{orth} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, OpenGL}_{orth} \Omega_{lh \rightarrow lh} \\ &= I M^{C, OpenGL}_{orth} I \\ &= M^{C, OpenGL}_{orth} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,lhlhOpenGL=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)002fnf+nfn0001].M^{OpenGL}_{orth,lh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,lhlhOpenGL=ΩlhlhQlhOpenGLMper,vfovC,OpenGLΩlhlhQlhOpenGL=(ΩlhlhQlhOpenGL)Mper,vfovC,OpenGL(ΩlhlhQlhOpenGL)=(ΩlhlhI)Mper,vfovC,OpenGL(ΩlhlhI)=ΩlhlhMper,vfovC,OpenGLΩlhlh=IMper,vfovC,OpenGLI=Mper,vfovC,OpenGL=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010]\begin{align*} M^{OpenGL}_{per,vfov,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} M^{C,OpenGL}_{per,vfov} \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) M^{C,OpenGL}_{per,vfov} \left( \Omega_{lh \rightarrow lh} Q^{OpenGL}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,OpenGL}_{per,vfov} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,OpenGL}_{per,vfov} \Omega_{lh \rightarrow lh} \\ &= I M^{C,OpenGL}_{per,vfov} I \\ &= M^{C,OpenGL}_{per,vfov} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,lhlhOpenGL=[1aspecttan(θvfov2)00001tan(θvfov2)0000f+nfn2fnfn0010].M^{OpenGL}_{per,vfov,lh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f + n}{f - n} & -\frac{ 2 f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This completes the computation of the matrices for the left-handed OpenGL view coordinates.

Comparing Coordinate System Orientations

Let us illustrate why the coordinate systems in this section have a left-handed orientation or right-handed orientation. By convention, the standard basis on R3\mathbb{R}^{3} has a right-handed orientation. Recall that the standard basis on R3\mathbb{R}^{3} is the tuple of vectors (x^,y^,z^)(\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, and z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} are the standard basis vectors. In this basis, OpenGL’s left-handed view coordinates and clip coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & -\mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \\ \end{bmatrix} = 1 \cdot 1 \cdot -1 = -1

and OpenGL’s right-handed view coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & \mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} = 1 \cdot 1 \cdot 1 = 1

so the right-handed OpenGL view coordinate system indeed has a right-handed orientation, and the left-handed view coordinate system and clip coordinate system have a left-handed orientation.

DirectX

We compute the perspective and orthographic transformation matrices for DirectX.

The Canonical Matrices

The canonical view space coordinate system for DirectX is the frame (0,(x^,y^,z^)(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T}, where z^\mathbf{\hat{z}} points into the view volume. The canonical view volume in normalized device coordinates is parametrized by [1,1]×[1,1]×[0,1][-1, 1] \times [-1, 1] \times [0, 1]. The canonical perspective projection matrix for this parametrization is given by

MperC,DirectX=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{C, DirectX}_{per} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

The canonical orthographic projection matrix for DirectX is given by

MorthC,DirectX=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{C, DirectX}_{orth} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The canonical symmetric vertical field of view perspective projection matrix for DirectX is given by

Mper,vfovC,DirectX=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{C,DirectX}_{per,vfov} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This finishes the statement of the canonical matrices for DirectX.

Right-Handed View Space

The right-handed view coordinate system for DirectX is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points out of the view volume towards the viewer. This is a right-handed coordinate system. The clip coordinate system for DirectX is the canonical left-handed one. The orthogonal transformations are given by

QlhDirectX=QrhDirectX=IQ^{DirectX}_{lh} = Q^{DirectX}_{rh} = I

where II is the identity matrix. The change of orientation matrices are given by

Ωrhlh=[1000010000100001],Ωlhlh=[1000010000100001].\Omega_{rh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} , \hspace{4 pt} \Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,rhlhDirectX=ΩlhlhQlhDirectXMperC,DirectXΩrhlhQrhDirectX=(ΩlhlhQlhDirectX)MperC,DirectX(ΩrhlhQrhDirectX)=(ΩlhlhI)MperC,DirectX(ΩrhlhI)=ΩlhlhMperC,DirectXΩrhlh=IMperC,DirectXΩrhlh=MperC,DirectXΩrhlh=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010][1000010000100001]=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]\begin{align*} M^{DirectX}_{per,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C,DirectX}_{per} \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C,DirectX}_{per} \left( \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,DirectX}_{per} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,DirectX}_{per} \Omega_{rh \rightarrow lh} \\ &= I M^{C,DirectX}_{per} \Omega_{rh \rightarrow lh} \\ &= M^{C,DirectX}_{per} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,rhlhDirectX=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{DirectX}_{per,rh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,rhlhDirectX=ΩlhlhQlhDirectXMorthC,DirectXΩrhlhQrhDirectX=(ΩlhlhQlhDirectX)MorthC,DirectX(ΩrhlhQrhDirectX)=(ΩlhlhI)MorthC,DirectX(ΩrhlhI)=ΩlhlhMorthC,DirectXΩrhlh=IMorthC,DirectXΩrhlh=MorthC,DirectXΩrhlh=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001][1000010000100001]=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]\begin{align*} M^{DirectX}_{orth,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C, DirectX}_{orth} \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C, DirectX}_{orth} \left( \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, DirectX}_{orth} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, DirectX}_{orth} \Omega_{rh \rightarrow lh} \\ &= I M^{C, DirectX}_{orth} \Omega_{rh \rightarrow lh} \\ &= M^{C, DirectX}_{orth} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,rhlhDirectX=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{DirectX}_{orth,rh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,rhlhDirectX=ΩlhlhQlhDirectXMper,vfovC,DirectXΩrhlhQrhDirectX=(ΩlhlhQlhDirectX)Mper,vfovC,DirectX(ΩrhlhQrhDirectX)=(ΩlhlhI)Mper,vfovC,DirectX(ΩrhlhI)=ΩlhlhMper,vfovC,DirectXΩrhlh=IMper,vfovC,DirectXΩrhlh=Mper,vfovC,DirectXΩrhlh=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010][1000010000100001]=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{DirectX}_{per,vfov,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C,DirectX}_{per,vfov} \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C,DirectX}_{per,vfov} \left( \Omega_{rh \rightarrow lh} Q^{DirectX}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,DirectX}_{per,vfov} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,DirectX}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= I M^{C,DirectX}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= M^{C,DirectX}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,rhlhDirectX=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{DirectX}_{per,vfov,rh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

This completes the computation of the matrices for the right-handed DirectX view coordinates.

Left-Handed View Space

The left-handed view coordinate system for OpenGL is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points into the view volume away from the viewer. This is a right-handed coordinate system. The clip coordinate system is the canonical left-handed one. The orthogonal transformation is given by

QlhDirectX=IQ^{DirectX}_{lh} = I

where II is the identity matrix. The change of orientation matrix are given by

Ωlhlh=[1000010000100001].\Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,lhlhDirectX=ΩlhlhQlhDirectXMperC,DirectXΩlhlhQlhDirectX=(ΩlhlhQlhDirectX)MperC,DirectX(ΩlhlhQlhDirectX)=(ΩlhlhI)MperC,DirectX(ΩrllhI)=ΩlhlhMperC,DirectXΩlhlh=IMperC,DirectXI=MperC,DirectX=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]\begin{align*} M^{DirectX}_{per,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C,DirectX}_{per} \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C,DirectX}_{per} \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,DirectX}_{per} \left( \Omega_{rl \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,DirectX}_{per} \Omega_{lh \rightarrow lh} \\ &= I M^{C,DirectX}_{per} I \\ &= M^{C,DirectX}_{per} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,lhlhDirectX=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{DirectX}_{per,lh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,lhlhDirectX=ΩlhlhQlhDirectXMorthC,DirectXΩlhlhQlhDirectX=(ΩlhlhQlhDirectX)MorthC,DirectX(ΩlhlhQlhDirectX)=(ΩlhlhI)MorthC,DirectX(ΩlhlhI)=ΩlhlhMorthC,DirectXΩlhlh=IMorthC,DirectXI=MorthC,DirectX=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]\begin{align*} M^{DirectX}_{orth,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C, DirectX}_{orth} \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C, DirectX}_{orth} \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, DirectX}_{orth} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, DirectX}_{orth} \Omega_{lh \rightarrow lh} \\ &= I M^{C, DirectX}_{orth} I \\ &= M^{C, DirectX}_{orth} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,lhlhDirectX=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{DirectX}_{orth,lh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,lhlhDirectX=ΩlhlhQlhDirectXMper,vfovC,DirectXΩlhlhQlhDirectX=(ΩlhlhQlhDirectX)Mper,vfovC,DirectX(ΩlhlhQlhDirectX)=(ΩlhlhI)Mper,vfovC,DirectX(ΩlhlhI)=ΩlhlhMper,vfovC,DirectXΩlhlh=IMper,vfovC,DirectXI=Mper,vfovC,DirectX=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{DirectX}_{per,vfov,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} M^{C,DirectX}_{per,vfov} \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) M^{C,DirectX}_{per,vfov} \left( \Omega_{lh \rightarrow lh} Q^{DirectX}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,DirectX}_{per,vfov} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,DirectX}_{per,vfov} \Omega_{lh \rightarrow lh} \\ &= I M^{C,DirectX}_{per,vfov} I \\ &= M^{C,DirectX}_{per,vfov} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,lhlhDirectX=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{DirectX}_{per,vfov,lh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This completes the computation of the matrices for the left-handed DirectX view coordinates.

Comparing Coordinate System Orientations

Let us illustrate why the coordinate systems in this section have a left-handed orientation or right-handed orientation. By convention, the standard basis on R3\mathbb{R}^{3} has a right-handed orientation. Recall that the standard basis on R3\mathbb{R}^{3} is the tuple of vectors (x^,y^,z^)(\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, and z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} are the standard basis vectors. In this basis, DirectX’s left-handed view coordinates and clip coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & -\mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \\ \end{bmatrix} = 1 \cdot 1 \cdot -1 = -1

and DirectX’s right-handed view coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & \mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} = 1 \cdot 1 \cdot 1 = 1

so the right-handed DirectX view coordinate system indeed has a right-handed orientation, and the left-handed view coordinate system and clip coordinate system have a left-handed orientation.

Metal

We compute the perspective and orthographic transformation matrices for Metal.

The Canonical Matrices

The canonical view space coordinate system for Metal is the frame (0,(x^,y^,z^)(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T}, where z^\mathbf{\hat{z}} points into the view volume. The canonical view volume for for Metal in normalized device coordinates is parametrized by [1,1]×[1,1]×[0,1][-1, 1] \times [-1, 1] \times [0, 1]. The canonical perspective projection matrix for Metal is given by

MperC,Metal=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{C, Metal}_{per} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} .

The canonical orthographic projection matrix for Metal is given by

MorthC,Metal=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{C, Metal}_{orth} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} .

The canonical symmetric vertical field of view perspective projection matrix for Metal is given by

Mper,vfovC,Metal=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{C,Metal}_{per,vfov} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This finishes the statement of the canonical matrices for Metal.

Right-Handed View Space

The right-handed view space coordinate system for Metal is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points out of the view volume towards the viewer. This is a right-handed coordinate system. The clip coordinate system for Metal is the canonical left-handed one. The orthogonal transformations are given by

QlhMetal=QrhMetal=IQ^{Metal}_{lh} = Q^{Metal}_{rh} = I

where II is the identity matrix. The change of orientation matrices are given by

Ωrhlh=[1000010000100001],Ωlhlh=[1000010000100001].\Omega_{rh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} , \hspace{4 pt} \Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,rhlhMetal=ΩlhlhQlhMetalMperC,MetalΩrhlhQrhMetal=(ΩlhlhQlhMetal)MperC,Metal(ΩrhlhQrhMetal)=(ΩlhlhI)MperC,Metal(ΩrhlhI)=ΩlhlhMperC,MetalΩrhlh=IMperC,MetalΩrhlh=MperC,MetalΩrhlh=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010][1000010000100001]=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]\begin{align*} M^{Metal}_{per,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C,Metal}_{per} \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C,Metal}_{per} \left( \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,Metal}_{per} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,Metal}_{per} \Omega_{rh \rightarrow lh} \\ &= I M^{C,Metal}_{per} \Omega_{rh \rightarrow lh} \\ &= M^{C,Metal}_{per} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \end{bmatrix} \end{align*}

therefore

Mper,rhlhMetal=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{Metal}_{per,rh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,rhlhMetal=ΩlhlhQlhMetalMorthC,MetalΩrhlhQrhMetal=(ΩlhlhQlhMetal)MorthC,Metal(ΩrhlhQrhMetal)=(ΩlhlhI)MorthC,Metal(ΩrhlhI)=ΩlhlhMorthC,MetalΩrhlh=IMorthC,MetalΩrhlh=MorthC,MetalΩrhlh=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001][1000010000100001]=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]\begin{align*} M^{Metal}_{orth,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C, Metal}_{orth} \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C, Metal}_{orth} \left( \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, Metal}_{orth} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, Metal}_{orth} \Omega_{rh \rightarrow lh} \\ &= I M^{C, Metal}_{orth} \Omega_{rh \rightarrow lh} \\ &= M^{C, Metal}_{orth} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \end{bmatrix} \end{align*}

therefore

Morth,rhlhMetal=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{Metal}_{orth,rh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,rhlhMetal=ΩlhlhQlhMetalMper,vfovC,MetalΩrhlhQrhMetal=(ΩlhlhQlhMetal)Mper,vfovC,Metal(ΩrhlhQrhMetal)=(ΩlhlhI)Mper,vfovC,Metal(ΩrhlhI)=ΩlhlhMper,vfovC,MetalΩrhlh=IMper,vfovC,MetalΩrhlh=Mper,vfovC,MetalΩrhlh=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010][1000010000100001]=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{Metal}_{per,vfov,rh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C,Metal}_{per,vfov} \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C,Metal}_{per,vfov} \left( \Omega_{rh \rightarrow lh} Q^{Metal}_{rh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,Metal}_{per,vfov} \left( \Omega_{rh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,Metal}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= I M^{C,Metal}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= M^{C,Metal}_{per,vfov} \Omega_{rh \rightarrow lh} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,rhlhMetal=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{Metal}_{per,vfov,rh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

This completes the computation of the matrices for the right-handed Metal view coordinates.

Left-Handed View Space

The left-handed view space coordinate system for Metal is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points into the view volume away from the viewer. This is a right-handed coordinate system. The clip coordinate system is the canonical left-handed one. The orthogonal transformation is given by

QlhMetal=IQ^{Metal}_{lh} = I

where II is the identity matrix. The change of orientation matrix are given by

Ωlhlh=[1000010000100001].\Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,lhlhMetal=ΩlhlhQlhMetalMperC,MetalΩlhlhQlhMetal=(ΩlhlhQlhMetal)MperC,Metal(ΩlhlhQlhMetal)=(ΩlhlhI)MperC,Metal(ΩrllhI)=ΩlhlhMperC,MetalΩlhlh=IMperC,MetalI=MperC,Metal=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]\begin{align*} M^{Metal}_{per,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C,Metal}_{per} \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C,Metal}_{per} \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,Metal}_{per} \left( \Omega_{rl \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,Metal}_{per} \Omega_{lh \rightarrow lh} \\ &= I M^{C,Metal}_{per} I \\ &= M^{C,Metal}_{per} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \end{bmatrix} \end{align*}

therefore

Mper,lhlhMetal=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{Metal}_{per,lh \rightarrow lh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,lhlhMetal=ΩlhlhQlhMetalMorthC,MetalΩlhlhQlhMetal=(ΩlhlhQlhMetal)MorthC,Metal(ΩlhlhQlhMetal)=(ΩlhlhI)MorthC,Metal(ΩlhlhI)=ΩlhlhMorthC,MetalΩlhlh=IMorthC,MetalI=MorthC,Metal=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]\begin{align*} M^{Metal}_{orth,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C, Metal}_{orth} \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C, Metal}_{orth} \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C, Metal}_{orth} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C, Metal}_{orth} \Omega_{lh \rightarrow lh} \\ &= I M^{C, Metal}_{orth} I \\ &= M^{C, Metal}_{orth} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \end{bmatrix} \end{align*}

therefore

Morth,lhlhMetal=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{Metal}_{orth,lh \rightarrow lh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,lhlhMetal=ΩlhlhQlhMetalMper,vfovC,MetalΩlhlhQlhMetal=(ΩlhlhQlhMetal)Mper,vfovC,Metal(ΩlhlhQlhMetal)=(ΩlhlhI)Mper,vfovC,Metal(ΩlhlhI)=ΩlhlhMper,vfovC,MetalΩlhlh=IMper,vfovC,MetalI=Mper,vfovC,Metal=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{Metal}_{per,vfov,lh \rightarrow lh} &= \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} M^{C,Metal}_{per,vfov} \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \\ &= \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) M^{C,Metal}_{per,vfov} \left( \Omega_{lh \rightarrow lh} Q^{Metal}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow lh} I \right) M^{C,Metal}_{per,vfov} \left( \Omega_{lh \rightarrow lh} I \right) \\ &= \Omega_{lh \rightarrow lh} M^{C,Metal}_{per,vfov} \Omega_{lh \rightarrow lh} \\ &= I M^{C,Metal}_{per,vfov} I \\ &= M^{C,Metal}_{per,vfov} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \end{bmatrix} \end{align*}

therefore

Mper,vfov,lhlhMetal=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{Metal}_{per,vfov,lh \rightarrow lh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \end{bmatrix}.

This completes the computation of the matrices for the left-handed Metal view coordinates.

Comparing Coordinate System Orientations

Let us illustrate why the coordinate systems in this section have a left-handed orientation or right-handed orientation. By convention, the standard basis on R3\mathbb{R}^{3} has a right-handed orientation. Recall that the standard basis on R3\mathbb{R}^{3} is the tuple of vectors (x^,y^,z^)(\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, and z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} are the standard basis vectors. In this basis, Metal’s left-handed view coordinates and clip coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & -\mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \\ \end{bmatrix} = 1 \cdot 1 \cdot -1 = -1

and Metal’s right-handed view coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & \mathbf{\hat{y}} & \mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} = 1 \cdot 1 \cdot 1 = 1

so the right-handed Metal view coordinate system indeed has a right-handed orientation, and the left-handed view coordinate system and clip coordinate system have a left-handed orientation.

Vulkan

We compute the perspective and orthographic transformation matrices for Vulkan.

The Canonical Matrices

The canonical view coordinate system for Vulkan is the frame (0,(x^,y^,z^)(\mathbf{0}, (\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T}, where z^\mathbf{\hat{z}} points into the view volume. The canonical view volume for for Vulkan in normalized device coordinates is parametrized by [1,1]×[1,1]×[0,1][-1, 1] \times [-1, 1] \times [0, 1]. The canonical perspective projection matrix for Vulkan is given by

MperC,Vulkan=[2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010].M^{C, Vulkan}_{per} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

The canonical orthographic projection matrix for Vulkan is given by

MorthC,Vulkan=[2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001].M^{C, Vulkan}_{orth} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The canonical symmetric vertical field of view perspective projection matrix for Vulkan is given by

Mper,vfovC,Vulkan=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]M^{C, Vulkan}_{per,vfov} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}

This finishes the statement of the canonical matrices for Vulkan.

Right-Handed View Space

The right-handed view coordinate system for Vulkan is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, -\mathbf{\hat{y}}, \mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^\mathbf{\hat{z}} points into the view volume away from the viewer. Notice that the vertical axis points down in this frame. This is a right-handed coordinate system. The clip coordinate system for Vulkan is the same as the right-handed view coordinate system. A homogeneous rotation about the x-axis is defined as

Rx(θ)=[10000cos(θ)sin(θ)00sin(θ)cos(θ)00001].R_{x}\left( \theta \right) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\left( \theta \right) & -\sin\left( \theta \right) & 0 \\ 0 & \sin\left( \theta \right) & \cos\left( \theta \right) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The orthogonal transformations for the right-handed Vulkan view coordinates are given by

QrhVulkan=Rx(π)=[10000cos(π)sin(π)00sin(π)cos(π)00001]=[1000010000100001]QlhVulkan=Rx(π)=[10000cos(π)sin(π)00sin(π)cos(π)00001]=[1000010000100001].Q^{Vulkan}_{rh} = R_{x}\left( \pi \right) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\left( \pi \right) & -\sin\left( \pi \right) & 0 \\ 0 & \sin\left( \pi \right) & \cos\left( \pi \right) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ Q^{Vulkan}_{lh} = R_{x}\left( -\pi \right) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\left( -\pi \right) & -\sin\left( -\pi \right) & 0 \\ 0 & \sin\left( -\pi \right) & \cos\left( -\pi \right) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The change of orientation matrices are given by

Ωrhlh=[1000010000100001],Ωlhrh=[1000010000100001].\Omega_{rh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} , \hspace{4 pt} \Omega_{lh \rightarrow rh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,rhrhVulkan=Ωlhrh(QlhVulkan)1MperC,VulkanΩrhlhQrhVulkan=(Ωlhrh(QlhVulkan)1)MperC,Vulkan(ΩrhlhQrhVulkan)=([1000010000100001][1000010000100001])MperC,Vulkan([1000010000100001][1000010000100001])=[1000010000100001]MperC,Vulkan[1000010000100001]=[1000010000100001][2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010][1000010000100001]=[1000010000100001][2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]=[1000010000100001][2nr+l0rlr+l002nt+btbt+b000ffnfnfn0010]=[1000010000100001][2nr+l0rlr+l002nb+tbtb+t000ffnfnfn0010]=[2nr+l0rlr+l002nb+tbtb+t000ffnfnfn0010]=[2nr(l)0r+(l)r(l)002nb(t)b+(t)b(t)000ffnfnfn0010]\begin{align*} M^{Vulkan}_{per, rh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{per} \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per} \left( \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \right) \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{per} \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} M^{C,Vulkan}_{per} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & -\frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & -\frac{r - l}{r + l} & 0 \\ 0 & -\frac{ 2 n }{t + b} & -\frac{t - b}{t + b} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & -\frac{r - l}{r + l} & 0 \\ 0 & -\frac{ 2 n }{b + t} & \frac{b - t}{b + t} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & -\frac{r - l}{r + l} & 0 \\ 0 & \frac{ 2 n }{b + t} & -\frac{b - t}{b + t} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{b - \left( -t \right)} & -\frac{b + \left( -t \right)}{b - \left( -t \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,rhrhVulkan=[2nr(l)0r+(l)r(l)002nb(t)b+(t)b(t)000ffnfnfn0010].M^{Vulkan}_{per, rh \rightarrow rh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{b - \left( -t \right)} & -\frac{b + \left( -t \right)}{b - \left( -t \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,rhrhVulkan=Ωlhrh(QlhVulkan)1MorthC,VulkanΩrhlhQrhVulkan=(Ωlhrh(QlhVulkan)1)MorthC,Vulkan(ΩrhlhQrhVulkan)=([1000010000100001][1000010000100001])MorthC,Vulkan([1000010000100001][1000010000100001])=[1000010000100001]MorthC,Vulkan[1000010000100001]=[1000010000100001][2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001][1000010000100001]=[1000010000100001][2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]=[1000010000100001][2r+l00rlr+l02t+b0tbt+b001fnnfn0001]=[1000010000100001][2r+l00rlr+l02b+t0btb+t001fnnfn0001]=[2r+l00rlr+l02b+t0btb+t001fnnfn0001]=[2r(l)00r+(l)r(l)02b(t)0b+(t)b(t)001fnnfn0001]\begin{align*} M^{Vulkan}_{orth, rh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{orth} \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{orth} \left( \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \right) \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{orth} \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} M^{C,Vulkan}_{orth} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & -\frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & -\frac{2}{t + b} & 0 & -\frac{t - b}{t + b} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & -\frac{2}{b + t} & 0 & \frac{b - t}{b + t} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & \frac{2}{b + t} & 0 & -\frac{b - t}{b + t} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{b - \left( -t \right)} & 0 & -\frac{b + \left( -t \right)}{b - \left( -t \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,rhrhVulkan=[2r(l)00r+(l)r(l)02b(t)0b+(t)b(t)001fnnfn0001].M^{Vulkan}_{orth, rh \rightarrow rh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{b - \left( -t \right)} & 0 & -\frac{b + \left( -t \right)}{b - \left( -t \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,rhrhVulkan=Ωlhrh(QlhVulkan)1Mper,vfovC,VulkanΩrhlhQrhVulkan=(Ωlhrh(QlhVulkan)1)Mper,vfovC,Vulkan(ΩrhlhQrhVulkan)=([1000010000100001][1000010000100001])Mper,vfovC,Vulkan([1000010000100001][1000010000100001])=[1000010000100001]Mper,vfovC,Vulkan[1000010000100001]=[1000010000100001][1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010][1000010000100001]=[1000010000100001][1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{Vulkan}_{per,vfov,rh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{per,vfov} \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per,vfov} \left( \Omega_{rh \rightarrow lh} Q^{Vulkan}_{rh} \right) \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{per,vfov} \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} M^{C,Vulkan}_{per,vfov} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & -\frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,rhrhVulkan=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{Vulkan}_{per,vfov,rh \rightarrow rh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}.

This completes the computation of the matrices for the right-handed Vulkan view coordinates.

Left-Handed View Space

The right-handed view space coordinate system for Vulkan is the frame (0,(x^,y^,z^))(\mathbf{0}, (\mathbf{\hat{x}}, -\mathbf{\hat{y}}, -\mathbf{\hat{z}})) in R3\mathbb{R}^{3}, where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} where z^-\mathbf{\hat{z}} points out of the view volume towards the viewer. Notice that the vertical axis points down in this frame. This is a left-handed coordinate system. The clip coordinate system for Vulkan is the same as the right-handed view coordinate system. A homogeneous rotation about the x-axis is defined as

Rx(θ)=[10000cos(θ)sin(θ)00sin(θ)cos(θ)00001].R_{x}\left( \theta \right) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\left( \theta \right) & -\sin\left( \theta \right) & 0 \\ 0 & \sin\left( \theta \right) & \cos\left( \theta \right) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The orthogonal transformations for the left-handed Vulkan view coordinates are given by

QlhVulkan=Rx(π)=[10000cos(π)sin(π)00sin(π)cos(π)00001]=[1000010000100001].Q^{Vulkan}_{lh} = R_{x}\left( \pi \right) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\left( \pi \right) & -\sin\left( \pi \right) & 0 \\ 0 & \sin\left( \pi \right) & \cos\left( \pi \right) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

The change of orientation matrices are given by

Ωlhlh=[1000010000100001],Ωlhrh=[1000010000100001].\Omega_{lh \rightarrow lh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} , \hspace{4 pt} \Omega_{lh \rightarrow rh} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

To compute the projections, we need to transform from the chosen view coordinates to the canonical view coordinates, apply the canonical projection, and then transform from the canonical clip coordinates to the target clip coordinates. We can map any view coordinates to any clip coordinates using the same process. Each coordinate transformation is the product of an orthogonal transform and a change of orientation matrix. Let us calculate the perspective projection

Mper,lhrhVulkan=Ωlhrh(QlhVulkan)1MperC,VulkanΩlhlhQlhVulkan=(Ωlhrh(QlhVulkan)1)MperC,Vulkan(ΩlhlhQlhVulkan)=(Ωlhrh(QlhVulkan)1)MperC,Vulkan(IQlhVulkan)=(Ωlhrh(QlhVulkan)1)MperC,VulkanQlhVulkan=([1000010000100001][1000010000100001])MperC,Vulkan[1000010000100001]=[1000010000100001]MperC,Vulkan[1000010000100001]=[1000010000100001][2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010][1000010000100001]=[1000010000100001][2nr(l)0r+(l)r(l)002nt(b)t+(b)t(b)000ffnfnfn0010]=[1000010000100001][2nr+l0rlr+l002nt+btbt+b000ffnfnfn0010]=[1000010000100001][2nr+l0rlr+l002nb+tbtb+t000ffnfnfn0010]=[2nr+l0rlr+l002nb+tbtb+t000ffnfnfn0010]=[2nr(l)0r+(l)r(l)002nb(t)b+(t)b(t)000ffnfnfn0010]\begin{align*} M^{Vulkan}_{per, lh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{per} \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \\ &= \left( \Omega_{lh \rightarrow rh} \left( Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per} \left( \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left( Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per} \left( I Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left( Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per} Q^{Vulkan}_{lh} \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{per} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} M^{C,Vulkan}_{per} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{t - \left( -b \right)} & -\frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & -\frac{ 2 n }{t - \left( -b \right)} & \frac{t + \left( -b \right)}{t - \left( -b \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & \frac{r - l}{r + l} & 0 \\ 0 & -\frac{ 2 n }{t + b} & \frac{t - b}{t + b} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & \frac{r - l}{r + l} & 0 \\ 0 & -\frac{ 2 n }{b + t} & -\frac{b - t}{b + t} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r + l} & 0 & \frac{r - l}{r + l} & 0 \\ 0 & \frac{ 2 n }{b + t} & \frac{b - t}{b + t} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{b - \left( -t \right)} & \frac{b + \left( -t \right)}{b - \left( -t \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,lhrhVulkan=[2nr(l)0r+(l)r(l)002nb(t)b+(t)b(t)000ffnfnfn0010].M^{Vulkan}_{per, lh \rightarrow rh} = \begin{bmatrix} \frac{ 2 n }{r - \left( -l \right)} & 0 & \frac{r + \left( -l \right)}{r - \left( -l \right)} & 0 \\ 0 & \frac{ 2 n }{b - \left( -t \right)} & \frac{b + \left( -t \right)}{b - \left( -t \right)} & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

Here is the calculation for the orthographic matrix

Morth,lhrhVulkan=Ωlhrh(QlhVulkan)1MorthC,VulkanΩlhlhQlhVulkan=(Ωlhrh(QlhVulkan)1)MorthC,Vulkan(ΩlhlhQlhVulkan)=(Ωlhrh(QlhVulkan)1)MorthC,Vulkan(IQlhVulkan)=(Ωlhrh(QlhVulkan)1)MorthC,VulkanQlhVulkan=([1000010000100001][1000010000100001])MorthC,Vulkan[1000010000100001]=[1000010000100001]MorthC,Vulkan[1000010000100001]=[1000010000100001][2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001][1000010000100001]=[1000010000100001][2r(l)00r+(l)r(l)02t(b)0t+(b)t(b)001fnnfn0001]=[1000010000100001][2r+l00rlr+l02t+b0tbt+b001fnnfn0001]=[1000010000100001][2r+l00rlr+l02b+t0btb+t001fnnfn0001]=[2r+l00rlr+l02b+t0btb+t001fnnfn0001]=[2r(l)00r+(l)r(l)02b(t)0b+(t)b(t)001fnnfn0001]\begin{align*} M^{Vulkan}_{orth, lh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{orth} \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{orth} \left( \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{orth} \left( I Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{orth} Q^{Vulkan}_{lh} \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{orth} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} M^{C,Vulkan}_{orth} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & \frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & -\frac{2}{t - \left( -b \right)} & 0 & -\frac{t + \left( -b \right)}{t - \left( -b \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & -\frac{2}{t + b} & 0 & -\frac{t - b}{t + b} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & -\frac{2}{b + t} & 0 & \frac{b - t}{b + t} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r + l} & 0 & 0 & -\frac{r - l}{r + l} \\ 0 & \frac{2}{b + t} & 0 & -\frac{b - t}{b + t} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{b - \left( -t \right)} & 0 & -\frac{b + \left( -t \right)}{b - \left( -t \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{align*}

therefore

Morth,lhrhVulkan=[2r(l)00r+(l)r(l)02b(t)0b+(t)b(t)001fnnfn0001].M^{Vulkan}_{orth, lh \rightarrow rh} = \begin{bmatrix} \frac{2}{r - \left( -l \right)} & 0 & 0 & -\frac{r + \left( -l \right)}{r - \left( -l \right)} \\ 0 & \frac{2}{b - \left( -t \right)} & 0 & -\frac{b + \left( -t \right)}{b - \left( -t \right)} \\ 0 & 0 & -\frac{1}{f - n} & -\frac{n}{f - n} \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}.

Finally, we calculate the matrix for the symmetric vertical field of view perspective projection

Mper,vfov,lhrhVulkan=Ωlhrh(QlhVulkan)1Mper,vfovC,VulkanΩlhlhQlhVulkan=(Ωlhrh(QlhVulkan)1)Mper,vfovC,Vulkan(ΩlhlhQlhVulkan)=(Ωlhrh(QlhVulkan)1)Mper,vfovC,Vulkan(IQlhVulkan)=(Ωlhrh(QlhVulkan)1)Mper,vfovC,VulkanQlhVulkan=([1000010000100001][1000010000100001])Mper,vfovC,Vulkan[1000010000100001]=[1000010000100001]Mper,vfovC,Vulkan[1000010000100001]=[1000010000100001][1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010][1000010000100001]=[1000010000100001][1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010]\begin{align*} M^{Vulkan}_{per,vfov,lh \rightarrow rh} &= \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} M^{C,Vulkan}_{per,vfov} \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per,vfov} \left( \Omega_{lh \rightarrow lh} Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per,vfov} \left( I Q^{Vulkan}_{lh} \right) \\ &= \left( \Omega_{lh \rightarrow rh} \left(Q^{Vulkan}_{lh}\right)^{-1} \right) M^{C,Vulkan}_{per,vfov} Q^{Vulkan}_{lh} \\ &= \left( \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \right) M^{C,Vulkan}_{per,vfov} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} M^{C,Vulkan}_{per,vfov} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & \frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & -\frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \\ &= \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix} \end{align*}

therefore

Mper,vfov,lhrhVulkan=[1aspecttan(θvfov2)00001tan(θvfov2)0000ffnfnfn0010].M^{Vulkan}_{per,vfov,lh \rightarrow rh} = \begin{bmatrix} \frac{1}{\text{aspect} \cdot \tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan\left( \frac{\theta_{vfov}}{2} \right)} & 0 & 0 \\ 0 & 0 & -\frac{f}{f - n} & -\frac{ f n }{f - n} \\ 0 & 0 & -1 & 0 \\ \end{bmatrix}.

This completes the derivation of the matrices for the left-handed Vulkan view coordinates.

Comparing Coordinate System Orientations

Let us illustrate why the coordinate systems in this section have a left-handed orientation or right-handed orientation. By convention, the standard basis on R3\mathbb{R}^{3} has a right-handed orientation. Recall that the standard basis on R3\mathbb{R}^{3} is the tuple of vectors (x^,y^,z^)(\mathbf{\hat{x}}, \mathbf{\hat{y}}, \mathbf{\hat{z}}) where x^=[1,0,0]T\mathbf{\hat{x}} = [1, 0, 0]^{T}, y^=[0,1,0]T\mathbf{\hat{y}} = [0, 1, 0]^{T}, and z^=[0,0,1]T\mathbf{\hat{z}} = [0, 0, 1]^{T} are the standard basis vectors. In this basis, Vulkans’s left-handed view coordinate system has the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & -\mathbf{\hat{y}} & \mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} = 1 \cdot -1 \cdot 1 = -1

and Vulkan’s right-handed view coordinates and clip coordinates have the determinant

det[x^y^z^]=det[100010001]=111=1\det \begin{bmatrix} \mathbf{\hat{x}} & -\mathbf{\hat{y}} & -\mathbf{\hat{z}} \end{bmatrix} = \det \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & -1 \\ \end{bmatrix} = 1 \cdot -1 \cdot -1 = 1

so the right-handed Vulkan view coordinate system and clip coordinate system indeed have a right-handed orientation, and the left-handed view coordinate system has a left-handed orientation.

Summary

We develop the manifold structure of real projective space RP3\mathbb{RP}^{3} from scratch, then use that information to show how we can represent linear, affine, and projective transformations as matrices. We demonstrate why real projective space RP3\mathbb{RP}^{3} is a convenient manifold for solving problems in computer graphics, geometric modeling, robotics, computer vision, and other spatial computing domains formulated in the setting E3\mathbb{E}^{3}. We use this knowledge to construct homogeneous projection matrices.

We construct a set of projection matrices using a canonically chosen set of coordinates which makes it easy to derive any other projection matrix using coordinate transformations in conjunction with the relevant coordinate transformations to create the final result. We chose a view coordinate system where the horizontal axis points to the right, the vertical axis points up, and the depth axis points into the view volume. This has the benefit of keeping all of the computations in the same orthonormal frame, which makes the behavior of the projection more obvious. Operating in real projective space allows us to express our rendering problems in a coordinate system and scale independent way, such that the choice of coordinate system is a degree of freedom for the problem at hand. Moreover, the coordinate system independent formulation is a low-key form of separation of concerns in software engineering for spatial computing domains.

We show how to construct perspective and orthographic projection transformations in RP3\mathbb{RP}^{3} from any view space orthonormal frame to any clip coordinate frame by first defining the matrix in a specially chosen coordinate chart, and then show that one can construct any other one by using the appropriate orthogonal transformations and changes of orientation to map from the desired view coordinate system to the canonical one on one side, and mapping from the canonical clip coordinate system to the desired clip coordinate system using the same process. This result shows that perspective and orthographic projections are indeed coordinate independent transformations.

References

References
  1. Lee, J. M. (2011). Introduction to Topological Manifolds. In Graduate Texts in Mathematics. Springer New York. 10.1007/978-1-4419-7940-7
  2. Marschner, S., Shirley, P., Ashikhmin, M., Gleicher, M., Hoffman, N., Johnson, G., Munzner, T., Reinhard, E., Thompson, W. B., Willemsen, P., & Wyvill, B. (2021). Fundamentals of Computer Graphics. A K Peters/CRC Press. 10.1201/9781003050339