<p>There are <em>several</em> things going on here.</p>
<blockquote>
<p>I want to know if there is a transformation <span class="math-container">$T$</span> that will result in <span class="math-container">$TA=B$</span> and <span class="math-container">$TB=A$</span>.</p>
</blockquote>
<p>There is not, because what you would need to do is <em>transpose</em> the matrix, which cannot be expressed by multiplying by another matrix. Something to keep in mind is that it is common to store matrices in <a href="https://en.wikipedia.org/wiki/Row-_and_column-major_order" rel="nofollow noreferrer">column-major order</a>, and when that is done, if the elements are written out in an array literal or function arguments, they will appear transposed. So, you have <em>probably</em> encountered merely an accident of notation, and your <span class="math-container">$B$</span> should be written transposed:</p>
<p><span class="math-container">$$
B=\begin{bmatrix}
k&amp;0&amp;0&amp;0\\
0&amp;ka&amp;0&amp;0\\
0&amp;0&amp;\frac{f}{f-n}&amp;\frac{fn}{f-n}\\
0&amp;0&amp;-1&amp;0
\end{bmatrix}.
$$</span></p>
<p>Now the only differences are signs; let's discuss that next. Actually, you have <em>fewer</em> differences than a typical OpenGL perspective matrix would have — I'd usually expect to see</p>
<p><span class="math-container">$$
B=\begin{bmatrix}
k&amp;0&amp;0&amp;0\\
0&amp;ka&amp;0&amp;0\\
0&amp;0&amp;\frac{f + n}{n-f}&amp;\frac{2fn}{n-f}\\
0&amp;0&amp;-1&amp;0
\end{bmatrix}.
$$</span></p>
<p>Notice that the subtraction in the denominators is reversed, so the signs of the results are opposite. I'm going to assume that the “typical OpenGL graphics lesson” contains this and not what you wrote.</p>
<blockquote>
<p>I believe it has something to do with coordinate system handedness.</p>
</blockquote>
<p>Correct in part. Remember that if you negate any one axis, the handedness is changed. In an OpenGL conventional coordinate system, in eye space (the 3D coordinates that are being transformed for display by the projection matrix), the Z axis points <em>towards the viewer</em>, but in the conventional use of the clip and NDC spaces (after being transformed by the projection matrix), the Z axis points <em>away from the viewer</em>. So, there must be a negation of Z coordinates in the projection matrix; the value in the 3rd row and 3rd column is negative, and the off-diagonal elements which define the relationship between Z and W are also negative.</p>
<blockquote>
<p>(I assume OpenGL uses right-handed coordinates when applying the projective matrix).</p>
</blockquote>
<p>OpenGL does not actually care which handedness you use — it's all a matter of convention, because the projection matrix can do whatever it wants.</p>
<p>The remaining difference, the source of the <span class="math-container">$2$</span> in the matrix, is that OpenGL's NDC space differs from what most other graphics APIs use. NDC (normalized device coordinates) is the coordinate system where all “pixels that are actually drawn” live; the portions of the scene that are clipped are exactly those which live outside of the bounds in NDC space.</p>
<p>In OpenGL, the NDC space is a cube — the coordinate ranges are from -1 to 1 in all <em>three</em> axes. In most other systems, the X and Y ranges are -1 to 1, but the Z range is 0 to 1. That accounts for the final differences in the matrix — it's producing a different range of Z. In typical use of OpenGL, the perspective matrix maps points on the near plane to a NDC Z value of -1.0; elsewhere, the near plane would have a NDC Z value of 0.0.</p>
<p>This is often considered a design mistake on OpenGL's part; there are no technical advantages to the -1 to 1 system, and there are some for the 0 to 1 system (to do with the depth buffer precision available at various depths).</p>

CC BY-SA 4.0
2024-06-01T16:19:47.207Z
A delightfully well-explained and helpful answer. Thank you very much!
Scene
CC BY-SA 4.0
2024-06-01T14:41:38.067Z
2024-06-01T16:42:27.903Z
2024-06-01T16:42:27.903Z
Kevin Reid
<p>I have two 3D perspective projection matrices <span class="math-container">$A,B$</span> with standard projection parameters <span class="math-container">$k=\cot(\theta/2)$</span>, where <span class="math-container">$\theta$</span> is the field of view, <span class="math-container">$n$</span> is the <span class="math-container">$z$</span>-near value, <span class="math-container">$f$</span> is the <span class="math-container">$z$</span>-far value, and <span class="math-container">$a$</span> is the width-to-height aspect ratio:
<span class="math-container">$$
A=\begin{bmatrix}
k&amp;0&amp;0&amp;0\\
0&amp;ka&amp;0&amp;0\\
0&amp;0&amp;\frac{f}{f-n}&amp;-\frac{fn}{f-n}\\
0&amp;0&amp;1&amp;0
\end{bmatrix}
$$</span>
and
<span class="math-container">$$
B=\begin{bmatrix}
k&amp;0&amp;0&amp;0\\
0&amp;ka&amp;0&amp;0\\
0&amp;0&amp;\frac{f}{f-n}&amp;-1\\
0&amp;0&amp;\frac{fn}{f-n}&amp;0
\end{bmatrix}.
$$</span></p>
<p>I want to know if there is a transformation <span class="math-container">$T$</span> that will result in <span class="math-container">$TA=B$</span> and <span class="math-container">$TB=A$</span>. I also would like to know what <span class="math-container">$T$</span> represents geometrically. I believe it has something to do with coordinate system handedness. However, after putting pen to paper, I can't come to a conclusion.</p>
<p>For more context, <span class="math-container">$A$</span> is the perspective projection provided in <a href="https://www.pbr-book.org/4ed/Cameras_and_Film/Projective_Camera_Models#:%7E:text=All%20of%20this%20computation%20can%20be%20encoded%20in%20a%20%20matrix%20that%20can%20then%20be%20applied%20to%20homogeneous%20coordinates%3A" rel="nofollow noreferrer">Matt Phar's PBRT</a> (they use a left-handed coordinate system) and <span class="math-container">$B$</span> is the perspective projection provided in your typical OpenGL graphics lesson (I assume OpenGL uses right-handed coordinates when applying the projective matrix).</p>

