openGL中投影坐标矩阵的推导

参考:http://www.songho.ca/opengl/gl_projectionmatrix.html
http://www.songho.ca/opengl/gl_transform.html#projection
http://www.linuxidc.com/Linux/2015-08/122229.htm
http://web.cse.ohio-state.edu/~shen.94/5542/Site/Slides_files/coordinates5542.pdf(ndc到屏幕空间转换)
在这里插入图片描述
计算机屏幕是2D表面,openGL渲染的是3D场景,但最终要投影到2D的计算机屏幕上。GL_PROJECTION矩阵就是干这个的。顶点数据经过摄像机空间转换到裁剪空间,除以裁剪坐标的w分量得到ndc坐标。所以我们要记住裁剪坐标转换和ndc坐标转换都集成在了GL_PROJECTION矩阵。下面部分描述怎么样通过左右上下前后这6个边界参数创建投影矩阵。
注意,视锥体裁剪是在裁剪坐标下执行的,在除以w之前。裁剪坐标x、y、z是通过和w比较来测试的。如果任何裁剪坐标(x、y或z)大于w或者小于-w,则这个顶点就会被舍弃掉。当发生裁剪时,openGL会重建多边形的边。
#透视投影
下面为透视投影的视锥体
openGL中投影坐标矩阵的推导_第1张图片

其中,远裁剪平面距离原点为f, 近裁剪屏幕距离原点n。
设P(x0, y0,z0)投影到近平面上的Pn(x1, y1, z1)。
如下图所示,摄像机坐标是在右手坐标系下的,但NDC用的是左手坐标系。也就是说,摄像机看向的是摄像机空间的-z轴,却是ndc坐标系的+z轴。
openGL中投影坐标矩阵的推导_第2张图片
由于glFrustum()只接受near和far的正值,所以我们需要在创建GL_PROJECTION矩阵时,将near和far取反。
openGL中投影坐标矩阵的推导_第3张图片
如图所示,我们分别求x1,y1,z1。沿着x轴方向看横切面如图所示:
openGL中投影坐标矩阵的推导_第4张图片
投影后,x坐标为x1(在近裁剪平面投影),由相似三角形的性质,有:
openGL中投影坐标矩阵的推导_第5张图片

n为负,是由于视锥体和投影矩阵坐标系不同,一个是view空间,一个是投影空间。z轴方向不同
这样其实实现了透视投影近大远小的效果,因为z0越大,则x1,y1越小。为了将这两个值转换到[-1,1]区间内,设l和r分别为近裁剪平面左右边框的x左边,即l=-w/2,r=w/2。为了使任何投影到近裁剪空间的点都在区间内,转换后,[l’, r’]属于[0,1],其中l’,r’分别为l和r转换后的值。因为是线性变化,可另x’=kx+b;
openGL中投影坐标矩阵的推导_第6张图片
同理,y的表示:
openGL中投影坐标矩阵的推导_第7张图片
x和y投影后的左边都有共同因子[-1/z0],也就是说,他们都除以-ze。这是构建GL_PROJECTION矩阵的关键。view空间坐标乘以GL_PROJECTION矩阵后,裁剪坐标系还是一个齐次坐标。通过除以裁剪坐标系的w转换为NDC.如下图所示:
openGL中投影坐标矩阵的推导_第8张图片
所以我们可以将裁剪坐标系的w设为-z0。所以,GL_PROJECTION矩阵的第四行变成(0,0,-1,0),如图:
openGL中投影坐标矩阵的推导_第9张图片
接下来,我们看z要满足什么要求。为了简化讨论,根据以上结论,我们假设透视变换有下述形式(图片的p就是上面公式的b,bottom):
openGL中投影坐标矩阵的推导_第10张图片

openGL中投影坐标矩阵的推导_第11张图片
于是
openGL中投影坐标矩阵的推导_第12张图片
最后的变换矩阵为:
openGL中投影坐标矩阵的推导_第13张图片

如果视锥体是对称的,r=-l,t=-b,则
openGL中投影坐标矩阵的推导_第14张图片

z存在关系:
这里写图片描述
另外我们再看一个z2和z0关系,你会发现上述函数是有理函数,而z2和z0之间并不是线性关系。在近裁剪平面附近的地方精度较高,远裁剪平面附近的则较低。如果[-n,-f]范围变大,则会引起深度精度问题(z-fighting)。在远裁剪平面附近的z0值的很小的变化不会影响z0。所以n和f之间的距离应该尽量小,以减小深度缓存的精度问题。如图所示:
openGL中投影坐标矩阵的推导_第15张图片
openGL中投影坐标矩阵的推导_第16张图片

正交矩阵只需要考虑屏幕的最大最小值。上面的“为了将这两个值转换到[-1,1]区间内,设l和r分别为近裁剪平面左右边框的x左边,即l=-w/2,r=w/2。为了使任何投影到近裁剪空间的点都在区间内,转换后,[l’, r’]属于[0,1],其中l’,r’分别为l和r转换后的值。因为是线性变化,可另x’=kx+b;”
不用考虑z的变化,不需要w。
openGL中投影坐标矩阵的推导_第17张图片
如果r=-l,t=-b能继续简化。

你可能感兴趣的:(openGL)