概述
电脑显示器是2D平面,一个3D物体通过OpenGL渲染投影到2D显示器平面形成图像,GL_PROJECTION是OpenGL用于投影转换的矩阵。首先,转换3D物体的顶点数据从相机空间到裁剪空间,然后,通过除以W(齐次坐标)从裁剪空间再转换到标准设备空间(NDC)。
因此,我们需要意识到裁剪计算和NDC转换都是整合到了GL_PROJECTION矩阵里了。接下来的内容将探讨怎么构建投影矩阵,使用6个代表边界值的参数分别是:left,right,bottom,top,near , far(下面简写为l、r、b、t、n、f)。有一点注意一下,裁剪计算是在转换成NDC坐标之前发生的,即在除以(齐次坐标)之前。通过裁剪坐标,,和(这里的c下标表示裁剪空间)做对比,如果裁剪坐标小于或大于将被裁减掉(),然后OpenGL会重新构建网格边缘。
透视投影
在透视投影里,一个3D点在一个平头视锥体里面(相机空间)是要被映射到一个正方体(NDC空间)里的,x坐标的区间从[l,r]映射到[-1,1],y坐标的区间从[b,t]映射到[-1,1],z坐标的区间从[-n,-f]映射到[-1,1]。
注意一点,相机空间是使用右手坐标系统,但是NDC坐标空间使用左手坐标系统,这就是相机在原点沿着-Z方向看,但是在NDC空间是反过来的。因为glFrustum()仅仅接收正的near和far值,在构造GL_PROJECTION矩阵时我们需要给他们变成负值。
在OpenGL里,一个3D点在相机空间是被投影到near平面(projection plane 即下图的-n平面)。下面的图片展示一个点()在相机空间投影到near平面上的点()。
从上往下看视锥体,相机空间的x坐标点投影到,通过相似三角形原理得: = => = =
同理,从侧边看视锥体可得: = => = =
注意到, 和都依赖,他们和成相反的比例,也就是说他们都需要除以。这是非常有用的线索,用于构建GL_PROJECTION矩阵上,通过乘以GL_PROJECTION矩阵从相机空间转换到裁剪空间,坐标仍然是齐次坐标,除以裁剪空间的w最终变成规范化设备坐标空间(NDC)(更多资料请查阅OpenGL Transformation)
因此,我们可以设置裁剪空间的w坐标等于,然后投影矩阵GL_PROJECTION的第四行就变成(0,0,-1,0)。
下一步,我们通过线性关系映射(p下标表示投影空间未有裁剪的)和(p下标表示投影空间未有裁剪的)到NDC坐标空间的(n下标表示NDC空间)和(n下标表示NDC空间),即:[l,r] => [-1,1] [b,t] => [-1,1]
然后使用上面的和两个等式替换到和等式里:
注意到,我们故意把等式构造成除以的形式,即与透视除法()等同,只要把看成上面等式括号的值就是裁剪空间的和。
从上面的等式总结,我们可以找到GL_PROJECTION矩阵第一行和第二行的构造方法
现在GL_PROJECTION矩阵只剩下第三行没构造好,构造稍微不同于、,因为在相机空间ze总是投影在near平面的-n点上,由于我们需要z值方便做深度测试和裁剪,另外也需要逆转换投影,我们知道z是不依赖于x或y的值,我们可以借用w表示和之间的关系,因此我们可以构造GL_PROJECTION矩阵的第三行如下图:
在相机空间,等于1,因此等式变成:
为了求出系数A和B,根据上面等式得出和的关系,假设等于-n(即近平面)那么等于-1(即映射到NDC空间的坐标应为-1),等于-f(即远平面)那么等于1(映射到NDC空间的坐标应为1),带入上面等式:
由等式(1)推出:
把B等式代入等式(2):
把A等式代入等式(1):
得到A和B的等式可导出和的关系等式:
当视锥体是个对称视锥体时,r = -l , t = -b 所以可以简化矩阵公式:
最后,再审视一下上面等式(3)表达的和的关系。注意到这个等式函数是非线性关系的,意思是在近平面时会有非常高的精度,反过来在远平面会有非常低的精度。如果区间[-n,-f]是个很大的范围会导致出现深度(z值)精度的问题(z-fighting),改变很小的值不会计算得到对应的的值。所以,n和f之间的区间应该小点以减少z深度的精度问题。
正交投影
构造正交投影矩阵 GL_PROJECT比构造透视投影矩阵简单多了,只需要在相机空间里线性的映射到NDC空间。我们只需要缩放长方体变成正方体,然后移到原点位置,让我们看看GL_PROJECTION的各元素之间的线性关系吧。
因为正交投影矩阵是不需要用w计算z值的(z值也是线性关系直接求出来,透视投影需要用w来间接计算的关系),矩阵GL_PROJECTION的第四行保留为(0,0,0,1),因此完整的正交投影矩阵为:
当视锥体是对称长方体,即r = -l、t = -b,有:
坐标转换:模型坐标 -> 世界坐标 -> 相机坐标 -> 裁剪坐标 -> NDC坐标
原文链接