阴影
阴影的数学推导
这是实时渲染中常用的约等式

这个约等式如果满足以下两个条件中的至少一个,则成立
- small support: 积分域比较小
- smooth integrand: \(g(x)\)比较平缓,没有大的波动起伏
在实时渲染中,我们会给the rendering equation加上一个\(V\)项,代表可见程度

通过用上述的约等式,改写成

其中提出来的部分就代表我们要求解的阴影,其余的就是常规的shading
根据我们上述提出的,这种形式的the rendering equation需要至少满足其中一个条件
- small support:点光源、平行光
- smooth integrand: diffuse材质会让BRDF均匀;单个面光源会让radiance比较均匀
硬阴影
算法
这是最原始的,在光栅化中生成阴影的算法,步骤为
- 将相机放在光源处,根据场景在每个pixel中记录一个最小深度,得到一张深度图,叫做shadow map

- 将相机放回观察处,对场景渲染,在每一个pixel记录的场景位置,和光源做一个连线,计算深度h,再找到深度图中该连线对应像素的深度h',如果 h 不等于 h',则产生阴影

存在问题
Self-Shadow Aliasing

因为我们在shadow map中,每一个pixel都记录了一个深度,但场景中的点的数量是远远大于pixel的数量的,shadow map只是离散地采样了场景
我们往往用每个pixel中心的点来采样,代表这一块区域的深度,但一块区域内的深度往往是会有变化的
光源和地面法线夹角越大,区域内深度变化就越大,导致有可能在同一块区域,shadow map记录的深度和第二次渲染找到的深度有一定差距,而错误地得到了阴影

我们通过给深度加上一个bias,来解决这个问题,也就是只要深度差不超过bias,就不会生成阴影
slope scale bias是一个动态的bias,光源和地面法线夹角越大,bias就越大,更符合实际情况
Detached Shadow
在加上bias之后,在一些位置阴影会发生缺失

这是因为影子和遮挡物的距离比较近,这个距离有可能会bias抹去了,导致不生成阴影
PCSS
PCF
Percentage Closer Filtering是用来抗锯齿的算法,但同时也是生成软阴影的方法

核心在于,在第二次渲染时,原本是对每个fragment,查询shadow map中对应pixel的深度进行比较
现在是对每个fragment,查询shadow map中对应pixel所处的一片范围里每个pixel的深度,将fragment与该范围里每个pixel的深度一一比较,每个结果记录在一个矩阵中对应的位置
然后对该矩阵做一个卷积得到一个阴影值,代表该fragment的可见程度

算法
生活中,阴影的软硬程度是随着影子与遮挡物距离而变化的,距离越近影子越硬朗

PCSS的思路就是在距离比较小的地方,用比较小的卷积核做PCF,得到比较硬的阴影,否则用比较大的卷积核,让影子变软
这是我们建立的抽象模型,将距离与半影长度建立了联系


PCSS的算法步骤如下

其中blocker depth我们需要的是一个范围的平均blocker depth
这个范围我们通常通过如下方法来找到
将shading point和光源做连线得到一个锥体,锥体与shadow map相交的部分就是要求的范围

PCSS的数学形式,\(w\)代表加权的权值, \(\chi^+\)使得深度比较值变为0或者1


VSSM
算法
在PCSS中,第二次渲染时,我们用shadow map中的一块区域来和shading point比较,然后做卷积
在VSSM中转化为,找到该shading point的深度\(t\),和shadow map该区域中深度分布\(P\),求\(P(x>t)\)
我们将切比雪夫不等式看作一个约等式,来求\(P(x>t)\)

使用切比雪夫不等式时,其中\(\mu\)在记录shadow map时就记录下来
\(\sigma\)我们通过这个方程来计算

所以shadow map中还要记录深度的平方\(x^2\),用来计算方差
VSSM也能将找平均blocker depth的步骤加速

我们把阴影接收部分看作一个平面,这样我们将\(z_{unocc}\)看作一个常数,也就是shading point的深度\(t\)
这样就可以计算出\(z_{occ}\)
SAT
Summed Area Table是用于范围求和的算法
我们可以用于快速查询shadow map中区域的\(\mu\)
SAT中每个点记录的是从左上角到该点覆盖的矩形区域的和
可用于快速查询任意矩形的和

存在问题
切比雪夫不等式的约等形式只在\(t>\mu\)时比较准确,如果超出这个范围可能会出现问题,比如light leaking
概率可以用Moment Shadow Mapping等算法估量得更加准确

我们把\(z_{unocc}\)看作常数在一些情况也会出现问题

Distance Field Soft Shadow
算法
Distance Field Soft Shadow可以高效计算出软阴影
SDF(Signed Distance Field) 的意义是,记录了三维场景中每个点,到离该点最近的物体的距离
渲染一个点的阴影时,算法先是用了ray marching的思想
从shading point向光源做ray marching,每次走SDF的长度,直到SDF收敛到一定程度(与物体发生接触)
Distance Field Soft Shadow的思路在于
在每次marching抵达的点,计算遮挡物与shading point连线和光源与shading point连线的夹角
找到所有计算得到的角度中最小的夹角,这个夹角越小,代表遮挡程度越大,阴影越深


这个夹角本应该用arcsin来解,但我们用如下右侧的方程来拟合,k是人为给定的系数
把阴影控制在[0,1],如果k越大,阴影效果越容易达到饱和,影子就越硬,否则就得到较软的阴影


存在问题
SDF需要预计算,一个三维空间的SDF需要大量存储空间
这种算法也会造成瑕疵,叫做banding effect
在ray marching时,因为是离散地采样光线上的角度,会出现无法找到光线上最小角度的情况,就会出现light leaking
特别是在遮挡物是一个角(sharp corner)的时候,就容易发生这种情况
一个算法是,在ray marching每相邻两个采样点之间再加多一个采样点
如图,红点和绿点是原采样点,黄点是容易导致light leaking的地方,所以再加多一个采样点

如下是改进的效果


浙公网安备 33010602011771号