在 Unity 的阴影渲染中,这几个概念紧密相关,理解它们能帮你更好地调试阴影效果。
1.ApplyShadowBias返回什么?
ApplyShadowBias是 Unity 内部用于渲染阴影贴图(Shadow Map)时的一个函数,你通常不会直接调用它。它的作用是返回一个经过深度偏移(Bias)调整后的裁剪空间坐标。
具体来说,它接收一个从光源视角生成的裁剪空间位置clipPos,然后:
根据当前的渲染设置(如光源类型、阴影强度等)计算一个深度偏移量。
将这个偏移量应用到
clipPos.z(即深度值)上。返回调整后的坐标,用于后续写入 Shadow Map。
核心目的:通过人为改变写入 Shadow Map 的深度值,来减少“阴影痤疮(Shadow Acne)”这种渲染错误。
2. 什么是 Shadow Map 采样?
这是阴影渲染的核心步骤,可以理解为“从光源的视角拍一张深度照片,然后从相机视角使用这张照片”。
生成 Shadow Map(拍照):把光源当作一个相机,渲染整个场景,但只记录每个像素距离光源的深度值(不是颜色),形成一张纹理,这就是 Shadow Map。
采样与比较(查照片):在最终渲染场景时,对于一个屏幕上的像素点:
计算出该点在光源空间中的位置和深度(距离光源的距离)。
到 Shadow Map 中,采样出光源视角下那个位置记录的深度。
进行比较:
如果“点的实际深度” > “Shadow Map 中记录的深度”(加上容差),说明该点被挡住了,就在阴影中。
否则,不在阴影中。
一句话总结:Shadow Map 采样就是查询“从光源看过来,这个点是否被其他物体挡住”的过程。
3. 什么是阴影 Acne 和 Peter-Panning?
这两个都是阴影渲染中的经典问题,由 Shadow Map 的深度偏移(Bias)设置不当引起。
| 问题 | 阴影 Acne(也叫阴影痤疮、条纹、摩尔纹) | Peter-Panning(也叫悬空阴影、悬浮阴影) |
|---|---|---|
| 现象 | 物体表面出现奇怪的、自阴影的条纹、波纹或斑点,尤其在光滑平面上很明显。 | 物体投射的阴影和物体本身之间出现明显空隙,看起来像物体悬浮着,影子在地面上。 |
| 示意图 | 表面有黑白相间的锯齿状条纹 | 物体的脚离地面的影子有一段距离 |
| 产生原因 | Bias 太小。由于 Shadow Map 分辨率有限和浮点精度误差,物体表面在计算自身阴影时,采样到的深度值有时比自己的实际深度大,有时小,导致表面一部分认为被自己遮挡,一部分认为没被遮挡。 | Bias 太大。人为添加的深度偏移量过大,导致物体应该被阴影覆盖的区域被错误地判定为在“更前方”,于是阴影向后“缩”,产生了空隙。 |
| 解决办法 | 适当增加光源设置中的Bias值。 | 适当减少光源设置中的Bias值。 |
核心矛盾:你需要找到一个恰到好处的 Bias 值,在 Acne(Bias 太小)和 Peter-Panning(Bias 太大)之间取得平衡。
实际调试建议
在 Unity 的 Light 组件中,你可以直接调整这两个参数:
Bias:主要控制深度偏移,直接影响 Acne 和 Peter-Panning。从0开始微调,直到表面条纹消失,且阴影没有明显分离。
Normal Bias:沿着法线方向偏移,对消除曲面 Acne 特别有效,通常比单纯增大 Bias 效果更好,且不容易引起 Peter-Panning。
常用技巧:对于角色或小物体,使用较小的 Bias;对于地面或大平面,可以稍微增大。也可以使用Shadowmask或屏幕空间阴影等更高级的技术来从根本上缓解这些问题。