Real-Time Shadows 2
在PCF的最后一步,需要对一定范围内的所有深度值做比较,如果深度值大于着色点的深度值记为1,小于记为0.然后求平均。这种操作需要花费较多的时间。这种行为可类比于在一个班级中,知道自己的分数,想要知道自己在班级中的排名,需要和班级中每一位同学的分数比较。一种改进的方法是只需要知道有多少人比我的分数高,当然也不需要非常准确的范围,于是在一个根据成绩的正态分布中,就可以知道自己的大致排名了。而对于正态分布,只需要知道方差和期望。这也就是VSSM的思路,用来解决PCF的最后一步的算法。
当然PCSS在范围内查询时,可以使用采用的方法,就是没有在范围内全部查询,这样会有噪声。不过由于图形处理会解决噪声问题,PCSS的使用还是比较广泛。
要求得方差,可用下面这个公式,其中X2是随机变量的平方,也就是需要多一张表,这个表用来存储深度值的平方,而E(X2)就是深度值平方和的平均值。
以图中为例,想要得到比1小的,需要计算1左边的面积。
切比雪夫(Chebychev)公式可以近似估算结果,它估算在t右边的值,这里的小于等于可以看作约等于,t在均值的右边时会比较准确,在左边的话就会不太准确,也就是说t值要大于均值才会准确。
以上只对PCSS的第三步进行了改进,但PCSS的第一步也是在一定范围内查询,也需要花费很多的时间。下面是对第一步的改进方法。在一定范围内,我们已知该范围内所有深度值的平均值Zavg,我们需要求出能够遮挡着色点的Zocc,把这些能够遮挡着色点的深度值求和除以遮挡点的数量得到了Zocc,Zunocc是不能够遮挡着色点的平均深度值。
根据下图中白色方框内的公式,N1/N是无法遮挡着色点的比例,N2/N是可以遮挡着色点的比例。无法遮挡着色点说明其深度值大于着色点的深度值,可以用切比雪夫(Chebychev)公式直接得出N1/N,那么N2/N=1-P。再大胆假设不能够遮挡着色点的平均深度值Zunocc等于着色点深度值,因为大多数接收阴影的物体是平面。这样就可以求出Zocc。
还有就是对一定范围内的深度平均值的计算,如果也是一个个的遍历计算也会很慢,所有也需要有改进方法。这里引入一个叫SAT的数据结构。在一维场景下,下图中,要求出3+7+1的值,需要从头便利。而SAT的思路是使用一个O(n)的空间来记录从开始到当前位置的总和,比如要查询3+7+1的值,需要用1的位置上的值减去5位置上的值。
在二维场景内。需要计算下图中的蓝色矩形平均深度值,用绿色矩形减去竖着的橘黄色矩形范围和横着的橘黄色矩形范围,再加上多减的左上角的绿色矩形范围,就是蓝色矩形平均深度值。二维的SAT建立可以是每一行都是一个一维的SAT(上图),然后再对应列。这样就可以快速的得到一定范围内的深度平均值。
VSSM有一些问题,比如在第三步的时候,一般情况是用一个正态分布来记录的,但当着色点连向光源时穿过三个shadow map时,就会有三个峰值,此时用一个正态分布就会不准确。
要么会算大,要么会算小,也就是阴影要么会变得更暗,要么会变白,变暗是可以接受的,变白是无法接受的。以下图汽车阴影举例来说,可以看到汽车阴影中有白色出现,这是因为在着色点连向光源时,它可能会被汽车的上面的盖子遮挡住,也会被汽车的底板遮挡住,这是用一个正态分布来计算就会出现问题。
VSSM在描述深度分布不够准确,Moment Shadow Mapping可以解决这个问题,它用更高阶的矩来记录深度值,VSSM就是记录到2阶矩。
Distance field soft shadows:也是一种做软阴影的方法。
Distance functions:空间中任何一个点到物体表面的最小距离。
SDF(Sign Distance functions):一种有方向的Distance functions,正号可以表示为在物体的外部,负号可以表示为在物体的内部。
对AB边界进行插值,可得到一个中间的边界值。以下图为例,求出中间位置的边界,在A中这个位置假设为5,B中这个位置就是-5,所有插值后这个位置就是0。
SDF的第一个应用:求光线与物体的求交,根据SDF的范围,光线可以安全的向前进,直到光线与物体足够接近,或者离物体足够远。
SDF的第二个应用:三维场景下,在SDF的安全范围内,相当于在一个球内,从着色点向某个SDF重心连线,以SDF为半径的范围内光线都不会和物体相交,以下图为例,就是一个角度,在这个安全的角度内,着色点不会被遮挡,如果角度再大些,就会被遮挡,也就会产生阴影,且在那个角度范围之外都会被遮挡,也就是软阴影。
需要计算安全角度,最小的安全角度也是安全范围。
求安全角度是arcsin,也就是arcsin(SDP/|p-o|),SDP/|p-o|可以近似为安全角度。但计算arcsin很麻烦,也是有估计值,其中k代表了阴影了的软硬程度,如果K非常大,安全角度就会非常小,比如k=10000,那么安全角度就是从0到1/10000,此时就是硬阴影了。k小的话,安全角度就会大,就是软阴影了。