46-透视修正算法
插值算法回顾
透视投影下,目前代码中,都是变化到屏幕空间坐标系后,按照屏幕空间形成的三角形对某点进行重心坐标插值:

但是在三维空间中,三角形是立体有深度(前后)的图形,需要使用空间中的三角形重心坐标,使用屏幕上二维的重心坐标是不准确的
问题分析(1)
逆着y轴看下去,可以得到如下平面视图:

由上图可知,在屏幕空间中,A`O`:B`O`=7:3
在三维空间中,AO:BO=5:5
可见两者的重心坐标并不相等,因此需要透视修正:
为了能方便计算屏幕空间三角形像素的重心坐标,需要找到一种方法计算三维空间对应点的重心坐标
问题分析(2)
顶点到屏幕,会经历如下空间变换:

我们已经知道三维空间投影到二维重心坐标会变换,那么N空间到S空间,对应点的重心坐标会发生变换吗?

如上图分析,N空间到S空间,会发生两个变换:
(1)顶点坐标从-1到1,变换为0-1,这个过程NDC内对应顶点重心坐标不会发生改变
(2)顶点坐标从为0-1变化为屏幕上具体的像素点,并且由于width与height不同,产生了横向与纵向的拉伸,可以理解为,先投影到1*1的幕布上,然后横向统一缩放width倍,纵向统一缩放height倍

可以知道,只要1*1幕布上重心坐标不变,则统一放大后,重心坐标是不变的

观察上面的直线投影,可知 AO:BO=A`O`:B`O`
说明O点在投影空间与屏幕空间中的插值比例是不变的

观察上图A与C的权重 α:γ = hc:ha = lc:la

观察上图A与C的权重 α:γ = hc:ha = lc:la
初步结论:
(1)存在O点在三角形内;
(2)在NDC下计算O点三维空间重心坐标
(3)在屏幕空间计算O点二维空间重心坐标二者相等
即,只需要修正视图空间下O点的重心坐标与NDC空间下O点坐标的关系即可
明确问题
在NDC空间,已知三角形三个点为A` B` C`,并且已知其中点O`在本三角形重心坐标为(α`,β`,γ`)
即通过点O`在屏幕空间三角形内重心坐标计算而来,与之相等的(α`,β`,γ`)
点O`在视图空间(摄像机坐标系)对应的三维点O
A` B` C`在视图空间(摄像机坐标系)对应的三维点为A B C
现在我们需要根据以上已知条件求出对应的三维空间中真正的插值重心坐标(α,β,γ)
透视修正推导
我们知道,A B C到A` B` C`的变换过程,是经过投影矩阵P变换的来的
P矩阵是4*4投影矩阵,可分解为: 3*3矩阵M,3维列向量t,以及最后一行数字abcd,而abcd这几个数字只会对w产生影响

假设NDC上有一个点O`,按照重心坐标定义,可知:

将其展开就可以得到:

O在是视图空间中,可以表示维A B C点经过重心坐标插值的结果:

O`也是由O经过投影P变换以及透视除法而来,可以得到:

将上述结果结合起来,得到:

由投影矩阵得到的如上公式适用于任何A B C取值,所以左右系数必须非零且相等,因此可以进一步得到:

至此,我们已经求出了两组系数之间的关系,距离得到真正的(α,β,γ)还需要知道Wo
由于已知重心坐标相加为1,可得:

从上就可以得到以下结论:

最终结论

探讨Depth深度插值
对于顶点的z值,经过投影矩阵以及透视除法后,到达NDC坐标下,经过屏幕空间变换,到达0-1的坐标范围内,称为Depth
此时Depth作为一个被插值的属性,可否之间使用屏幕空间的重心坐标插值呢?
考察透视除法z变化的细节:

由上可知: Zndc当中的常数项可以忽略,插值之后不会发生改变;
Zndc当中的第二项,已经变成了z的倒数(1/z相当于1/w)即下图公式可直接使用,因此可以直接在屏幕空间使用重心坐标(α`,β`,γ`)进行插值,不用再走透视修正的流程

