Real-Time Shadows

Real-Time Shadows

Shadow Mapping

Shadow Mapping的算法

  • 使用两趟Pass
    • 第一趟Pass从光源所在的地方看向场景,并输出一个阴影贴图,来记录场景中最近的深度。
    • 第二趟Pass使用第一趟渲染出的阴影贴图通过比较当前像素的深度与记录的深度来判断看到的物体是否在阴影内。

Shadow Mapping的问题

Self Occlusion(自遮挡)

由于阴影贴图记录的是离散的像素,而一片像素记录的深度又是相同的,因此当摄像机看到一个点时,该点的实际深度阴影贴图中记录的深度就会有很小的偏差。如下图中的点p,其实际深度为\(d(p_1)\),但从阴影贴图中采样的深度为s,两者s小于\(d(p_1)\),因此会被判定为阴影,但实际上p点并没有被遮挡,这就会形成自遮挡。自遮挡的剧烈程度和光照与平面的角度有关,也就是光照方向与该点的法线方向形成的夹角越小,对应的余弦值越小,自遮挡越严重。

自遮挡的解决方法

引入偏移

在第二趟Pass判断深度时加上一个bias(偏移),来增加容忍度,同时由于自遮挡的剧烈程度与角度有关,因此可以通过夹角的余弦值来实时控制偏移的值,在角度大时偏移小,角度小时便宜大。 但该方法会造成detached shadow(不接触的阴影),也就是当偏移取得过大时,会使一些本该出现阴影的地方没有阴影。

Second-depth Shadow Mapping

进行第一趟Pass时不仅存储最小深度,还存储第二小的深度,在比较时使用两个深度的中间深度与实际深度进行比较。这样虽然不会发生自遮挡现象,但该方法要求物体必须为watertight,也就是必须有两面,地板这种没有反面的物体次浅深度可以为无限大,同时加入一个次小深度会时间消耗变大。

Shadow Mapping背后的知识

积分的约等式:

近似的使用条件:

  1. 当积分域很小时,近似比较准确。
  2. \(g(x)\)在积分域中变化不大,近似比较准确。

约等式的使用:

可以使用该约等式将可见性从积分中拆出来,从而先进行Shading,在进行乘上可见性。

当光源为点光源或是方向光时近似较准确。

当光源的radiance不变,BRDF为diffuse时较准确。

Percentage Closer Filtering(PCF)

  • PCF不是对已经有锯齿的阴影进行过滤。

  • 不是对Shadow Map进行过滤。

PCF的解决办法:

  1. 将ShadingPoint连向光源后,不只选取对应的一个像素,而是选取ShadowMap上对应像素特定范围内的所有像素
  2. 对所选的所有像素进行比较,得到0或1表示visibility。
  3. 对所有的visibility进行平均。

Percentage Closer Soft Shadow(PCSS)

PCSS的核心是PCF,本质上是通过特定的手段选取适应性的FilterSize,再根据得到的FilterSize对阴影进行过滤。

当光源的面积越大时,或当遮挡物距离阴影越远时,阴影越平滑,由此可以使用下列式子表示选取FilterSize的大小:

blocker depth:
所有有可能挡住ShadingPoint的物体到光源的平均距离。

PCSS的算法

  1. (Blocker Search)获取特定范围内所有遮挡物并计算所有blocker depth的平均值。
  2. 使用平均blocker depth去计算FilterSize。
  3. 使用PCF计算阴影。

在进行PCSS前,我们还需要先选取特定的范围来获取平均blocker depth。可将ShadingPoint连向Light,形成一个视锥体,而ShadowMap和Light分别在近平面和远平面,看ShadowMap对应了多大的区域。

PCSS的缺点及优化

缺点:第一步和第二步使用了过大的FilterSize,需要进行大量的采样操作。

优化:可进行稀疏采样,使用泊松圆盘、均匀圆盘等圆盘滤波核对滤波区域进行随机采样,减少采样次数。但由此最后计算出的visibility也会带有噪声,可进行图像空间的降噪来提高画质。

Variance Soft Shadow Mapping

优化PCF

在PCSS的第三步PCF中,我们选取了一个区域对采样结果进行滤波,而滤波中要做的一步便是比较当前像素与滤波核中像素的深度,从而找到比自身浅的像素的百分比,因此我们本质上希望得到的是当前像素在滤波核中深度大于ShadingPoint的像素的百分比。若对精准度要求不是过高,可将像素的深度分布当成正态分布,那么只需要知道均值与方差,就可以得到一定范围内当前像素所处的百分比。

Mean(平均值):

  1. MipMap: 想要获得特定范围的的平均值可使用MipMap,但其精准度不是很高,因为在不同的层级之间需要进行插值,且只能处理正方形的情况。
  2. Summed Area Tables(SAT).

Variance(方差):

其中\(E^2(x)\)可从ShdowMap中获取,而\(E(x^2)\)只需要在生成ShdowMap时顺便计算\(x^2\),并存在另一张纹理中,或存在ShdowMap中的其他通道。

切比雪夫不等式:

使用切比雪夫不等式可得到变量x大于某个常数t的概率的上界,当常数t大于均值时,该公式可用来近似x大于t的概率。

优化BlockSearch

在PCSS的第一步中,需要求一定范围内遮挡物的平均深度,也就是深度值小于当前深度的像素的平均深度。而对于遮挡物深度\(Zocc\)、非遮挡物深度\(Zunocc\)和整个氛围的平均深度\(Zavg\),可以得到这么一个关系:

