【GAMES101】透视投影

原文链接:【GAMES101】透视投影

GAMES101作业1中编程实现一个三角形旋转投影的任务,期间配置环境、找Bug费了好几天的功夫。本期,推送一些注意的地方。

1 3D Perspective Projection

How to do perspective projection

  • First “squish” the frustum into a cuboid n → n , f → f n \rightarrow n, f \rightarrow f nn,ff ( M p e r s p → o r t h o M_{persp\rightarrow ortho} Mpersportho)

  • Do orthographic projection ( M o r t h o M_{ortho} Mortho, already known!)

【GAMES101】透视投影_第1张图片

就是将Frustum拉成一个长方体,然后再利用正交投影进行变换。

注意:在右手系中,相机正对 − z -z z方向。这是一个坑,在编程时,应该 n = − z N e a r n = -zNear n=zNear

△ O A C ∼ △ O B D \triangle OAC \sim \triangle OBD OACOBD,有
{ y ′ = n z y x ′ = n z x 。 \left\{ \begin{aligned} y' = \frac{n}{z}y\\ x' = \frac{n}{z}x \end{aligned}\right.。 y=znyx=znx
在齐次坐标系中,,有
( x y z 1 ) ⟹ ( n z x n z y unknown 1 ) ⟹ × z ( n x n y still unknown z ) \left ( \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right ) \Longrightarrow \left ( \begin{matrix} \frac{n}{z}x \\ \frac{n}{z}y \\ \text{unknown} \\ 1 \end{matrix} \right ) \Longrightarrow^{\times z} \left ( \begin{matrix} nx \\ ny \\ \text{still unknown} \\ z \end{matrix} \right ) xyz1znxznyunknown1×znxnystill unknownz
因此
KaTeX parse error: No such environment: equation* at position 8: \begin{̲e̲q̲u̲a̲t̲i̲o̲n̲*̲}̲M_{persp\righta…
M p e r s p → o r t h o M_{persp\rightarrow ortho} Mpersportho如下
M p e r s p → o r t h o = ( n 0 0 0 0 n 0 0 ? ? ? ? 0 0 1 0 ) M_{persp\rightarrow ortho} = \left ( \begin{matrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ ? & ? & ? & ? \\ 0 & 0 & 1 & 0 \end{matrix}\right ) Mpersportho=n000n0001000

Observation: the third row is responsible for z ’ z’ z

  • Any point on the near plane will not change
  • Any point’s z z z on the far plane will not change
  • Near plane

M p e r s p → o r t h o ( x y n 1 ) = ( x y n 1 ) M_{persp\rightarrow ortho} \left ( \begin{matrix}x \\ y \\ n \\ 1\end{matrix}\right ) = \left ( \begin{matrix}x \\ y \\ n \\ 1\end{matrix}\right ) Mpersporthoxyn1=xyn1

所以 M p e r s p → o r t h o M_{persp\rightarrow ortho} Mpersportho第三行为 ( 0 , 0 , A , B ) (0, 0, A, B) (0,0,A,B)

  • Far plane

M p e r s p → o r t h o ( 0 0 f 1 ) = ( 0 0 f 1 ) M_{persp\rightarrow ortho}\left ( \begin{matrix}0 \\ 0 \\ f \\ 1\end{matrix}\right ) = \left ( \begin{matrix}0 \\ 0 \\ f \\ 1\end{matrix}\right ) Mpersportho00f1=00f1

综上
{ A n 2 + B = n A f 2 + B = f 。 \left\{ \begin{aligned}A n^2 + B = n\\A f^2 + B = f\end{aligned}\right.。 {An2+B=nAf2+B=f
解得
{ A = n + f B = − n × f 。 \left\{ \begin{aligned}A &= n + f\\ B &= - n \times f\end{aligned}\right.。 {AB=n+f=n×f

2 Orthographic Projection

In general

  • We want to map a cuboid [ l , r ] × [ b , t ] × [ f , n ] [l, r] \times [b, t] \times [f, n] [l,r]×[b,t]×[f,n] to the canonical cube [ − 1 , 1 ] 3 [-1,1]^3 [1,1]3.

【GAMES101】透视投影_第2张图片

需要两部操作:

  • Center cuboid by translating
  • Scale into “canonical” cube

因此
M o r t h o = ( 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f ) 0 0 0 0 1 ) ( 0 0 0 − r + l 2 0 0 0 − t + b 2 0 0 0 − n + f 2 0 0 0 1 ) M_{ortho} = \left ( \begin{matrix} \frac{2}{r - l} & 0 & 0 & 0 \\ 0 & \frac{2}{t - b} & 0 & 0 \\ 0 & 0 & \frac{2}{n - f}) & 0\\ 0 & 0 & 0 & 1\end{matrix}\right ) \left ( \begin{matrix} 0 & 0 & 0 & -\frac{r + l}{2} \\ 0 & 0 & 0 & -\frac{t + b}{2} \\ 0 & 0 & 0 & -\frac{n + f}{2} \\ 0 & 0 & 0 & 1\end{matrix}\right ) Mortho=rl20000tb20000nf2)000010000000000002r+l2t+b2n+f1

3. Filed of View

Filed of View如下

【GAMES101】透视投影_第3张图片

How to convert from f o v Y fovY fovY and aspect to l , r , b , t l, r, b, t l,r,b,t?

【GAMES101】透视投影_第4张图片

易得
{ t = tan ⁡ ( f o v Y 2 ) ∣ n ∣ ,   b = − t r = a s p e c t × t ,   l = − r 。 \left\{ \begin{aligned}t &= \tan(\frac{fovY}{2}) | n |, &~b = -t\\ r &= aspect \times t, ~ &l = -r\end{aligned}\right.。 tr=tan(2fovY)n,=aspect×t,  b=tl=r
综上所述,透视投影矩阵
M p e r s p = M o r t h o × M p e r s p → o r t h o = ( 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f ) 0 0 0 0 1 ) ( 0 0 0 − r + l 2 0 0 0 − t + b 2 0 0 0 − n + f 2 0 0 0 1 ) ( n 0 0 0 0 n 0 0 0 0 n + f − n × f 0 0 1 0 ) \begin{aligned}M_{persp}=&M_{ortho} \times M_{persp\rightarrow ortho} \\=&\left ( \begin{matrix} \frac{2}{r - l} & 0 & 0 & 0 \\ 0 & \frac{2}{t - b} & 0 & 0 \\ 0 & 0 & \frac{2}{n - f}) & 0\\ 0 & 0 & 0 & 1\end{matrix}\right ) \\&\left ( \begin{matrix} 0 & 0 & 0 & -\frac{r + l}{2} \\ 0 & 0 & 0 & -\frac{t + b}{2} \\ 0 & 0 & 0 & -\frac{n + f}{2} \\ 0 & 0 & 0 & 1\end{matrix}\right ) \\&\left ( \begin{matrix}n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & - n \times f \\ 0 & 0 & 1 & 0\end{matrix}\right )\end{aligned} Mpersp==Mortho×Mpersporthorl20000tb20000nf2)000010000000000002r+l2t+b2n+f1n0000n0000n+f100n×f0

Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();

    // TODO: Implement this function
    // Create the model matrix for rotating the triangle around the Z axis.
    // Then return it.

	double rotation_radian = rotation_angle * MY_PI / 180;

    model << std::cos(rotation_radian), -std::sin(rotation_radian), 0, 0,
             std::sin(rotation_radian), std::cos(rotation_radian), 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1;   
    return model;
}

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
                                      float zNear, float zFar)
{
    // Students will implement this function

    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    // TODO: Implement this function
    // Create the projection matrix for the given parameters.
    // Then return it.

    float n = -zNear;
    float f = -zFar;
    float t = std::abs(n) * std::tan(.5f * eye_fov * MY_PI / 180);
    float b = -t;
    float r = aspect_ratio * t;
    float l = -r;
    

    Eigen::Matrix4f perspective_to_orthogonal = Eigen::Matrix4f::Identity();
    perspective_to_orthogonal << n, 0, 0, 0,
                                 0, n, 0, 0,
                                 0, 0, n + f, - n * f,
                                 0, 0, 1, 0;

    Eigen::Matrix4f orthogonal_projection = Eigen::Matrix4f::Identity();
    orthogonal_projection << 2.f/(r-l), 0, 0, 0,
                             0, 2.f/(t-b), 0, 0,
                             0, 0, 2.f/(n-f), 0,
                             0, 0, 0, 1;

    projection = orthogonal_projection * perspective_to_orthogonal;
    return projection;
}

你可能感兴趣的:(GAMES101,图形学)