建议开始前阅读前文:http://www.songho.ca/opengl/gl_projectionmatrix.html
在GAMES101的第四课中,闫令琪老师推导了由透视坐标(Perspective Projection)变换为正射坐标(Orthographic Projection Matrix)的矩阵。
在课后,闫老师留下了一个问题:对于 n 到 f 的范围内的 z,在经过变换后,中间的 z 会变大,变小还是不变?
在OpenGL中,我们将一个右手系的透视区域

投影为一个棱长为2,中心为左手系原点的正方体正射投影区域的矩阵如下

在这个模型中,闫老师的问题可以转化为,
对变化前的 z,∃k,使得(−n)×k+(−f)×(1−k)=z
对变化后的 z′,∃m,使得(−1)×m+1×(1−m)=z′
求 k 和 m 的大小关系。
实际上,用更通俗的语言说,就是求变换前和变换后的 z 在前后两个平面的 z 坐标中的插值大小。
任取一个 k∈(0,1),则 z=−kn−f(1−k)=k(f−n)−f(即 k 越大,z 越靠近 −n)。
根据变换矩阵,我们可以求得点 (0,0,z,1) 变换后的坐标为 (0,0,f−n−(f+n)×z+f−n−2fn,−z)
因此,
z′=f−nf+n+z(f−n)2fn=f−nf+n+(k(f−n)−f)(f−n)2fn
同样的插值在 (−1,1) 中的结果为 1−2k。
令函数 F(k)=[f−nf+n+(k(f−n)−f)(f−n)2fn]−(1−2k)
我们只需要讨论它在 k∈(0,1) 上的符号即可判断 z 的变换情况。如果F(k)>0,说明 z 在被变换后插值更大,更接近 −n 一侧,反之则更接近 −f 一侧。
因为
F′(k)=2−(k(f−n)−f)22fn
F′′(k)=(k(f−n)−f)34fn<0,k∈(0,1)
而
F′(0)=2−f2n>0
F′(1)=2−n2f<0
因此, F(k) 在 (0,1) 上先单调递增,再单调递减。而 F(0)=F(1)=0,因此,∀k∈(0,1),F(k)>0。
所以,对任意的变换后的 z,比起变换前的 z 来说,要更接近 n 平面的一侧。