阴影贴图:原理、算法与优化
什么是阴影贴图
阴影贴图(Shadow Mapping)是一种实时阴影生成技术,广泛应用于游戏和实时渲染。其基本思想是从光源视角渲染场景的深度信息到一张纹理(阴影贴图),然后在主渲染中,将每个像素转换到光源空间,比较其深度与阴影贴图中的深度,如果像素深度大于阴影贴图深度,则该像素处于阴影中。
阴影贴图的原理
阴影贴图通常分为两个 Pass:
- **阴影 Pass**:从光源位置渲染场景,只写入深度,得到阴影贴图。对于方向光,使用正交投影;对于点光源,使用透视投影或立方体贴图(六面)。
- **主渲染 Pass**:正常渲染场景,在片段着色器中,将世界坐标转换到光源空间,采样阴影贴图,比较深度。如果当前片元深度大于阴影贴图中对应深度(加上偏移),则片元在阴影中,光照减弱。
- **级联阴影贴图(Cascaded Shadow Maps, CSM)**:将视锥体划分为多个区域,每个区域使用不同分辨率的阴影贴图,提高近处阴影质量。
- **紧配合光源视锥**:调整光源投影范围以紧密包围场景,提高阴影贴图利用率。
- **使用低分辨率阴影贴图**:对于远处或小物体,可以降低阴影贴图分辨率。
- **阴影距离限制**:超出一定距离不渲染阴影。
- **缓存静态阴影**:烘焙静态物体的阴影到光照贴图。
- **Unity**:使用 Shadow Map 技术,支持 CSM、软阴影、阴影距离等设置。
- **Unreal**:使用 Shadow Map 和 Ray Traced Shadows,支持多种优化。
常见问题
阴影痤疮(Shadow Acne)
由于深度缓冲精度有限,表面被自身误判断为阴影,产生条纹或斑点。解决方法:使用深度偏移(Depth Bias)和法线偏移(Normal Offset),在比较深度时添加一个小偏移。
彼得潘现象(Peter Panning)
偏移过大导致阴影与物体分离,阴影漂浮。需要调整偏移量。
阴影锯齿(Aliasing)
阴影贴图分辨率有限,边缘出现锯齿。解决方法:使用百分比渐近滤波(PCF)进行软阴影,或提高阴影贴图分辨率。
阴影贴图精度
阴影贴图使用深度纹理,精度有限,远处可能产生 Z-fighting。可以使用级联阴影贴图(CSM)提高方向光在大场景中的精度。
优化方法
在引擎中的应用
常见问题
阴影贴图和光线追踪阴影有什么区别?
阴影贴图是基于深度比较的近似方法,存在精度问题;光线追踪阴影通过投射光线精确计算,效果更好但性能开销大。
为什么阴影贴图需要深度偏移?
因为深度缓冲精度有限,深度偏移可以避免表面自阴影(阴影痤疮)。
点光源如何生成阴影贴图?
点光源通常使用立方体阴影贴图,从六个方向渲染深度,或使用单通道双抛物面映射。
移动端如何优化阴影?
移动端可以使用低分辨率阴影贴图、限制阴影距离、使用简单的硬阴影或关闭阴影。
CSM 是什么?
级联阴影贴图,将视锥体分为多个区域,每个区域使用不同分辨率阴影贴图,平衡近处和远处的阴影质量。
常见问题
阴影贴图和光线追踪阴影有什么区别?
阴影贴图是基于深度比较的近似方法,存在精度问题;光线追踪阴影精确但性能开销大。
为什么阴影贴图需要深度偏移?
深度偏移可以避免表面自阴影(阴影痤疮),因为深度缓冲精度有限。
点光源如何生成阴影贴图?
点光源通常使用立方体阴影贴图,从六个方向渲染深度,或使用单通道双抛物面映射。
移动端如何优化阴影?
可以使用低分辨率阴影贴图、限制阴影距离、使用简单的硬阴影或关闭阴影。
CSM 是什么?
级联阴影贴图,将视锥体分为多个区域,每个区域使用不同分辨率阴影贴图,平衡阴影质量。