最近在重温计算机图形学的基础知识,期望能做到温故知新,加深对其的理解,以便能从容应对工作中各种情况。
  小弟水平有限,若有不正确之处,欢迎大家批评指正。
相关文章链接:
【计算机图形学基础】线性代数基础1
【计算机图形学基础】线性代数基础2
【计算机图形学基础】相机矩阵
【计算机图形学基础】投影矩阵
【计算机图形学基础】光照模型和着色频率
【计算机图形学基础】阴影映射

1 投影矩阵的作用

  投影分为正交投影和透视投影。
  正交投影会保留场景原始的画面,平行的线仍然平行;
  透视投影会产生近大远小的效果,平行的线不再平行。
  投影矩阵将相机空间的顶点全部转换到裁剪空间,裁剪空间的点处于齐次坐标系中,x, y和z除以齐次坐标后,值范围为[-1, 1]。
  齐次坐标转换到笛卡尔坐标后,才能进行视口变换,如下所示:

   ( x y z w ) \begin{pmatrix}x \\ y \\ z \\ w\end{pmatrix} ⎝ ⎛​xyzw​⎠ ⎞​ ----> ( x w y w z w 1 ) \begin{pmatrix}\frac{x}{w} \\ \frac{y}{w} \\ \frac{z}{w} \\ 1\end{pmatrix} ⎝ ⎛​wx​wy​wz​1​⎠ ⎞​----> ( x w y w z w ) \begin{pmatrix}\frac{x}{w} \\ \frac{y}{w} \\ \frac{z}{w}\end{pmatrix} ⎝ ⎛​wx​wy​wz​​⎠ ⎞​

2 正交投影

2.1 视景体

  正交投影的视景体如下图所示:
视景体
  该视景体是一个立方体,在 x y z xyz xyz 组成的的相机空间中;
  l 代表视景体左截面x坐标,r 代表视景体右截面x坐标;
  b 代表视景体底截面y坐标,t 代表视景体上截面y坐标;
  n 代表视景体近截面z坐标,f 代表视景体远截面z坐标;
  视景体中,l 一定小于 r,b 一定小于 t。相机空间中,可视点的 z 值一定小于0,所以 n 一定大于 f。

2.2 正交投影变换

  正交投影变换包含两个步骤:
  ① 将视景体中心平移到原点;
  ② 执行缩放,使 xyz的范围为[-1, 1]。
正交投影变换
  上述变换要分别使用平移矩阵 M T M_{T} MT​ 和缩放矩阵 M S M_{S} MS​。
  平移矩阵如下:

M T M_{T} MT​ = ( 1 0 0 − ( l + r ) 2 0 1 0 − ( b + t ) 2 0 0 1 − ( n + f ) 2 0 0 0 1 ) \begin{pmatrix}1 & 0 & 0 & -\frac{(l+r)}{2}\\0 & 1 & 0 &-\frac{(b+t)}{2}\\0 & 0 & 1 & -\frac{(n+f)}{2}\\0 & 0 & 0& 1\end{pmatrix} ⎝ ⎛​1000​0100​0010​−2(l+r)​−2(b+t)​−2(n+f)​1​⎠ ⎞​

  缩放矩阵如下:

