文章目录
前言
-
图元装配是图形学渲染管线中很重要的一环。其目的在于将位于模型坐标系下的顶点,通过矩阵运算,最终变换至标准设备坐标系下(NDC);
-
具体来说是 本地坐标系->世界坐标系->摄像机坐标系->裁剪坐标系->标准化设备坐标系,如下图所示:
-
-
其中模型矩阵和视图矩阵的推导很容易理解,但是透视投影矩阵即使理解了也要每次推导一遍才能确认自己明白了。因此写下这篇博文,帮助自己加深印象。同时也希望它能帮助你理解透视投影矩阵,我会尽量详细地讲解每一个步骤;
-
但是正如你能在其他解释图元装配的文章一样,有必要说明一下——除非你有需要,否则你可以不用关心这些矩阵是怎么来的。当你真正用到它们的时候再去查阅资料也来得及;
-
原创不易,转载请注明出处和作者,谢谢!
前置知识
- 了解透视投影的原理,至少知道视锥体的存在;
- 知道齐次坐标,至少知道w分量的存在;
视见体和标准设备坐标系
为了明白透视投影的目的,有必要先了解什么是视见体和标准设备坐标系:
- 视见体是长度为2、宽度为1、高度为2的一个立方体;
- 标准设备坐标系是 x∈[-1, 1]、y∈[-1, 1]、z∈[0, 1] 的一个坐标系;
如下图所示,正如你所看到的是,视见体往往可以等价于标准设备坐标系:
那么视见体和标准设备坐标系在渲染管线中起到什么作用呢?答案是位于视见体以外的所有顶点会被丢弃(或者说裁剪)掉。换一句话说,渲染管线只会使用坐标位于视见体中的顶点,继续参与后面的渲染过程。
- 需要注意的是不同图形API对视见体的规定不一样,上面的是DirectX3D的标准;而OpenGL的标准对z的要求是[-1, 1]。但是这对透视投影矩阵的推导影响不大;
- 后面的视见体采用的是上面所说的标准。
透视投影
原理
接下来看看透视投影的视锥体,这里借用一段引用来简单解释视锥体1:
视锥体(frustum)是指场景中摄像机的可见的一个锥体范围。它由上、下、左、右、近、远共6个面组成。在视锥体内的景物可见,反之则不可见。
需要补充的是,视锥体中的景象最后会被被投影到近平面上。这里的视锥体好比如人类的眼球成像原理,物点经过晶状体后投影在视网膜上,人才能看到物体(左图是人眼的成像原理,右图是透视投影的成像原理 ):
目的/结果
从上面的原理中可以看出视锥体和视见体的共同点:
- 渲染管线只会渲染视见体中的内容;
- 视锥体是人为规定的一块区域,希望只能显示这其中的内容。
因此,透视投影矩阵的目的就是通过映射关系,将视锥体区域映射到视见体中。从数学角度上解释,则是为了让视锥体中的点,在经过投影矩阵以后,符合以下公式:
− 1 ≤ X N D C ≤ 1 − 1 ≤ Y N D C ≤ 1 0 ≤ Z N D C ≤ 1 其 中 X N D C , Y N D C , Z N D C 为 视 锥 体 中 的 点 在 N D C 坐 标 系 下 的 坐 标 -1\leq X \scriptsize NDC \normalsize \leq 1 \\ -1\leq Y \scriptsize NDC \normalsize \leq 1 \\ 0\leq Z \scriptsize NDC \normalsize \leq 1 \\ 其中X \scriptsize NDC \normalsize , Y \scriptsize NDC \normalsize , Z \scriptsize NDC \normalsize 为视锥体中的点在NDC坐标系下的坐标 −1≤XNDC≤1−1≤YNDC≤10≤ZNDC≤1其中XNDC,YNDC,ZNDC为视锥体中的点在NDC坐标系下的坐标
透视投影矩阵的推导
有了上面的结论以后,接下来进行推导——设法将一个处于视锥体中的点P,经过一个矩阵,使得其处于视见体范围当中。
- 为了计算和描述方便,我们假设视锥体如下:
左 面 : l e f t , 右 面 : r i g h t 上 面 : t o p , 下 面 : b o t t o m 近 平 面 : n e a r , 远 平 面 : f a r 左面: left,\ 右面: right\\ 上面: top,\ 下面: bottom\\ 近平面: near, \ 远平面: far 左面:left, 右面:right上面:top, 下面:bottom近平面:near, 远平面:far
即如下图所示:
- 并对计算结果有下面的表示:
视 锥 体 下 点 P f : ( X f , Y f , Z f , 1 ) 近 平 面 下 点 P n : ( X n , Y n , n e a r , 1 ) 投 影 矩 阵 运 算 后 点 P p : ( X p , Y p , Z p , 1 ) f 表 示 f r u s t u m , 表 示 视 锥 体 下 的 点 n 表 示 n e a r , 表 示 近 平 面 下 的 点 p 表 示 p r o j e c t i v e , 表 示 投 影 矩 阵 运 算 后 的 点 视锥体下点P \scriptsize f \normalsize: (X \scriptsize f \normalsize ,Y \scriptsize f \normalsize ,Z \scriptsize f \normalsize ,1 ) \\ 近平面下点P \scriptsize n \normalsize: (X \scriptsize n \normalsize ,Y \scriptsize n \normalsize ,near \normalsize ,1 ) \\ 投影矩阵运算后点P \scriptsize p \normalsize: (X \scriptsize p \normalsize ,Y \scriptsize p \normalsize ,Z \scriptsize p \normalsize ,1 )\\ f表示frustum,表示视锥体下的点\\ n表示near,表示近平面下的点\\ p表示projective,表示投影矩阵运算后的点\\ 视锥体下点Pf:(Xf,Yf,Zf,1)近平面下点Pn:(Xn,Yn,near,1)投影矩阵运算后点Pp:(Xp,Yp,Zp,1)f表示frustum,表示视锥体下的点n表示near,表示近平面下的点p表示projective,表示投影矩阵运算后的点
1. 计算视锥体的点投影到近平面的x、y坐标
前面说过,视锥体中的景象会被投影到近平面。因此我们的第一步就是计算视锥体中的一个点,其投影到近平面的点Pp。
计算原理很简单,我们可以使用相似三角形分别计算得到,如下图所示计算近平面的x坐标:
同理通过同样的方法计算近平面的y坐标:
因此我们得到近平面的x、y坐标分别为:
X n = n e a r ⋅ X f Z f Y n =