4.6 Projections
在进行真正的场景渲染之前,必须把场景中的所有相关对象都投影到某个平面上或某种简单的包围体内。完成投影之后,就开始执行裁和渲染操作(见第2.3节)。
到目前为止,本章中的变换操作都没有使用到向量的第四个元素分量,
w
-分量。也就是说,点和向量在变换后依然为保持为原来的类型。另外,
在本节中,我们假设负
z
-轴表示观察者的观看方向,y轴表示向上的方向,x轴表示向右的方向。这是一种右手坐标系。在一些书本和软件中,比如DirectX,使用左手坐标系,其中观察者的趋向对应于正
4.6.1 Orthographic Projection(正交投影)
正交投影的特点之一是平行线在投影后依然保持平行。如下所示,矩阵
Po
是一个简单的正交投影矩阵,该投影不会改变坐标点的
x
- 和
这种投影的效果如图4.16所示。显然,矩阵
Po
是不可逆的,因为行列式
|Po|=0
。换句话说,该变换从三维降到二维,并且没有办法取回丢弃的维度。使用这种正交投影产生的观察问题是,它会把
z
分量值为正的坐标点和
图4.16 由公式4.59生成的简单正交投影的三个不同视图。我们可以把这种投影看成是观察者沿着负
注:near平面也称为front plane或者hither,far平面也称为back plane或者yon。
用于执行正交投影变换的矩阵通常使用六元组
(l,r,b,t,n,f)
表示,分别表示left,right,bottom,top,near以及far平面。这个矩阵本质上是缩放和平移AABB(轴对齐包围盒;详见第16.2节中的定义),通过把6个平面放置到以原点为中心的轴对齐立方体的每一面中形成的。AABB的最小拐角是
(l,b,n)
,最大拐角为
(r,t,f)
。需要重点注意的是
n>f
,因为我们是沿着该空间体的负
z
-轴方向观察。但是根据常识我们一般会认为near值应该是比far更小的数值。在OpenGL中观察方向也是朝向负
在OpenGL中,轴对齐立方体的最小拐角为
(−1,−1,−1)
,最大拐角为
(1,1,1)
;而在DirectX中,对应的边界为
(−1,−1,0)
到
(1,1,1)
。该立方体称为canonical view volume(规范视图体),里面的坐标称为normalized device coordinates(NDC规范化设备坐标)。变换过程如图4.17所示。之所以要变换到canonical view volume内,是因为在这种坐标下裁剪操作更高效。
图4.17 在canonical view volume上变换轴对齐包围框。首先对左图的包围盒执行平移操作,使其中心与原点重合。然后对其进行缩放使其与canonical view volume具有相同的大小,如右图所示。
变换到canonical view volume之后,就根据该立方体对要渲染的几何图形的顶点进行裁剪。最后通过把单位正方形映射到屏幕,渲染位于立方体范围内的几何图形。这种正交变换矩阵如下所示:
如该公式所示:矩阵 Po 可以写成一个平移矩阵 T(t) ,以及一个缩放矩阵 S(s) 的串联,其中 s=(2/(r−l),2(t−b),2/(f−n)) , t=(−(r+l)/2),−(t+b)/2,−(f+n)/2) 。该矩阵是可逆的,即 P−1o=T(−t)S((r−l)/2,(t−b)/2,(f−n)/2) 。
注:当且仅当 n≠f , l≠r 以及 t≠b 时是可逆的;否则,不存在可逆矩阵。
在计算机图形学中,经过投影变换之后通常使用左手坐标系—即对于视口来说,
x
-轴表示向右的方向,
这是一种镜像矩阵。正是通过这种镜像从右手观察坐标系(观察方向为负 z -轴)转换到左手normalized device coordinates(NDC)。
DirectX将
因此在DirectX中使用的正交矩阵为
通常使用矩阵的转置进行计算,因为在DirectXk中,通常使用行优先矩阵的表示方法。
4.6.2 Perspective Projection
比正交投影更有趣的一种变换是透视投影,在大多数计算机图形学应用程序中都会使用这种变换。在这种情况下,平行线在投影之后通常不再是平行的;相反,可能会在无穷远处聚集到单个点。透视投影更接近于我们感知真实世界的情况,即距离观察者越远的物体看起来越小。
首先,我们将提出一种有关透视投影矩阵的具有指导意义的推导过程,该投影矩阵把物体投影到平面 z=−d,d>0 上。从world space的推导到进一步简化对world-to-view变换的理解,最后推导出OpenGL中所使用的更规范的矩阵。
图4.18 用于推导透视投影矩阵的数学记号。其中点
p
投影到平面
z=−d,d>0
上,并产生投影点
q
。该投影是从相机所在位置的观察角度进行计算的,在这里为原点的位置。右图中显示了在推导过程中使用的针对
x
-分量的相似三角形。
假设相机(视点)位于坐标原点,并且我们想要将点
q
的其他分量对应的表达式为
qy=−dpy/pz
(计算过程与
qx
类似),
qz=−d
。与上述公式一起,可以推导出透视投影矩阵
Pp
,如下所示:
通过公式4.66的简单验证可以确认该矩阵产生的透视投影的正确性:
最后一步是基于整个向量除以
w
-分量(在这种情况下该分量值为
直观地说,很容易理解为什么齐次坐标允许投影。齐次化过程的一种几何解释是该操作把点 (px,py,pz) 投影到平面 w=1 上。
与正交变换一样,也有一个对应的透视变换,用于把视锥体变换为canonical view volume,而不是投影到一个具体的平面上(这种变换是不可逆的)。其中视锥体假定为起始于
z=n
处,并在
z=f
处结束,其中
0>n>f
。位于
z=n
处的矩形具有最小拐角值
(l,b,n)
,以及最大拐角
(r,t,n)
。如图4.19所示。
图4.19 使用矩阵
Pp
将视锥体变换成单位立方体,该立方体称为canonical view volume。
参数
(l,r,b,t,n,f)
确定了相机的视锥体。水平视域由左平面和右平面(由
l
和
视域是提供给观察者一种场景感觉的重要因素。与计算机屏幕相比,人的眼睛本身具有物理上的视域范围。这种对应关系为
其中 ϕ 表示视域, w 表示物体垂直于视线的宽度,
与物理设置相比,使用一个更窄的视域范围将会减少透视效果,因为场景中的观察者将会被放大。设置一个更宽的视域将使物体看起来变得扭曲(就像使用一个宽角度相机镜头),特别是靠近屏幕边缘的位置,并且会扩大附近物体的规模。但是,更宽的视域范围能够带给观察者一种物体变得更大,更令人印象深刻的感觉,并且具有向用户提供有关周围环境更多信息的优点。
使用公式4.68所示的透视变换矩阵可以把视锥体变换为一个单位立方体:
注:其中 far平面也可以设置为无穷远处。有关具体形式,请阅读345页的公式9.8。
对一个点执行该变换操作,我们将会得到另一个点
q=(qx,qy,qz,qw)T
。点
q
的
w
-分量
要获得在OpenGL中所使用的透视投影变换,与正交投影变换的理由一样,首先把
注:因此为了验证该投影矩阵在 z -方向真正有效,我们可以把矩阵
POpenGL 乘以向量 (0,0,−n′,1)T 。由此得到的向量的 z -分量值将为−1 。如果我们改用向量 (0,0,−n′,1)T , z -分量值将为+1 ,如期望的结果一致。对矩阵 P[0,1] 可以执行类似的测试。
有些API(比如DirectX)把near平面映射到
z=0
(而不是
z=−1
),far平面映射到
z=1
。此外,DirectX还使用左手坐标系定义其投影矩阵。意味着DirectX沿着正
z
-轴作为观察方向,并且把near和far值表示为正数。相应的,DirectX的投影公式如下所示:
DirectX在其文档中使用行优先的矩阵形式,因此该矩阵通常写成它的转置形式。
使用透视变换产生的一种影响是计算的深度值不会随着输入的
pz
值线性变化。例如,如果
n′=10
和
f′=110
(使用OpenGL术语),当
pz
位于负
z
-轴方向的60个单位长度时(即,near和far的中间点),normalized device coordinate的深度值为0.833,而不是0。图4.20中显示了改变near平面到原点的距离产生的影响结果。near和far平面到原点的距离会影响 Z-buffer 的精度。在第18.1.2节中我们将会进一步讨论由此带来的影响。
图4.20 改变 near平面到原点的距离产生的不同效果。其中
Further Reading and Resources
以一种轻松的方式建立对矩阵的直观理解,最好的书籍之一是 Farin 和 Hansford 的 The Geometry Toolbox[333]。另一本非常实用的书是Lengyel的 Mathematics for 3D Game Programming and Computer Graphics [761]。从不同的角度来讲,大量计算机图形课本,比如 Hearn 和 Baker [516],Shirley [1172],Watt 和 Watt [1330],以及 Foley 等人[348,349]所编写的书籍中也包含有基本的矩阵知识。在Graphics Gems系列书籍中[36,405,522,667,982]讲解了各种变换相关的算法,并在线提供了各种变换的实现代码。 Golub 和 Van Loan 的 Matrix Computations[419]是一本值得认真研究通用矩阵技术的入门书籍。参考http://www.realtimerendering.com/网站,上面包含了各种不同的变换操作以及四元数的代码。关于skeleton-subspace deformation/vertex blending 以及 shape interpolation 的更多信息,请阅读 Lewis 等人的SIGGRAPH论文[770]。
Hart 等人[507] 和 Hanson [498]提供了四元数的可视化。Pletinckx 和 Schlag [1126]提出了在一组四元数之间进行平滑插值的不同方法。 Vlachos 和 Isidoro [1305]推导出了关于四元数的 C2 插值公式。有关四元数插值的主要问题是如何沿着一条曲线计算一致的坐标系。Dougan已经解决该问题[276]。
Alexa [16]和Lazarus&Verroust [743]提出了关于各种不同的morphing技术的研究结果。