OpenGL左手坐标系透视矩阵全推导过程
OpenGL左手坐标系透视矩阵全推导过程
在计算机图形学中,透视投影矩阵是将3D场景转换为2D图像的关键组件。本文将详细介绍OpenGL中左手坐标系下透视矩阵的推导过程,从基本的坐标系概念开始,逐步推导出最终的投影矩阵。
坐标系基础
首先,我们先确定坐标系,坐标系分为左手坐标系和右手坐标系(在某些书上这被称为偏手性)。
如何确定一个坐标系是左手还是右手呢?只需要将你右手的拇指对准y轴,中指对准x轴,如果z轴刚好在食指指向的方向,那么这个坐标系是右手坐标系;如果z轴刚好和食指指向的方向相反,那么这个坐标系就是左手坐标系。
现在,我们选择右手坐标系为我们的变换前的坐标系。
观察方向
观察方向有两个,一个是Z轴方向,一个是负Z轴方向。我们现在选择看向负Z轴方向。
想象我们从天上鸟瞰整个场景:原点为摄像机所在位置(视图变化导致的),黑线框住的区域为摄像机的可使范围,粉线表示的是近平面,天蓝线表示的是远平面,里面的物体为摄像机的可视物体。
现在,假设摄像机可视范围内有一点P,连接P点与原点,与近平面相交得到交点P`。
这里定义一下n和f,n表示摄像机到近平面的距离,f表示摄像机到远平面的距离,所以n,f∈[0,+∞]。
所以因为摄像机看向的是负Z方向,所以近平面:z=-n,远平面:z=-f。
所以,线段OP与近平面交点P`的坐标为:
由相似三角形,我们可以得到等式:
恒等变换后:
同理可得:
P`以向量形式表示为:
转换到齐次坐标:
等价变换为:
我们将P→P的过程想象为变换,那么一定存在一个矩阵A,使得AP=P
,不妨列出等式:
由矩阵乘法的性质,我们可以很容易得到第一行第二行和第四行:
A=
那么第三行怎么求呢?根据两个重要定义:近平面上任意点通过矩阵A变换之后,坐标不变;远平面的中心点在经过矩阵A的变换之后,坐标保持不变。
由此可得:
解出方程:
解出矩阵A:
此时,若将视角内所有点乘上矩阵A,则会出现这样的情况:视锥内的一个正方体会被改变形状,其靠近近平面的面更大,靠近远平面的面更小。近平面大小不变,且远平面缩小到和近平面大小一致。
这个时候若将近平面远平面围成的区域看作一个正方体,那么我们可以开始第二步的正交变换了。
首先我们需要将这个由近平面和远平面构成的立方体中心移动到原地。
平移矩阵很简单,但在此之前,我们需要定义一些属性:r=近平面右边x值,l=近平面的左边x值,t=近平面的上边y值,b=近平面的下边y值。
平移矩阵T=
注意矩阵第三行第四个为非负值,因为近平面和远平面构成的立方体本身就处于Z的负轴上,如果,那么矩阵T不可能把立方体中心平移至原点。
然后我们需要一个缩放矩阵,假设为立方体中的一个点,那么,我们需要将都缩放至这个区间。
缩放矩阵S=
通过ATS三个矩阵的连续变换,我们能得到一个在右手坐标系下,n,f表示近远平面到摄像机距离的正确的投影矩阵。
但是,通过查证一些资料,得知了OpenGL的NDC,标准设备坐标系其实是左手系,也就是近平面与远平面需要对调一下,但这也不难理解,只需要将向量的z值变成它的相反数就好了,所以最终的投影矩阵:
由此可以得出结论,不同的坐标系下,采用不同的观察方向,以及n与f的定义都会影响到最终的投影矩阵。