Games202笔记——Real-time Shadows

这节课主要是关于光栅化软阴影的算法光追扎布多德勒

关于shadow mapping的回顾

shadow mapping的步骤

1.生成shadow map

从光源方向看向场景,测量场景最浅的的深度,记录成为shadow map(SM)

2.检测阴影

从相机方向,结合SM判断场景是否在阴影里

shadow mapping的问题

self occlusion

因为shadow map 的精度,每个像素记录的深度为常数,使得深度被离散化产生的问题

解决方法:

1.加入一个bias,可以根据情况调整(工业界常用)

2.second-depth shadow mapping

​ 不但储存最小深度,还储存次小深度,对两个深度取中点作为深度储存。

听起来很美好但限制太多了又慢根本没人用

​ 此外,这个方法要进行两次深度查询,虽然渐近时间复杂度都是O(n)但是实时渲染不相信复杂度

走样

同样是因为shadow map的精度问题,投射的阴影有锯齿

实时渲染中的近似相等

上式在积分域小,g(x)足够光滑时足够准确别问我为什么我不知道我恨数学

依照上式,渲染方程

可被近似为

此式子将会在环境光遮蔽时被使用

PCSS(Percentage Closer Soft Shadows)

传统的shadow mapping方法只能得到硬阴影,但在现实世界中更加常见的是软阴影,PCSS就是一种获得软阴影的方法

PCF(Percentage Closer Filtering)

最开始开发出来是为了做阴影的反走样(抗锯齿),但PCSS用这种方法做反走样

PCF的作用原理

首先,PCF不是对SM求平均,模糊SM,也不是直接对生成完毕后的阴影结果做模糊

对于一个shading point p,在SM上查找其深度时,不止查找p点本身在SM上对应的深度,还查找p点及其周围像素对应的深度值,并与p点对应的值做比较,周围的像素在上述比较过后可以产生两种结果,要么挡得住p点(深度小于p点),要么挡不住p点(深度大于p点),然后对此结果做filter,以此为依据决定阴影的强度

可以看见,当我把这个filter的范围取的比较大的时候,就可以用PCF近似出软阴影的效果了

PCSS中的PCF

那么,我们应该给一个多大的filter,filter的大小必须要是固定的吗?

显然并不是的,对于不同的遮挡物到阴影的距离,要给不同大小的filter,这也很好理解,月食不一定能把太阳全部挡住,但你的手可以

更准确的说法,filter size和相对的,平均的,投射的遮挡物深度有关(relative average projected blocker depth)说人话

image-20210508172429519

从上图可以看到其实就是个简单的相似三角形关系,图来自Games202原视频

PCSS算法全过程

对于面光源无法生成SM的问题:将面光源看作点光源(例如放在面光源中心的点光源)去生成SM

对于一个shading point p:

1.记录p点周围所有可以遮挡住p点的像素(Blocker)的平均深度$d_{Blocker}$

2.根据$d_{Blocker}$求得$w_{penumbra}$

3.PCF

在PCSS中,我们可以用如下式子表示PCF算法

其中$\chi^+()$为符号函数,其中变量大于0函数值为1,反之为0,w为权值

关于取得$d_{Blocker}$时所查询的范围大小,第一可以用一个常数大小(比如5x5)

除此之外还有一个更好的方法,见图

image-20210508174819794

这样这个套娃问题就解决啦

PCSS的问题

开销非常,非常,非常,恐怖

想象一下,对于一个点p,假如PCF的filter范围是5x5,第一步找$d_{Blocker}$的范围也是5x5,一来一去五十次采样,50倍开销,这么压榨电脑,这要是个ai,你就 等着智械危机吧。

不难看出,多次采样就是变慢的元凶,而采样主要发生在第一步和第三步,那么有没有方法减少采样次数,加速PCSS呢?

1.稀疏采样

​ 工业界有在用,但是会导致噪声,目前有先稀疏采样再降噪的做法

2.全新的软阴影生成方法:VSSM

VSSM(Variance Soft Shadow Mapping)

VSSM解决PCF

此方法针对性的解决PCSS第一步和第三步慢的问题

我们在PCF这一步想要知道周围像素是否遮挡的加权平均,不难看出,如果在不加权的情况下,这个问题其实等价于求周围像素遮挡的个数除以总个数,那不就是周围像素遮挡的概率嘛!

换句话说,我们只要能够估计周围像素遮挡着色点的概率,我们就可以在不知道周围像素具体情况(不采样)的情况下实现PCF算法。

我们直接暴力的认为周围采样点的深度的分布是符合正态分布的,那么我们如何估算出这么一个正态分布呢?熟悉个屁概率论的良好大学生很快就能反应过来了:我们需要掌握周围采样点的信息只有两个:均值和方差。