M S M_{S} MS​ = ( 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ) \begin{pmatrix}\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{pmatrix} ⎝ ⎛​r−l2​000​0t−b2​00​00n−f2​0​0001​⎠ ⎞​

  现以 x 为例来推导缩放因子。
  平移视景体中心到原点后,由于视景体是对称的立方体,所以 − n < x < n -n < x < n −n<x<n,其中n > 0,且 n = r − l + r 2 r - \frac{l+r}{2} r−2l+r​ = r − l 2 \frac{r-l}{2} 2r−l​。
  为了让 − 1 < x < 1 -1 < x < 1 −1<x<1,因此需要乘以系数 1 n \frac{1}{n} n1​,即 2 r − l \frac{2}{r-l} r−l2​。
  其他两个维度的推导也是如此。
  综上,正交投影矩阵 M O r t h o M_{Ortho} MOrtho​ = M S M_{S} MS​ M T M_{T} MT​。

  结果如下: M O r t h o M_{Ortho} MOrtho​ = ( 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 − 2 f − n − f + n f − n 0 0 0 1 ) \begin{pmatrix}\frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{-2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{pmatrix} ⎝ ⎛​r−l2​000​0t−b2​00​00f−n−2​0​−r−lr+l​−t−bt+b​−f−nf+n​1​⎠ ⎞​

  注意,如果视景体的aspect ratio != 1,经过正交变换后,图像会被拉伸。最后,会通过视口变换进行纠正。

3 透视投影

  透视投影是应用最广泛的投影,它能产生近大远小的效果,平行线经过透视投影后不再平行。

3.1 视椎体

视椎体
  同正交投影一样,透视投影也有自己的l、r、b、t、n、f。不同的是,各个截面会相交于相机空间的原点。
  视椎体中的顶点被投影到近平面上,从而被渲染到屏幕。

3.2 决定视椎体的因素

  视椎体由如下因素决定:① field of view;② aspect ration;③ near 和 far。
fovy和aspect ratio
  视椎体是个对称的平截头体,现以侧面YZ平面来分析:
在这里插入图片描述
  现在已知fovY、apsect ratio = w i d t h h e i g h t \frac{width}{height} heightwidth​、near和far,视椎体是一个对称平截头体,且规则地放在 − Z -Z −Z轴上。
  根据正切定理,有 t = t a n ( f o v Y 2 ) tan(\frac{fovY}{2}) tan(2fovY​) * ∣ n ∣ |n| ∣n∣;又根据对称性,得到 -t = b;
  又根据 aspect ratio = r t \frac{r}{t} tr​ = w i d t h h e i g h t \frac{width}{height} heightwidth​,因此 r = aspect ratio * t;又因为对称性,所以有 -r = l。
  综上,可根据fovY、aspect ration、near 和 far可求得 l、r、b 和 t。

3.3 透视投影矩阵

3.3.1 相似变换

  以侧面 YZ 面来进行分析:
在这里插入图片描述
  由相似三角形,点投影到近平面后,其 y ′ y' y′ = ∣ n ∣ ∣ z ∣ \frac{|n|}{|z|} ∣z∣∣n∣​ * y y y;
  同理,该点的x轴坐标为 x ′ x' x′ = ∣ n ∣ ∣ z ∣ \frac{|n|}{|z|} ∣z∣∣n∣​ * x x x。
  在OpenGL中,通常near和far必须指定为大于0,因此,由于 z < 0 z < 0 z<0,有:
   x ′ x' x′ = − n z -\frac{n}{z} −zn​ * x x x, y ′ y' y′ = − n z -\frac{n}{z} −zn​ * y y y。

3.3.2 推导影响x、y分量的元素

   x x x 经过投影后成为 x ′ x' x′, x ′ x' x′在近平面上,因此有: l < x ′ < r l < x' < r l<x′<r;

  减去 l,有: 0 < x ′ − l < r − l 0 < x' - l < r - l 0<x′−l<r−l;

  除以 r − l r - l r−l,有: 0 < x ′ − l r − l < 1 0 < \frac{x' - l}{r - l} < 1 0<r−lx′−l​<1;

  乘以2,有: 0 < 2 x ′ − l r − l < 2 0 < 2\frac{x' - l}{r - l} < 2 0<2r−lx′−l​<2;

  减去1,有: − 1 < 2 x ′ − l r − l − 1 < 1 -1 < 2\frac{x' - l}{r - l} - 1< 1 −1<2r−lx′−l​−1<1;

  将上述等式优化,有: − 1 < 2 x ′ − 2 l r − l − r − l r − l < 1 -1 < \frac{2x' - 2l}{r - l} - \frac{r-l}{r-l}< 1 −1<r−l2x′−2l​−r−lr−l​<1;

  有: − 1 < 2 x ′ − l − r r − l < 1 -1 < \frac{2x' - l - r}{r - l}< 1 −1<r−l2x′−l−r​<1;

  有: − 1 < 2 x ′ r − l − r + l r − l < 1 -1 < \frac{2x'}{r - l} - \frac{r+l}{r-l}< 1 −1<r−l2x′​−r−lr+l​<1;

  将上述 x ′ x' x′ 替换为 x x x(相机空间坐标点),有: − 1 < − 2 n x z ( r − l ) − r + l r − l < 1 -1 < \frac{-2nx}{z(r - l)} - \frac{r+l}{r-l}< 1 −1<z(r−l)−2nx​−r−lr+l​<1; (等式①)

  因此,若将下述矩阵作为透视变换矩阵,有:

   M P e r s p e c t M_{Perspect} MPerspect​ = ( 2 n r − l 0 r + l r − l 0 . . . . . . . . . . . . . . . . . . . . . . . . 0 0 − 1 0 ) \begin{pmatrix}\frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0\\... & ... & ... & ...\\... & ... & ... & ...\\0 & 0 & -1 & 0\end{pmatrix} ⎝ ⎛​r−l2n​......0​0......0​r−lr+l​......−1​0......0​⎠ ⎞​

  现求取 x x x分量进行验证, M P e r s p e c t M_{Perspect} MPerspect​ x ( x y z w ) \begin{pmatrix}x \\y \\z \\w \end{pmatrix} ⎝ ⎛​xyzw​⎠ ⎞​,该结果的 x x x 分量为: 2 n r − l x \frac{2n}{r-l}x r−l2n​x + r + l r − l z \frac{r+l}{r-l}z r−lr+l​z;

  该结果的 w w w 分量(齐次坐标)为: 0 ∗ x 0 * x 0∗x + 0 ∗ y 0 * y 0∗y + ( − 1 ∗ z ) (-1 * z) (−1∗z) + 0 ∗ w 0 * w 0∗w = − z -z −z;

  齐次坐标转换为笛卡尔坐标需要除以 w w w,故上述 x x x 分量转换到笛卡尔坐标后为: 2 n x − z ( r − l ) \frac{2nx}{-z(r-l)} −z(r−l)2nx​ - r + l r − l \frac{r+l}{r-l} r−lr+l​。该值和前述推导等式①一致。

  综上,透视投影矩阵的第一行元素就确定下来了。
  同理,可以确定透视投影的第二行元素,其推导方法和前述一致,只是把 r r r 和 l l l 分别替换为 t t t 和 b b b。

   M P e r s p e c t M_{Perspect} MPerspect​ = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 . . . . . . . . . . . . 0 0 − 1 0 ) \begin{pmatrix}\frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0\\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0\\... & ... & ... & ...\\0 & 0 & -1 & 0\end{pmatrix} ⎝ ⎛​r−l2n​0...0​0t−b2n​...0​r−lr+l​t−bt+b​...−1​00...0​⎠ ⎞​

3.3.3 推导影响z分量的元素

  投影后的点在近平面上, x x x 和 y y y 不会对 z z z 有影响,那么设透视投影矩阵为:

   M P e r s p e c t M_{Perspect} MPerspect​ = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 A B 0 0 − 1 0 ) \begin{pmatrix}\frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0\\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0\\0 & 0 & A & B\\0 & 0 & -1 & 0\end{pmatrix} ⎝ ⎛​r−l2n​000​0t−b2n​00​r−lr+l​t−bt+b​A−1​00B0​⎠ ⎞​

  其中 A 和 B 是待求解的未知数。

  有: z ′ z' z′ = ( A z + B w Az + Bw Az+Bw) / ( − z -z −z);

  其中 A z + B w Az + Bw Az+Bw 表示进行投影变换,此时点处于裁剪空间。

  ( A z + B w Az + Bw Az+Bw) / ( − z -z −z) 表示将裁剪空间转换到NDC。

  当相机空间的点在近平面时, z ′ z' z′ 需要被投影为-1,且此时 z z z = -near;
  当相机空间的点在远平面时, z ′ z' z′ 需要被投影为1,且此时 z z z = -far;

  因此,可以列出两个方程:

  ① − 1 -1 −1 = − n A + B n \frac{-nA + B}{n} n−nA+B​;

  ② 1 1 1 = − f A + B f \frac{-fA + B}{f} f−fA+B​;

  两个方程,两个未知数,解得 A A A = − f + n f − n -\frac{f+n}{f-n} −f−nf+n​, B B B = − 2 f n f − n -\frac{2fn}{f-n} −f−n2fn​。

  综上,透视投影的方程如下:

   M P e r s p e c t M_{Perspect} MPerspect​ = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 − f + n f − n − 2 f n f − n 0 0 − 1 0 ) \begin{pmatrix}\frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0\\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0\\0 & 0 & -\frac{f+n}{f-n} & -\frac{2fn}{f-n}\\0 & 0 & -1 & 0\end{pmatrix} ⎝ ⎛​r−l2n​000​0t−b2n​00​r−lr+l​t−bt+b​−f−nf+n​−1​00−f−n2fn​0​⎠ ⎞​

4 投影矩阵之后

4.1 裁剪空间

    相机空间中的顶点应用了投影矩阵后,便进入了裁剪空间,其中 w c l i p w_{clip} wclip​ 即齐次坐标:

( x c l i p y c l i p z c l i p w c l i p ) \begin{pmatrix}x_{clip} \\ y_{clip} \\ z_{clip} \\ w_{clip} \end{pmatrix} ⎝ ⎛​xclip​yclip​zclip​wclip​​⎠ ⎞​ = M p r o j e c t i o n ( x c a m y c a m z c a m w c a m ) M_{projection} \begin{pmatrix}x_{cam} \\ y_{cam} \\ z_{cam} \\ w_{cam} \end{pmatrix} Mprojection​⎝ ⎛​xcam​ycam​zcam​wcam​​⎠ ⎞​

4.2 NDC

   进入裁剪空间的点,被齐次坐标相除。此后,顶点被转变到笛卡尔坐标中。此时的坐标空间被称为标准设备坐标系(NDC)。如下所示:

( x n d c y n d c z n d c ) \begin{pmatrix}x_{ndc} \\ y_{ndc} \\ z_{ndc}\end{pmatrix} ⎝ ⎛​xndc​yndc​zndc​​⎠ ⎞​ = ( x c l i p / w c l i p y c a m / w c l i p z c a m / w c l i p ) \begin{pmatrix}x_{clip} / w_{clip} \\ y_{cam} / w_{clip} \\ z_{cam} / w_{clip}\end{pmatrix} ⎝ ⎛​xclip​/wclip​ycam​/wclip​zcam​/wclip​​⎠ ⎞​

   在NDC中,三轴的坐标值被转换到 [-1, 1] 中。

4.3 视口变换

   NDC的坐标经过视口变换(viewport transformation)后,能得到每个顶点在屏幕空间的坐标。
   视口变换中,NDC坐标将会被缩放、平移,从而去匹配渲染屏幕。最后,屏幕空间坐标将会被用于光栅化。
   屏幕空间的原点在视口左下角,+x水平向右,+y水平向上。
   假如有屏幕空间原点( x o x_{o} xo​, y o y_{o} yo​),窗口的宽度 w w w 和高度 h h h,转换如下:

( x w y w z w ) \begin{pmatrix}x_{w} \\ y_{w}\\ z_{w}\end{pmatrix} ⎝ ⎛​xw​yw​zw​​⎠ ⎞​ = ( w 2 x n d c + ( x o + w 2 ) h 2 y n d c + ( y o + h 2 ) z n d c ) \begin{pmatrix}\frac{w}{2} x_{ndc} + (x_{o} + \frac{w}{2})\\ \frac{h}{2} y_{ndc} + (y_{o} + \frac{h}{2}) \\z_{ndc}\end{pmatrix} ⎝ ⎛​2w​xndc​+(xo​+2w​)2h​yndc​+(yo​+2h​)zndc​​⎠ ⎞​

    x w x_{w} xw​ 和 y w y_{w} yw​ 都会被转换成整数,像素中心在( x w x_{w} xw​ + 0.5, y w y_{w} yw​ + 0.5)。
   上述转换中,有如下对应关系:
    x o x_{o} xo​ 对应 -1, x o x_{o} xo​ + w 对应1;
    y o y_{o} yo​ 对应 -1, y o y_{o} yo​ + h 对应1。

5 参考

  1. mathematics-physics-for-computer-graphics/lookat-function
  2. 推导相机矩阵
  3. GAMES101-现代计算机图形学入门-闫令琪
  4. gl_transform
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