Computer graphics in Game development
Ivan Belyavtsev
23.10.2020
It’s possible to construct any image using the next operation:
Homogeneous coordinates - cartesian coordinates + 1 dimension
\[ (X, Y, Z) => (x, y, z, w) \]
\[ X = x/w, Y = y/w, Z = z/w \] [3]
\[T(\overrightarrow{x}) = A\overrightarrow{x}\]
where \[A = \left[\begin{array}{cccc} x1 & x2 & x3 & x4 \\ y1 & y2 & y3 & y4 \\ z1 & z2 & z3 & z4 \\ w1 & w2 & w3 & w4 \end{array}\right]\] [4]
\(\overrightarrow{tr}\) - vector of translation
\[T = \left[\begin{array}{cccc} 1 & 0 & 0 & tr.x \\ 0 & 1 & 0 & tr.y \\ 0 & 0 & 1 & tr.z \\ 0 & 0 & 0 & 1 \end{array}\right]\] [4]
\(\overrightarrow{scale}\) - vector of scaling
\[S = \left[\begin{array}{cccc} scale.x & 0 & 0 & 0 \\ 0 & scale.y & 0 & 0 \\ 0 & 0 & scale.z & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\] [4]
\(\alpha\) - angle of rotation around axis X
\[R_x = \left[\begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & cos(\alpha) & -sin(\alpha) & 0 \\ 0 & sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\] [4]
\(\beta\) - angle of rotation around axis Y
\[R_y = \left[\begin{array}{cccc} cos(\beta) & 0 & sin(\beta) & 0 \\ 0 & 1 & 0 & 0 \\ -sin(\beta) & 0 & cos(\beta) & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\] [4]
\(\gamma\) - angle of rotation around axis Z
\[R_z = \left[\begin{array}{cccc} cos(\gamma) & -sin(\gamma) & 0 & 0 \\ sin(\gamma) & cos(\gamma) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\] [4]
\[World=TRS\]
First scale, then rotate, then translate
\[ \overrightarrow{zaxis} = \frac{\overrightarrow{Eye} - \overrightarrow{At}}{||\overrightarrow{Eye} - \overrightarrow{At}||} \] \[ \overrightarrow{xaxis} = \frac{\overrightarrow{Up} \times \overrightarrow{zaxis}}{||\overrightarrow{Up} \times \overrightarrow{zaxis}||}\] \[ \overrightarrow{yaxis} = \overrightarrow{zaxis} \times \overrightarrow{xaxis} \]
\[View = \left[\begin{array}{cccc} xaxis.x & yaxis.x & zaxis.x & 0 \\ xaxis.y & yaxis.y & zaxis.y & 0 \\ xaxis.z & yaxis.z & zaxis.z & 0 \\ \overrightarrow{xaxis} \cdot \overrightarrow{eye} & \overrightarrow{yaxis} \cdot \overrightarrow{eye} & \overrightarrow{zaxis} \cdot \overrightarrow{eye} & 1 \end{array}\right]\]
\[Projortho = \left[\begin{array}{cccc} \frac{2}{S_w} & 0 & 0 & 0 \\ 0 & \frac{2}{S_h} & 0 & 0 \\ 0 & 0 & \frac{1}{Z_f-Z_n} & 0 \\ 0 & 0 & \frac{-Z_n}{Z_f-Z_n} & 1 \end{array}\right]\]
\[Proj = \left[\begin{array}{cccc} \frac{2Z_n}{S_w} & 0 & 0 & 0 \\ 0 & \frac{2Z_n}{S_h} & 0 & 0 \\ 0 & 0 & \frac{Z_f}{Z_f-Z_n} & 1 \\ 0 & 0 & \frac{-Z_n\cdot Z_f}{Z_f-Z_n} & 0 \end{array}\right]\]
\[Viewport = \left[\begin{array}{cccc} width & 0 & 0 & 0 \\ 0 & -height & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\]
\[\vec{X} = Viewport \cdot Proj \cdot View \cdot World \cdot \vec{x}\]
Remember about left-handed and right-handed operations!
Check correctness of each matrix, e.x. in DirecX documentation [1]
Let’s implement it together