首先是平均值,给你一张图,我问你要一个范围内的平均值,在图形学课程中我们能想到什么?

这玩意不就是MIPMAP嘛

除了MIPMAP,我们还有一种更精准的方法叫做SAT(Summed Area Tables),实现原理是简单的前缀和,SAT的介绍写在后面了

我们可以知道的就是我们很轻松的就可以知道它的平均值,现在平均值有了,那么方差呢?

接下来请出我们的一个刻在DNA里的经典公式概率论双杀

直接拿下

这样我们只需要在缓存SM的同时再缓存一张记录了深度平方的SM就搞定了

现在我们已经可以估计出一个正态分布了,这时候其实我们想要知道的是这个正态分布曲线下面围成的面积,也就是那个熟悉的$P(X> x)$

学过概率论的你估计有反应过来了:这不是那个著名的不等式吗?

没错,隆重请出切比雪夫(chebychev)不等式

到现在就可以摊牌了,正态分布只是方便理解,真正要用到的就是上面这个切比雪夫不等式

虽然这里不是等于,是小于等于,但是实时渲染充满了近似,我们可以近似的认为有

尽管切比雪夫不等式其实有很多的限制都没有考虑,但是这很好用,也很快,误差也尚可接受,所以实时渲染里我们可以用这种方法

以上我们解决了第三步PCF的多次采样问题,那么第一步Blocker search呢?

一次采样的点之中有且仅有两种情况:这个点可以算作Blocker,以及这个点不能算作Blocker

我们记总采样个数$N$,Blocker的平均深度为$z_{occ}$,个数为$N_1$,非Blocker的深度为$z_{unocc}$,个数为$N_2$,平均深度为$z_{avg}$

则很容易看出来对于任意情况总有

我们不难看出$\cfrac{N_2}{N}=P(x>t)$,又可以愉快的切比雪夫了

现在我们知道了$\cfrac{N_2}{N}$,$\cfrac{N_1}{N}=1-\cfrac{N_2}{N}$以及直接从MIPMAP或SAT获得的$z_{avg}$,想要解出$z_{occ}$,但我们还有一个变量不知道:$z_{unocc}$

这里就又是大胆假设出场的时机了:我们直接假设$z_{unocc}=t$,没想到吧

其实是因为绝大部分阴影接收者是个平面,所以这么假设问题不大(你妹啊斜的平面咋办啊?)

总之现在我们也就把这个问题解决了,撒花

SAT(Summed Area Table)

这里插播一个之间就提到的,比MIPMAP精确且可以适应长方形查询平均值的技术:SAT

前面已经说到了SAT是一个基于前缀和的算法,这里放张图大家感受一下什么是前缀和

image-20210508210011660

可以看到SAT的第n项实际上就是把原输入前面的n项加起来,当我们要求m到n项之间的和的时候,只需要用SAT的第n项减去第m-1项就好了,这种预处理的方法快速便捷无误差。

拓展到二维也是一样,我们只需要在预处理生成SAT的时候把1D时的加左方一项改成加上方一项和左方一项,求[a,b]到[x,y]之间的和的时候只需要做如下的操作即可,具体看图

image-20210508210856542

VSSM结尾

虽然VSSM很牛逼,但是业界还就那个逐渐没人用

主要是因为各种降噪手段都出来了,空间域和时间域双管齐下,导致稀疏采样的PCSS逐渐的好起来了,这么多近似的VSSM用的人就少了

但是这个算法是真的牛逼啊,这就是我学概率论的意义吗(

话是这么说但根本没好好学概率论

Moment Shadow Mapping

由于VSSM做出了太多的近似,容易被出题人出数据卡掉在某些环境下不准确

举个例子,如果在切比雪夫估计遮挡率的环节你估计遮挡率低了,阴影就会偏白并发生漏光现象,偏黑也就算了,偏白是绝对不能忍受的

另外当接收物不是平面的时候也会出现问题,参见Blocker search的近似

MSM主要是为了解决VSSM估计分布不准的问题

如果我告诉你Moment在这里是“矩”的意思,你是不是就能猜出点什么了?没错,MSM正式利用了高阶矩来估计分布

不知道矩的自己回去复习概率论虽然我也就知道这么个名词

十分复杂所以闫大神没讲具体实现

我也不想听

现在也没人用

结尾

头一次上课做笔记

这是闫令琪大神在GAMES上发表的课程GAMES202-高质量实时渲染的个人笔记,有想要学习的和图一乐的可以参考一下

本次笔记覆盖到了第三讲和第四讲,real-time shadows部分

做笔记真的累死了但是为了充实blog我忍了

欢迎关注我的其它发布渠道