01 / 阴影不是一种材质颜色
局部光照公式假设光源能直接照到表面。阴影项是一个可见性因子:光源可见时为 1,被完全遮挡时为 0,面积光源部分可见时则介于两者之间。
directLighting = visibility × BRDF × incomingLight
阴影能显著强化物体接触关系和场景尺度,但它只影响对应光源的直接光。间接光、环境光和发光材质仍可能照亮阴影区域。
02 / 阴影贴图做两次观察
- 从光源视角渲染场景,只保存每个样本最近的深度。
- 从相机视角着色时,把当前世界位置变换到光源裁剪空间。
- 用投影坐标查询阴影贴图,比较当前点深度与已存深度。
currentDepth ≤ shadowMapDepth → 光源可见
currentDepth > shadowMapDepth → 被更近表面遮挡
currentDepth > shadowMapDepth → 被更近表面遮挡
方向光使用正交投影;聚光灯适合透视投影;点光源向所有方向发光,常用立方体贴图保存六个面的深度。
阴影贴图是从光源看到的离散深度图。它不是屏幕空间效果,因此离开相机视野的遮挡物也必须包含在光源渲染范围内。
03 / 深度偏移在两类错误之间权衡
有限精度、纹理分辨率和表面倾斜会让接收面误判为遮挡自身,形成条纹状 shadow acne。比较时加入小偏移可减少自阴影。
visible = currentDepth - bias ≤ storedDepth
bias 可随表面与光线夹角增大
bias 可随表面与光线夹角增大
偏移过大又会让阴影与物体底部脱离,形成 Peter Panning。没有适用于所有场景的固定值,应结合场景尺度、法线夹角、阴影分辨率和深度范围调节。
| 现象 | 常见原因 | 调整方向 |
|---|---|---|
| 表面黑色条纹 | 偏移太小 | 增加深度或法线偏移 |
| 阴影漂浮 | 偏移太大 | 减小偏移并收紧范围 |
| 边缘块状 | 分辨率不足 | 提高有效纹素密度 |
04 / 过滤和级联改善阴影质量
PCF 软化比较结果
百分比渐近过滤在阴影贴图周围多次深度比较,再平均可见比例。它能软化锯齿,但固定采样范围并不等同于真实面积光源的半影。
级联阴影贴图
相机附近需要更高阴影细节,远处可接受较低密度。级联阴影把相机视锥按深度分段,每段使用一张方向光阴影贴图;需要处理级联选择、稳定性和过渡。
- 收紧光源投影范围,让纹素集中在真正可见区域。
- 让投影随纹素网格稳定移动,减少相机运动时的闪烁。
- 按重要性分配分辨率,不要只盲目放大整张贴图。
05 / 光线追踪直接查询光源可见性
从着色点向光源采样位置发射阴影光线。若在到达光源前命中几何,该样本被遮挡;面积光源上取多个位置,就能自然得到随距离变化的软阴影。
visibility = 未遮挡光源样本数 / 光源总样本数
光追阴影避免阴影贴图的投影分辨率和偏移问题,但需要相交加速结构、更多采样和降噪。实时项目常让主要光源使用光追阴影,其他光源继续使用阴影贴图。
选型依据:阴影贴图擅长重复利用一次光源深度渲染;光线追踪擅长复杂可见性与真实软阴影。两者都是对同一个问题的不同计算策略。