而其中的\(N_1/N\),为大于当前深度的像素的比例,可使用前面提到的切比雪夫不等式来近似;\(N_2/N\)自然是\(1-N_1/N\)\(Zavg\)可通过MipMap或SAT得到。那么就只剩下两个变量\(Zocc\)\(Zunocc\)了,其中\(Zocc\)是我们希望求得的。至于\(Zunocc\),VSM使用了一个大胆的假设,即所有非遮挡物的深度都为当前像素的深度,那么\(Zunocc\)即为当前像素的深度。当然这种假设只是近似而不正确的,当接受物为曲面或与光源不平行时就会出现问题。

Average(均值)

前面已经提到可使用切比雪夫不等式来近似深度大于ShadingPoint的像素的比例,而求解不等式有需要得到均值,均值可使用MipMap来近似或是SAT来计算。

MipMap

MipMap本身是用来做快速的、近似的、方形的范围查询,在计算像素时MipMap使用了相邻像素的插值,在需要非\(2^n\)的层级时,还需要在层与层之间进行插值,由此会带来一定的误差。对于非正方形的情况同样也并不准确,这一点可使用各向异性过滤。

Summed Area Tables(SAT)

SAT是一个完全准确的方法,其涉及到了前缀和的算法。

在一维的情况下:

对于一个一维数组:

先对该数组进行预计算,创建一个新的数组,每一个元素来储存原数组前方所有蒜素的总和。对于查询中间部分元素的和,如计算3,7,1的和,可使用最后一个元素对应的前缀和减去首元素前一个元素的前缀和,即20减9。

在二维的情况下:

对于二维情况,可先对一张二维纹理进行与计算,从左上角开始,每一个像素记录的是从左上角到当前像素所形成的矩形的所有元素的和。计算时为了提高效率可先对所有行进行并行计算,从左边加到右边,再并行计算所有列,从上面加到下面。当我们需要得到图一中间蓝色部分的和时,可通过图二绿色部分的和减去图三、四的和在加上图五的和,对应的和即储存在最右下角的元素上。

VSSM的缺点

  1. 分布估计带来的问题:

    当阴影的分布不是一个单峰值的分布而是多峰值时,会出现漏光的情况。例如当使用切比雪夫不等式进行估计时,会产生红色面积的非遮挡物估计,而实际的分布式是蓝色的多峰值分布,那么实际只有蓝色部分的非遮挡物,就会造成过多的估计非遮挡物的比例,进而出现本应该在阴影中的像素不再阴影中。

  2. 接受物不是平面时出现问题。

  3. 切比雪夫不等式的估计带来的问题。

Moment Shadow Mapping

MSM解决了VSM中描述分布不准的问题,它使用了使用了四阶或者更高阶的距,而VSSM实际上使用了前两阶矩。m阶矩可以描述\(m/2\)个阶梯的函数,使用四阶矩可以很好的描述真正的CDF。而如何使用前四阶矩来得到两个台阶的函数可阅读这篇Paper。Moment Shadow Mapping (acm.org)

Distance Field Soft Shadows

Signed Distace Field(SDF):

可将有向距离场定义为空间上某个点到物体表面的最小距离,距离场可携带正负号,来表示在物体的内部或外部,如在物体外部时为正号,内部时为负号。

Distace Field的例子

在Games101中提到过,若是想混合两个边界,得到一个中间的边界,仅仅是进行线性过滤是不行的,得到的将会是一个过渡带。

若是将两个边界转换为对应的SDF,左侧为负右侧为正,将0值处定义为边界,再对两个SDF进行插值,就可将数值为0的地方移动到中间,再将SDF恢复成原图,就可得到一个移动的边界。

若将几何图形转化为对应的SDF,再对SDF进行混合,还原SDF为几何后就可得到的几何图形的混合。

Signed Distance Fields的使用

Ray Marching

若已经拥有了某个空间内的SDF,想要判断某个光线与物体的是否相交。可从SDF得到某个点与物体表面的最小距离(安全距离),沿着光线的方向前进这个最小距离,可以保证前进过程中不会与物体相交。再次获取当前点的SDF并前进获取到的最小距离,同样不会与任何物体相交。由此一直前进SDF中得到的最小距离,当获取的最小距离小于某个值时,就表示与物体足够接近,可得到光线与物体的交点。若是光线前进了很长的距离还没小于某个值,就可判断光线与物体不相交。

Distance Field Soft Shadows

使用SDF可生成高质量的阴影,对某个接受面上的点沿着点到光源的方向使用上述Ray Marching的方法,当光线与物体相交时即表示有物体遮挡,该点处于阴影中,到达光源位置还未相交即表示不处于阴影中,由此可获得物体的硬阴影。

当进行Ray Marching时,每次前进都会从SDF中获取一个点到物体表面的最小距离,由这个最小距离又可通过反三角得到射线到物体的最小角度(安全角度),对Marching中得到的所有安全角度取最小值,即可得到该点的安全角度,可根据该角度来决定该点的visibility,即阴影的软硬程度。

在计算角度的时候会使用到反三角函数在Shader中这类函数的开销是很大的,因此可以通过SDF与前进距离的比值来近似阴影的软硬程度,,其中k是为了控制阴影的软硬程度,当k的值越小时,更容易大于1,该函数在[0, 1]中的过渡带就越小,就可以表示更硬的阴影。

Signed Distance Fields的优缺点

优点:

  • 快速,当然这个快速指的时已经有SDF时,只需要进行Ray Marching并采样SDF,若是加上SDF的生成还是有较大开销
  • 高质量

缺点:

  • 需要进行预计算,运动的物体可重复使用SDF,但是物体发生形变的话就需要重新计算SDF。
  • 储存SDF需要花费大量的空间
posted @ 2025-10-13 23:53  单身喵  阅读(8)  评论(0)    收藏  举报