透视投影矩阵
在说透视投影矩阵之前,先简单说下在3D世界中的一个物体的位置是如何定义的。
模型空间,局部坐标
一个物体,最开始是通过3D建模渲染软件比如3DMax制作出来的,因为一开始只是一个单独的模型,所以它开始会拥有一个局部坐标,来标识整个模型的位置。那么既然是单独的物体,为什么还要有局部坐标呢?是因为模型在这个坐标中,并不一定以模型的中心为坐标原点,而是以模型的特征来选择坐标的原点。比如一个人,会把它的脚放到局部坐标原点上。这样在后续往世界空间中放的时候就以这个点为基础做转换。
世界空间,世界坐标
模型是要在放到一个场景中展示的,这个场景就是处在世界空间中。所有物体的位置,都是以世界空间的坐标系定义的。
模型从模型空间到世界空间,就需要指定一个转换矩阵(这个矩阵可能包括旋转,缩放和平移),这个矩阵就叫做模型矩阵(Model Matrix)。
视图空间(View Space),摄像机空间
世界空间最后要展示到Camera中,需要做一次世界空间坐标向视图空间的转换。这个矩阵就是视图矩阵(View Matrix)。
为什么模型一开始不转换到视图空间中,而要在中间插入一个世界空间呢?
这么做的目的就是可以让设计者可以只关心整个世界的构造,而不用关心摄像机的位置。
透视投影
我们绘制的一切东西,最后都要展示到一个二维屏幕上。而且这个二维空间中物体呈现的效果是带有透视效果的,简单说是近大远小的效果。详细参考[1].
那在转换为二维屏幕坐标前,透视投影矩阵会将平截头体转换为一种单元立方体,它的的中心在坐标原点,上下左右的边界从-1到1。这就是CVV(canonical view volume),规则观察体。里面的坐标称为NDC,标准设备坐标。有了这个坐标,就不需要考虑具体设备分辨率的影响,之后的一系列操作就基于标准的坐标系。最后再经过视口转换,将-1到1之间的点转换为真正的设备分辨率的点坐标。
转换为CVV的一个重要作用就是可以高效剪裁。
最后将CVV映射到屏幕坐标系。
透视投影矩阵 Perspective Projection Matrix
PPM需要四个参数确定:
1)屏幕的高宽比 ar
2)相机的垂直视角大小 Fov
3)近剪裁面位置
4) 远剪裁面位置
这几个参数其实就是View Space中的平截头体的参数。透视投影就是将平截头体中的点,投影到CVV。
具体的推导过程可以参考:
http://wiki.jikexueyuan.com/project/modern-opengl-tutorial/tutorial12.html
其中有几个关键点:
1) 公式的推导主要借助了相似三角形原理中,相似三角形的对应边成比例。推导出了由摄像机处发出的穿过点P的射线,在投影平面和点P所在的xy平面之间形成的线段,与z轴与这两个平面之间形成的线段的比例关系。
2)为了保留z坐标在深度测试中的使用,z坐标要保留到w中。
3)z坐标在CVV中的范围是-1到1,所以通过变换近平面的z坐标转换到-1,远平面的z坐标转换到1,通过这两个方程,就可以确定PPM的第三行的值。
Reference:
[1] https://en.wikipedia.org/wiki/Perspective_(graphical)