透视投影需要保证,1.变换矩阵内的元素是常数,2.相对深度值不变(绝对值不重要);若再加上变换后zNear和zFar平面上的点依旧在zNear和zFar平面上这两个条件(实际上并不一定需要满足这两个条件),那么即可求解得到M矩阵第3行(0,0,a,b)中a,b的取值;
一、问题提出
在GAMES101-Lecture4 Transformation Matrices 一节中,闫老师介绍了正交投影 和透视投影。
在讲透视投影 变换矩阵 M p e r s p → o r t h o M_{persp→ortho} Mpersp→ortho时,很多同学对于其中的z
分量是变化的还是不变的有很多争论。即下图中z
分量经过变换后的z'
底是保持不变依旧等于z
,还是"unknown"
大家有不同的看法。基于查阅的资料,我将在本文中谈一下自己对于这个问题的理解,并对投影变换矩阵 的计算公式进行解释。
二、投影变换
1. 正交投影 Orthographic Projection
(1). 正交投影目标:
将指定立方体 内部的点映射(变换)到正则立方体(canonical cube) 内。正则立方体 是一个中心点在原点,(x,y,z)
三个分量都在[-1,1]
范围内的正方体。
如将下图左侧立方体内部的点,先经过平移(Translate),再经过放缩(Scale)变换后,即可投影到正则立方体 内。
(2). 正交投影矩阵 M o r t h o M_{ortho} Mortho:
正交投影矩阵 可以由平移矩阵 和放缩矩阵相乘得到:
2. 透视投影
(1). 透视投影目标:
将视体 内部的点映射(变换)到正则立方体(canonical cube)内。视体通常是一个方平截头体 ,可由fov, aspect_ratio, zNear
和zFar
这几个参数确定。
如下图所示:
(2). 透视投影步骤:
前面已经简单介绍过正交投影 了,正交投影 相对简单,只要进行平移+放缩两次变换即可得到
透视投影包含两步:
- 将视体 变换为立方体 , First "squish" the frustum into a cuboid (n -> n, f -> f) ( M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho) ;
- 进行正交投影 ,将立方体 变换到正则立方体 ,Do orthographic projection ( M o r t h o M_{ortho} Mortho);
为什么不直接使用平移+放缩+非仿射变换 直接求得透视投影矩阵 ,而是需要先将透视投影 转为立方体 ,再进行一次正交投影 这两步(这两步称之为透视规范化 )?
因为:
- 规范化使得只需要一个流水线体系就可以进行透视投影 和正交投影;
- 尽可能位于四维齐次空间中,以便保持隐藏面消除和明暗处理 所需要的三维信息。透视投影 的第一步将视体 转到立方体依旧保持各点的z分量信息,便于之后进行深度处理等操作;
- 简化了裁剪的操作。第一步转为立方体 后,由于立方体的边都与空间的x,y,z轴平行,因此可以方便地裁剪掉立方体外的点;
(3). 透视投影矩阵:
在计算透视投影矩阵之前需要明确一点:目标投影矩阵 必须是一个固定的矩阵,针对视体 内的任何一点,都使用相同的一个矩阵,条件(1)
。
我们称第一步中从视体 变换到立方体 的矩阵 M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho为透视规范化矩阵 。
对于空间内的点(x,y,z)
(这里的x,y,z
是变量,因为空间需要进行投影变换的点不只一个),其变换后的点为(x',y',z')
。
其中:
x ′ = n z x , y ′ = n z y , z ′ = ? x'=\frac{n}{z}x, y'=\frac{n}{z}y, z'=? x′=znx,y′=zny,z′=?
a. 假设令z'
不变:
即:
x ′ = n z x , y ′ = n z y , z ′ = z x'=\frac{n}{z}x, y'=\frac{n}{z}y, z'=z x′=znx,y′=zny,z′=z
我们可以逆向算出对应的透视规范化矩阵 M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho
M p e r s p → o r t h o = ( n / z 0 0 0 0 n / z 0 0 0 0 1 0 0 0 0 1 ) M{persp→ortho} = \begin{pmatrix} n/z & 0 & 0 & 0 \\ 0 & n/z & 0 & 0 \\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix} Mpersp→ortho= n/z0000n/z0000100001
矩阵中n=zNear
是一个常数,然而矩阵中的z
是一个变量(即n/z
中的z
),对于视体 中的每一个不同的点,都需要一个特定的z
值,这个结果不是我们想要的,我们想要一个固定的、不随目标点变化的矩阵。
b. 假设令z'
改变:
根据a.
中的分析可以得出,假如令z'=z
,那么对于视体 中的每个点都需要一个透视规范化矩阵M ,不能满足条件(1)
。
因此我们需要令透视正则变换后的各点z'
值发生变化,以消除透视规范化矩阵M 中的变量z
。
一个简单的方式是,我们先假设此时不知道z'
等于什么,并令x',y'
和齐次坐标中的w'
都乘以z
。那么 透视规范化矩阵 M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho 可以写为:
M p e r s p → o r t h o = ( n 0 0 0 0 n 0 0 ? ? A B 0 0 1 0 ) M{persp→ortho} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ ? & ? & A & B\\ 0 & 0 & 1 & 0 \end{pmatrix} Mpersp→ortho= n0?00n?000A100B0
另外由于在投影变换后还需要进行阴影遮挡判断、隐藏面消除和明暗处理等操作,因此我们需要保证原始空间中z
值小的点,在投影正则化变换后的z'
值依旧小,条件(2)
。
条件(2)
也说明,z'
只能跟原始点齐次坐标中的z
和w
相关,跟x,y
无关,因此可以得到那么透视规范化矩阵 M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho 可以写为:
M p e r s p → o r t h o = ( n 0 0 0 0 n 0 0 0 0 A B 0 0 1 0 ) M{persp→ortho} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & A & B\\ 0 & 0 & 1 & 0 \end{pmatrix} Mpersp→ortho= n0000n0000A100B0
除此以外,我们还需要令原来在z=zNear
平面上的点,经过变换后依旧在z=zNear
平面上,原来在z=zFar
平面上的点依旧在z=zFar
平面上。这是因为,我们需要保证 边界上的点变换后依旧在边界上 ,条件(3)
。
假如不能保证满足条件(3)
,那么在经过投影正则化变化后,有可能原来在zFar
外面的点,在变换后到了立方体 内了!原本 视体 外需要被裁剪掉的点,变换到了立方体 内,这可能导致裁剪错误。
因此根据条件(3)
,可以得到下面两个公式:
( 0 0 A B ) ∗ ( x y n 1 ) = n 2 (0\ 0\ A\ B) * \begin{pmatrix} x \\ y \\ n \\ 1 \end{pmatrix} = n^2 (0 0 A B)∗ xyn1 =n2
同时:
( 0 0 A B ) ∗ ( x y f 1 ) = f 2 (0\ 0\ A\ B) * \begin{pmatrix} x \\ y \\ f \\ 1 \end{pmatrix} = f^2 (0 0 A B)∗ xyf1 =f2
根据这两个公式即可求得
A = n + f , B = − n f A=n+f, B=-nf A=n+f,B=−nf
这就是投影变换 中 M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho的由来。
3. 总结
投影变换的目标是:根据给出物体的参数(fov, aspect_ratio, zNear, zFar
等参数),计算得到一个投影变换矩阵M 。
这个矩阵是唯一固定的,即这个矩阵中的元素值只跟视体
相关,跟视体
中点的坐标无关,条件(1)
。
经过变换后,必须保证各个点的z
值相对关系不变,即假如点a 的z
值大于点b 的z
值,那么经过变换点a 的z'
依旧大于点b 变换后的z'
。那么z'
不能与(x,y,z,w)
中的x,y
相关,只能由z,w
确定,条件(2)
。
并且,视体 边界面z=zNear
平面和z=zFar
平面上点的经过变换后依旧在立方体 边界面上,条件(3)
。
为了满足条件(1)
:z'
不能等于z
。
为了满足条件(2)
: M p e r s p → o r t h o M{persp→ortho} Mpersp→ortho第三行 ( ? ? A B ) (?\ ?\ A\ B) (? ? A B) 前两个元素需要等于0。
为了满足条件(3)
:可以计算得到 A = n + f , B = − n f A=n+f, B=-nf A=n+f,B=−nf。
三、参考
1.计算机图形学第六章观察-黄章进-中国科学技术大学
2.GAMES101-Lecture 4:Transformation Matrices