TinyRenderer Note 2: Perspective Projection

Original link: https://www.kirito.info/tinyrenderer-note-2/

5e4a3c3ac6c7c5342d9a6ff360895297.png?siz

When rendering the model earlier, the z coordinate of each point was not considered. This method is called Orthographic projection . The model looks fat, because the objects we usually see in the 3D world are near large and far small. Perspective projection Perspective projection is to project in the way of near big and far small.

Comparison of two projections:

Orthogonal perspective

2D geometry

Linear transformationsLinear transformations

Linear transformation has three main points from geometric intuition:

  • It is a straight line before the transformation, and it is still a straight line after the transformation
  • Straight line ratio remains the same
  • It is the origin before the transformation, and it is still the origin after the transformation

To put it bluntly, it is scaling, cropping and rotation, excluding translation: you can see this article

All linear transformations on the plane can be computed using a two-dimensional matrix:

$$
\begin{bmatrix}
a & b \\
c & d
\end{bmatrix}
\begin{bmatrix}
x \\ y
\end{bmatrix}
=
\begin{bmatrix}
ax + by \\
cx + dy
\end{bmatrix}
$$

Affine transformation affine transformations

To put it simply, it is linear transformation plus translation, calculated by matrix:

$$
\begin{bmatrix}
a & b \\
c & d
\end{bmatrix}
\begin{bmatrix}
x \\ y
\end{bmatrix}
+
\begin{bmatrix}
e \\ f
\end{bmatrix}
=
\begin{bmatrix}
ax + by + e\\
cx + dy + f
\end{bmatrix}
$$

Homogeneous coordinates

Add one row and one column to the 2×2 transformation matrix to become 3×3, and add a coordinate that is always 1 to the vector waiting to be transformed:

$$
\begin{bmatrix}
a & b & e \\
c & d & f \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
x\\y\\1
\end{bmatrix}
=
\begin{bmatrix}
ax + by + e\\
cx + dy + f \\
1
\end{bmatrix}
$$

This achieves the same effect as the affine transformation! The idea is very simple. Translation is not linear in 2D space. So we embed 2D into 3D space (by simply adding 1 to the third component). This means that 2D space is the plane of z=1 in 3D space. We then perform a 3D linear transformation and project the result onto our 2D physical plane.

Projecting 3d to 2d is just a matter of dividing by the 3d component:

$$
\begin{bmatrix}
x\\
y\\
z
\end{bmatrix}
\rightarrow
\begin{bmatrix}
x/z \\
y/z
\end{bmatrix}
$$

If z is infinitely close to 0, it means that the projected point is at infinity:

  • Projected point -> 2d coordinates projected onto the plane z=?
  • (x,y,1) -> (x,y)
  • (x,y,1/2) -> (2x,2y)
  • (x,y,1/4) -> (4x,4y)

It can be seen that as the plane descends, the projected point becomes farther and farther away, so when z=0, it represents a vector instead of a point in 3d space.

3d affine transformation

The affine transformation of 2d can be converted into a linear transformation in 3d by embedding 2d into 3d, and then projected back to 2d. The same reason: the affine transformation of 3d can be converted into a linear transformation in 4d by embedding 3d into 4d, and then projected back to 3d!

Using homogeneous coordinates: point (x,y,z) -> (x,y,z,1), try to transform it in 4d space with the following matrix:

$$
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & r & 1
\end{bmatrix}
\begin{bmatrix}
x\\y\\z\\1
\end{bmatrix}
=
\begin{bmatrix}
x \\ y \\ z \\ rz+1
\end{bmatrix}
$$

Then project back to 3d:

$$
\begin{bmatrix}
x \\ y \\ z \\ rz+1
\end{bmatrix}
\rightarrow
\begin{bmatrix}
\frac{x}{rz+1} \\ \frac{y}{rz+1} \\ \frac{z}{rz+1}
\end{bmatrix}
$$

Put this result aside. Let’s look at an example of projecting a point in 3D onto a plane by the human eye in simulated reality:

There is a point P=(x,y,z), we want to project it onto the plane of z=0, the position of the camera (that is, the human eye) on the z-axis (0,0,c)

According to the knowledge of junior high school or high school, the triangles ABC and ODC are similar triangles, so $\frac{AB}{AC}=\frac{OD}{OC}$, and then $\frac{x}{cz}=\ frac{x^{‘}}{c}$

so:

$$
x^{‘}= \frac{x}{1-z/c}
$$

In the same way:

$$
y^{‘}= \frac{y}{1-z/c}
$$

Back to the matrix, let r=-1/c:

$$
\begin{bmatrix}
x \\ y \\ z \\ rz+1
\end{bmatrix}
\rightarrow
\begin{bmatrix}
\frac{x}{rz+1} \\ \frac{y}{rz+1} \\ \frac{z}{rz+1}
\end{bmatrix}
\rightarrow
\begin{bmatrix}
\frac{x}{1-z/c} \\ \frac{y}{1-z/c} \\ \frac{z}{1-z/c}
\end{bmatrix}
$$

Summarize

If we want to calculate a central projection with a camera located at a distance c from the origin on the z-axis, there are three steps:

  1. Embed 3d into 4d
  2. do linear transformation in 4d
  3. Project back to 3d
$$
\begin{aligned}
\begin{bmatrix}
x\\y\\z
\end{bmatrix}
\rightarrow
\begin{bmatrix}
x\\y\\z\\1
\end{bmatrix}
&\qquad(1)\\
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0 \\
0 & 0 & -1/c & 1
\end{bmatrix}
\begin{bmatrix}
x\\y\\z\\1
\end{bmatrix}
=
\begin{bmatrix}
x \\ y \\ z \\ 1-z/c
\end{bmatrix}
&\qquad(2)\\
\begin{bmatrix}
x \\ y \\ z \\ 1-z/c
\end{bmatrix}
\rightarrow
\begin{bmatrix}
\frac{x}{1-z/c} \\ \frac{y}{1-z/c} \\ \frac{z}{1-z/c}
\end{bmatrix}
&\qquad(3)
\end{aligned}
$$

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 // 4d投影到3d fn v4p2v3 ( v : glm :: Vec4 ) -> glm :: Vec3 {   
    glm :: vec3 ( v . x / v . w , v . y / v . w , v . z / v . w )   
}   
   
// ... let camera : glm :: Vec3 = glm :: vec3 ( 0. , 0. , 3. );   
// 投影变换矩阵,注意gml初始化一行是矩阵中的一列let projection = glm :: mat4 (   
        1. , 0. , 0. , 0. ,    
        0. , 1. , 0. , 0. ,    
        0. , 0. , 1. , - 1. / camera . z ,    
        0. , 0. , 0. , 1. );   
   
// ... // 透视投影let a = v4p2v3 ( projection * a . extend ( 1. ));   
let b = v4p2v3 ( projection * b . extend ( 1. ));   
let c = v4p2v3 ( projection * c . extend ( 1. ));   

See here for detailed code 076b31fc4ea69f00e2cee530e5e3e25445189b67

This article is transferred from: https://www.kirito.info/tinyrenderer-note-2/
This site is only for collection, and the copyright belongs to the original author.