Games202-Lecture3 Real-Time-Shadow 1

本文最后更新于:6 个月前

Shadow Mapping

image-20211220193557002

shadow mapping为一种二次渲染技术,对场景渲染两次。从光源发出光,统计光能够打到哪些地方,生成对应的深度图,即shadow map。再从人眼发出光,若人眼发出光照射的地方无法被光源直接打到,则为shadow。

image-20211220193058405

从光源位置看到的深度图,颜色越浅说明深度越大。

image-20211220194558684

由于Shadow Map记录的深度值不连续,会产生自遮挡现象,越倾斜越严重。可以引入一个可变长度值bias校正深度,光源倾斜角度越大,bias越大,在生成shadow时不考虑后面的bias深度。具体方式就是当一个点深度大于记录深度的值超过一个阈值时,我们才认为这个点在阴影内。这也是工业界使用较多的一个办法。但同时会产生阴影不连接的现象。

image-20211220194000037

可以建立两层深度(最小和次小),取均值,最后用均值图来算物体的遮挡关系,绘制shadow。但是要求材料有厚度,不能是单一平面,并且开销很大。

image-20211220193128536

Shadow Mapping第二个问题就是会产生锯齿。由于深度图是以像素绘制的,当投影到很远的平面时,自然会产生分辨率过低的问题,产生锯齿。

积分近似化

image-20211220193619592

积分近似:将乘积的积分转化为积分的乘积。空分母为归一化常数。

等式成立条件(有一个成立即可):

  1. g(x)的support(积分域)非常小
  2. g(x)为光滑函数

image-20211220205844066

此时我们把rendering equation代入这个约等式中,近似后,分解为visibility与shading的乘积。因此其表示的意义就是,我们计算每个点的shading,然后去乘这个点的visibility得到的就是最后的渲染结果。这也就是shadow mapping的基本思想。

image-20211220200445432

那么什么时候这个约等式比较正确呢?

  1. 我们要控制积分域足够小,也就是说我们只有一个点光源或者方向光源。

  2. 我们要保证shading部分足够光滑,也就是说brdf的部分变化足够小,那么这个brdf部分是diffuse的。

  3. 我们还要保证光源各处的radience变化也不大,类似于一个面光源。

PCF与PCSS

image-20211220195209116

Shadow Mapping只能获得硬阴影。PCF最开始是做抗锯齿后来被用作求软阴影,实质上就是做了个平均,但不是对已经有锯齿的阴影和Shadow Map做平均,而是在做阴影判断时做平均。

image-20211220195814229

PCF原理:人眼看到一点,从光源看向该点的时候不单单查找该点的深度,而是以n*n像素的范围从Shadow Map上查找深度,然后做平均。结果不再是非零即一,越远所做的模糊越大。filter的大小决定了阴影的软硬。

image-20211220203117042

我们可以发现,遮挡物blocker与阴影接受物receiver距离越远,阴影越软,因此可以通过相似三角形得到filter的可变大小,blocker就是深度图里的深度值。

image-20211220201629847

PCSS过程(开销非常大):

  1. 通过深度图确定平均blocker深度
  2. 通过blocker的深度确定filter的大小
  3. 做PCF

image-20211220204858659

不能直接使用shadow map中对应单个点的深度来代表 blocker 距离,因为如果该点的深度与周围点的深度差距较大(遮挡物的表面陡峭或者对应点正好有一个孔洞),将会产生一个错误的效果,我们选择使用平均遮挡距离来代替,所以平常我们指的blocker depth其实是Average blocker depth.

blocker上的每个点距离光源的距离是不同的,深度也是不一样的。这里我们采用取平均深度的方式来表示blocker的深度。

求blocker距离的方法如下:

首先,我们把目标shading point 转换到light space 找到shading point在shadow map上对应的像素。

如果shading point的深度大于这个shadow map上点对应的深度,则说明shadow map上的点就是一个Blocker,然后我们取shadow map上这个点(像素)周围的一些像素,找出能够挡住shading point的点的像素,并求出他们的深度平均值作为blocker的深度。