
原文链接
https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf

在对线性图元(比如线条或三角形)进行光栅化时,简单的在ScreenSpace中对顶点属性进行线性插值通常不会得到正确的透视结果。
在传统的光栅化中,顶点常常包含如颜色,纹理坐标,法向量等属性。然而这种在三维空间的属性值在经过透视投影到二维的ScreenSpace屏幕后,其属性不会在ScreenSpace中不会遵循相同的线性变换。因此,如果我们在ScreenSpace中对各种属性应用简单的线性插值并不能得到正确的结果。下图就是这样的一个例子。

图1
为了简单的说明,图一仅仅显示了一条2D空间中的线段被投影到1D图像屏幕上,但相同的论点可以拓展到3D空间中的物体投影到2D平面。如图所示2D线段的两个端点AB分别投影到1D平面ab。这里的顶点属性值是intensity,在A处为0,B处为1,因此a和b的intensity也是0和1。假设点c是屏幕ab的中点,如果我们在ScreenSpace中线性插值属性可以得到c点的intensity为0.5。然而,如果我们将c“反投影”回线段AB上可以明显看出,C并不是AB的中点。由于intensity在AB之间线性变化,既然此时的C不是中点,那自然此时的intensity就不应该是0.5。
尽管如此,通过在ScreenSpace中进行线性插值仍然有获得视角正确的结果,只不过需要应用一些其他的函数方法,而不能直接对属性进行插值。并且这些函数中会用到顶点的z-values

INTERPOLATING z-VALUES
在透视投影之前,许多渲染系统假设虚拟相机作为三维空间的原点并看向+Z或者-Z。通常者叫做ViewSpace,相机固定的观察方向是我们能够始终拥有一个与z轴垂直的成像平面,这显著简化了透视投影的计算。考虑到通用情况,我们假设相机看向+Z,且图像平面与相机的距离为d。许多图像渲染系统应用z-buffer来执行隐面消除。这要求所有被投影到ScreenSpace的图元都需要维护一个其在3D空间中的深度值(z-value)。然而,由于实际被投影到ScreenSpace的只有这些图元的顶点,为了更快的进行光栅化我们希望利用这些已知的顶点z-valus去推导出图元内部像素的z-valus。
在3D世界中,z-values可以被视为一种顶点属性使其可以进行线性变化,但在ScreenSpace中却不是这样。在接下来的内容中我们可以看到,对z-values的倒数进行线性插值可以得到正确的结果。
与图1类似,图2中添加了在公式推导中会用到的符号,其中s是ScreenSpace中的插值系数,t是原始物体上的插值系数。

图2
我们的目标是可以正确的在ScreenSpace中插值z值,也就是s和t直接的关系,相同的推导也可以直接应用于3D线性图元投影到2D屏幕的情况。
参考图2我们可以得到

通过在ScreenSpace进行线性插值,我们有

通过在ViewSpace中的线性插值,我们有

将式4,5代入3可得

将式1,2代入7可得

将式6代入8可得

并化简为

然后将10代入6可得

最后化简为

公式(12)告诉我们,图像平面中某点 ccc 的 z 值可以通过在 1/Z11/Z_11/Z1 和 1/Z21/Z_21/Z2 之间进行线性插值来正确推导出来,然后再对插值结果取倒数即可得到真正的 z 值。
但对于 z-buffer 的用途来说,甚至不需要计算最终的倒数,因为我们只需要在 z 值比较时反转比较运算符的方向就可以了。

INTERPOLATING ATTRIBUTE VALUES
在这里我们希望推导出一个可以在屏幕空间中正确插值其他属性值的公式。
回顾图2我们在ViewSpace中线性插值其他属性值可以得到

将式10代入13得到

我们整理上式可得

从式12中我们发现,分母就是1/Zt,因此

式16意味着在ScreenSpace中,点c的属性值可以通过I1/Z1和I2/Z2进行线性插值得到正确的推导,然后将插值结果除以1/Zt,而Zt本身可以通过在ScreenSpace中的线性插值得到,如式12所示。