2.1 Orthogonal Cameras
In this section, we'll discuss orthogonal cameras. Previously, we explored perspective cameras, which mimic real-life pinhole cameras where objects farther away appear smaller on the screen. This perspective effect mimics our natural visual experience. In contrast, orthogonal cameras don't introduce any perspective. They project objects onto the screen in their original size, regardless of their distance from the camera.
So, why are orthogonal cameras useful? Well, consider scenarios where we want to create 2D applications using a 3D API, such as image processing applications. In these cases, we don't want images to appear distorted due to perspective. Orthogonal projection is ideal in such situations. It's also commonly employed in 45-degree top-view video games.
let's try to derive the orthogonal projection matrix. remember before projection, we have converted the coordinate system to the view coordinates. in this coordinates, we should have the xy plane parallel to the screen plane and the z-axis pointing towards us.
Imagine if we have a screen aligned bounding box enclosing the 3d scene, our goal of projection is to project the bounding box to the ndc coordinates in the range of [-1,-1,-1] to [1,1,1] for both x, y and z.
this is actually a simpler calculation than the perspective projection.
let the right of the screen coordinates is r
and the left is l
. given a point p
at (x,y)
in the view coordinates, we have
\begin{multline}
-l \leq x \leq r \\
-0 \leq x \leq r-l \\
-0 \leq \frac{x-l}{r-l} \leq 1
-\end{multline}
...
-let orthProjMatrix = glMatrix.mat4.ortho(glMatrix.mat4.create(), -320.0, 320.0, 240.0, -240.0, -1000.0, 1000.0);
-...
Using an orthogonal camera is straightforward. There are no changes to the shader code or most of the JavaScript logic, so I'll focus on the key elements. The orthogonal projection matrix closely resembles the perspective projection matrix. We can easily generate this projection matrix using the glMatrix library. By specifying the width and height of the viewport, as well as the near and far planes of the view frustum, we obtain the orthogonal projection matrix.
Unlike the perspective projection, the view frustum for orthogonal projection is not a cone; it's a simple 3D rectangle. The image below illustrates the difference between these two projections.
+2.1 Orthogonal Cameras
In this section, we'll explore orthogonal cameras. Previously, we examined perspective cameras, which emulate real-life pinhole cameras where distant objects appear smaller on screen. This perspective effect mirrors our natural visual experience. In contrast, orthogonal cameras maintain objects' original sizes on screen, regardless of their distance from the camera, eliminating perspective distortion.
Launch Playground - 2_01_orthogonal_camerasOrthogonal cameras prove useful in various scenarios, particularly when creating 2D applications using a 3D API, such as image processing tools. In these cases, we want to avoid image distortion due to perspective effects. Orthogonal projection excels in such situations and is also frequently employed in 45-degree top-view video games.
Let's derive the orthogonal projection matrix. Recall that before projection, we convert the coordinate system to view coordinates. In this system, the xy plane is parallel to the screen plane, with the z-axis pointing towards us.
Imagine a screen-aligned bounding box enclosing the 3D scene. Our projection goal is to map this bounding box to NDC (Normalized Device Coordinates) in the range [-1,-1,-1]
to [1,1,1]
for x, y, and z.
This calculation is simpler than perspective projection. Let the right edge of the screen coordinates be r
and the left edge be l
. Given a point p
at (x,y)
in view coordinates, we have:
\begin{aligned}
+& l \leq x \leq r \\
+& 0 \leq x \leq r-l \\
+& 0 \leq \frac{x-l}{r-l} \leq 1 \\
+& 0 \leq 2 \times \frac{x-l}{r-l} \leq 2 \\
+& -1 \leq 2 \times \frac{x-l}{r-l} -1 \leq 1
+\end{aligned}
We've successfully converted the x-coordinate to the range [-1,1]
. Now, we'll refine the calculation to the form Ax + B
, allowing us to express it as matrix multiplication:
\begin{aligned}
+& -1 \leq \frac{2x-2l-r+l}{r-l} \leq 1 \\
+& -1 \leq \frac{2x}{r-l} - \frac{r+l}{r-l} \leq 1
+\end{aligned}
We can derive similar equations for y
and z
. Note that NDC uses a left-handed coordinate system, so we need to flip the z
axis:
\begin{aligned}
+x^\prime &= \frac{2x}{r-l} - \frac{r+l}{r-l} \\
+y^\prime &= \frac{2y}{t-b} - \frac{t+b}{t-b} \\
+z^\prime &= \frac{-2z}{f-n}-\frac{f+n}{f-n}
+\end{aligned}
Where t
and b
are the top and bottom of the screen coordinates, and n
and f
are the near and far plane. Now, we can express these calculations as a matrix multiplication:
\begin{pmatrix}
+\frac{2}{r-l} & 0 & 0 & 0 \\
+0 & \frac{2}{t-b} & 0 & 0 \\
+0 & 0 & \frac{-2}{f-n} & 0 \\
+-\frac{r+l}{r-l} & - \frac{t+b}{t-b} & -\frac{f+n}{f-n} & 0
+\end{pmatrix}
Implementing an orthogonal camera is straightforward. The shader code and most JavaScript logic remain unchanged, so we'll focus on the key elements:
let orthProjMatrix = glMatrix.mat4.ortho(glMatrix.mat4.create(), -320.0, 320.0, 240.0, -240.0, -1000.0, 1000.0);
+
The orthogonal projection matrix closely resembles the perspective projection matrix. We can easily generate this projection matrix using the glMatrix library. By specifying the viewport's width and height, along with the near and far planes of the view frustum, we obtain the orthogonal projection matrix.
Unlike perspective projection, the view frustum for orthogonal projection is a simple 3D rectangle rather than a cone. The rest of the code remains identical to the perspective projection program.