透视变换中变换后的Z坐标和变换前Z坐标的关系

建议开始前阅读前文:http://www.songho.ca/opengl/gl_projectionmatrix.html

前言

GAMES101的第四课中,闫令琪老师推导了由透视坐标(Perspective Projection)变换为正射坐标(Orthographic Projection Matrix)的矩阵。

在课后,闫老师留下了一个问题:对于 nnff 的范围内的 zz,在经过变换后,中间的 zz 会变大,变小还是不变?

OpenGL 中的透视投影

在OpenGL中,我们将一个右手系的透视区域

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

问题转化

在这个模型中,闫老师的问题可以转化为,

对变化前的 zzk\exists k,使得(n)×k+(f)×(1k)=z(-n) \times k + (-f) \times (1-k) = z

对变化后的 zz'm\exists m,使得(1)×m+1×(1m)=z(-1) \times m + 1 \times (1-m) = z'

kkmm 的大小关系。

实际上,用更通俗的语言说,就是求变换前和变换后的 zz 在前后两个平面的 zz 坐标中的插值大小

任取一个 k(0,1)k \in (0, 1),则 z=knf(1k)=k(fn)fz=-kn-f(1-k) = k(f - n) - f(即 kk 越大,zz 越靠近 n-n)。

根据变换矩阵,我们可以求得点 (0,0,z,1)(0, 0, z, 1) 变换后的坐标为 (0,0,(f+n)fn×z+2fnfn,z)(0, 0, \frac{-(f+n)}{f-n} \times z +\frac{-2fn}{f-n}, -z)

因此,

z=f+nfn+2fnz(fn)=f+nfn+2fn(k(fn)f)(fn)z' = \frac{f+n}{f-n} + \frac{2fn}{z(f-n)} = \frac{f+n}{f-n} + \frac{2fn}{(k(f-n)-f)(f-n)}

同样的插值在 (1,1)(-1, 1) 中的结果为 12k1-2k

令函数 F(k)=[f+nfn+2fn(k(fn)f)(fn)](12k)F(k) = [\frac{f+n}{f-n} + \frac{2fn}{(k(f-n)-f)(f-n)}] - (1 - 2k)

我们只需要讨论它在 k(0,1)k \in (0, 1) 上的符号即可判断 zz 的变换情况。如果F(k)>0F(k) > 0,说明 zz 在被变换后插值更大,更接近 n-n 一侧,反之则更接近 f-f 一侧。

因为

F(k)=22fn(k(fn)f)2F'(k) = 2 - \frac{2 f n}{(k(f-n) - f)^2}

F(k)=4fn(k(fn)f)3<0,k(0,1)F''(k) = \frac{4fn}{(k(f-n)-f)^3} < 0, k \in (0, 1)

F(0)=22nf>0F'(0) = 2 - \frac{2n}{f} > 0

F(1)=22fn<0F'(1) = 2 - \frac{2f}{n} < 0

因此, F(k)F(k)(0,1)(0, 1) 上先单调递增,再单调递减。而 F(0)=F(1)=0F(0) = F(1) = 0,因此,k(0,1)\forall k \in (0, 1)F(k)>0F(k) > 0

所以,对任意的变换后的 zz,比起变换前的 zz 来说,要更接近 nn 平面的一侧。