<opengl><projections><perspective><pbrt><coordinates>
How are these two projection matrices related?
Scene
# How are these two projection matrices related?

(Asked by: username_0 on 2024-06-01)

I have two 3D perspective projection matrices $A,B$ with standard projection parameters $k=\cot(\theta/2)$, where $\theta$ is the field of view, $n$ is the $z$-near value, $f$ is the $z$-far value, and $a$ is the width-to-height aspect ratio:
$$
A=\begin{bmatrix}
k&0&0&0\\
0&ka&0&0\\
0&0&\frac{f}{f-n}&-\frac{fn}{f-n}\\
0&0&1&0
\end{bmatrix}
$$
and
$$
B=\begin{bmatrix}
k&0&0&0\\
0&ka&0&0\\
0&0&\frac{f}{f-n}&-1\\
0&0&\frac{fn}{f-n}&0
\end{bmatrix}.
$$

I want to know if there is a transformation $T$ that will result in $TA=B$ and $TB=A$. I also would like to know what $T$ represents geometrically. I believe it has something to do with coordinate system handedness. However, after putting pen to paper, I can't come to a conclusion.

For more context, $A$ is the perspective projection provided in [Matt Phar's PBRT](https://www.pbr-book.org/4ed/Cameras_and_Film/Projective_Camera_Models#:%7E:text=All%20of%20this%20computation%20can%20be%20encoded%20in%20a%20%20matrix%20that%20can%20then%20be%20applied%20to%20homogeneous%20coordinates%3A) (they use a left-handed coordinate system) and $B$ is the perspective projection provided in your typical OpenGL graphics lesson (I assume OpenGL uses right-handed coordinates when applying the projective matrix).

**Tags:** opengl, projections, perspective, pbrt, coordinates


---

## 1 answers

### Answer by username_1 on 2024-06-01. Score: 2 | Accepted answer

There are *several* things going on here.

> I want to know if there is a transformation $T$ that will result in $TA=B$ and $TB=A$.

There is not, because what you would need to do is *transpose* the matrix, which cannot be expressed by multiplying by another matrix. Something to keep in mind is that it is common to store matrices in [column-major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order), and when that is done, if the elements are written out in an array literal or function arguments, they will appear transposed. So, you have *probably* encountered merely an accident of notation, and your $B$ should be written transposed:

$$
B=\begin{bmatrix}
k&0&0&0\\
0&ka&0&0\\
0&0&\frac{f}{f-n}&\frac{fn}{f-n}\\
0&0&-1&0
\end{bmatrix}.
$$

Now the only differences are signs; let's discuss that next. Actually, you have *fewer* differences than a typical OpenGL perspective matrix would have — I'd usually expect to see

$$
B=\begin{bmatrix}
k&0&0&0\\
0&ka&0&0\\
0&0&\frac{f + n}{n-f}&\frac{2fn}{n-f}\\
0&0&-1&0
\end{bmatrix}.
$$

Notice that the subtraction in the denominators is reversed, so the signs of the results are opposite. I'm going to assume that the “typical OpenGL graphics lesson” contains this and not what you wrote.

> I believe it has something to do with coordinate system handedness.

Correct in part. Remember that if you negate any one axis, the handedness is changed. In an OpenGL conventional coordinate system, in eye space (the 3D coordinates that are being transformed for display by the projection matrix), the Z axis points *towards the viewer*, but in the conventional use of the clip and NDC spaces (after being transformed by the projection matrix), the Z axis points *away from the viewer*. So, there must be a negation of Z coordinates in the projection matrix; the value in the 3rd row and 3rd column is negative, and the off-diagonal elements which define the relationship between Z and W are also negative.

> (I assume OpenGL uses right-handed coordinates when applying the projective matrix).

OpenGL does not actually care which handedness you use — it's all a matter of convention, because the projection matrix can do whatever it wants.

The remaining difference, the source of the $2$ in the matrix, is that OpenGL's NDC space differs from what most other graphics APIs use. NDC (normalized device coordinates) is the coordinate system where all “pixels that are actually drawn” live; the portions of the username_0 that are clipped are exactly those which live outside of the bounds in NDC space.

In OpenGL, the NDC space is a cube — the coordinate ranges are from -1 to 1 in all *three* axes. In most other systems, the X and Y ranges are -1 to 1, but the Z range is 0 to 1. That accounts for the final differences in the matrix — it's producing a different range of Z. In typical use of OpenGL, the perspective matrix maps points on the near plane to a NDC Z value of -1.0; elsewhere, the near plane would have a NDC Z value of 0.0.

This is often considered a design mistake on OpenGL's part; there are no technical advantages to the -1 to 1 system, and there are some for the 0 to 1 system (to do with the depth buffer precision available at various depths).

> **Comments:**
> **username_0**: A delightfully well-explained and helpful answer. Thank you very much!  

---

