Unity Shader 系列(十):URP AO 技术全景 — SSAO、烘焙 AO 与洞穴材质实战
什么是 AO,为什么游戏中不可缺少?
环境光遮蔽(Ambient Occlusion,AO)模拟的是一种物理现象:在凹陷、缝隙、角落等处,来自四面八方的间接环境光被周围几何体遮挡,导致这些区域比开放区域更暗。
游戏中的 AO 有三种主要来源:
- 实时 SSAO(Screen Space Ambient Occlusion):每帧实时计算,响应动态场景变化
- 烘焙 AO(Baked AO in Lightmap):预计算到 Lightmap 贴图中,移动端友好
- 贴图 AO(AO Map):美术手动制作,存储在材质贴图的特定通道
实际游戏应用:
- 《黑神话:悟空》等 AAA 游戏:SSAO + GTAO 叠加,洞穴内部、岩石缝隙有强烈 AO 暗化
- 开放世界室外场景:烘焙 AO 处理静态植被根部、建筑墙角的接触阴影
- 室内场景(密室逃脱、恐怖游戏):高强度 SSAO 增强角落的阴暗感
URP SSAO Renderer Feature
URP 内置了 SSAO,通过 Renderer Feature 方式添加:
添加步骤:
- 选择 URP Asset 引用的 Renderer(通常是
UniversalRenderer) - Inspector →
Add Renderer Feature→Screen Space Ambient Occlusion - 配置参数:
1 | |
URP SSAO 的渲染时机:
SSAO 在 AfterRenderingOpaques 之后计算,结果存储在 _ScreenSpaceOcclusionTexture,在后续的 ForwardLit Pass 中自动采样。
在 Shader 中读取 SSAO
1 | |
烘焙 AO:Lightmap UV 与正确工作流
烘焙 AO 存储在 Lightmap 中,依赖 Unity 的光照烘焙系统(Bake Mode = Baked 或 Mixed)。
Lightmap UV 设置:
1 | |
在 Shader 中读取烘焙 GI(包含烘焙 AO):
1 | |
贴图 AO 的使用:
1 | |
实时 AO vs 烘焙 AO:选择策略
| 场景类型 | 推荐方案 | 原因 |
|---|---|---|
| 移动端(低端硬件) | 仅贴图 AO | 无性能开销 |
| 移动端(中端+) | 烘焙 AO | 无实时开销,质量好 |
| PC/主机静态场景 | 烘焙 AO + SSAO | 静态精度高,动态物体有 SSAO |
| PC/主机动态场景 | SSAO + 贴图 AO | 动态物体需要实时 AO |
| 室内密闭场景 | 烘焙 AO(高采样) | 离线烘焙质量远超实时 SSAO |
| 开放世界 | SSAO(低质量)+ 烘焙 AO | 视野范围大,SSAO 高质量开销过大 |
完整示例:URP 洞穴/室内场景材质 Shader
SSAO + 烘焙 AO 双层叠加,适合表现洞穴、地牢等阴暗密闭场景:
1 | |
Bent Normal AO 与 GTAO 简介
Bent Normal AO:
普通 AO 只是一个标量(0~1),告诉我们遮蔽程度。Bent Normal 是一个方向向量,表示”法线半球中最少被遮蔽的平均方向”。用 Bent Normal 代替 Surface Normal 采样环境光贴图(IBL),可以获得更准确的间接光照遮蔽效果。
Unity Enlighten(旧版烘焙)可以烘焙 Bent Normal;HDRP 支持 Bent Normal AO,URP 目前不原生支持,需要自定义实现。
GTAO(Ground Truth Ambient Occlusion):
URP 2022 LTS 开始提供 GTAO 作为 SSAO 的替代方案(通过 Screen Space Ambient Occlusion Renderer Feature 的 Method 选项)。GTAO 相比传统 SSAO:
- 更少的 halo 伪影(SSAO 在薄物体边缘常见的光晕)
- 更精确的能量守恒
- 对移动端更友好(虽然采样数相同,但噪声更少)
ShaderGraph 中的 AO
ShaderGraph 中访问 AO 的节点:
Ambient Occlusion节点:自动读取 SSAO(如果启用)或返回 1Sample Texture 2D→ 接 Occlusion Map →Lerp(1, ao, strength)→ 贴图 AO- 将上述结果乘以
Ambient输出或接入Occlusion端口(在PBR Master节点)
移动端 AO 最佳实践
推荐方案(按性能排序):
- 仅贴图 AO(最快):将美术制作的 AO 贴图存入材质的 G 通道,直接乘以间接光
- 烘焙 AO(Lightmap):预计算阶段消耗,运行时只是一次纹理采样
- SSAO 低质量(4 次采样,半分辨率):约 0.5-1ms,可在中端移动端使用
- SSAO 中等质量(8 次采样,全分辨率):约 1.5-2ms,仅 PC/主机推荐
移动端完全禁用 SSAO 时:
确保 Shader 中的 #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION 声明正确,URP 会在 SSAO Feature 不存在时不定义 _SCREEN_SPACE_OCCLUSION,Shader 中的 SSAO 采样代码自动跳过(零开销)。
常见踩坑
SSAO 在 HDR 场景下过暗:SSAO 在线性空间计算,当场景有强烈 HDR 光照时,AO 叠加可能导致环境光区域过黑。调低
Intensity并配合Falloff Distance限制 SSAO 影响范围。烘焙 AO 在动态物体上无效:Lightmap AO 只对静态物体有效(需要勾选
Static标志)。动态角色/物件需要用 SSAO 或贴图 AO。DepthNormals Pass 缺失导致 SSAO 质量下降:URP SSAO 的
Source设置为Depth Normals时,需要DepthNormalsPass。如果自定义 Shader 没有DepthNormalsPass,该物体的 SSAO 法线数据缺失,会产生 halo 伪影。UsePass "Universal Render Pipeline/Lit/DepthNormals"是最简单的解决方案。Lightmap UV 缝隙处出现 AO 泄漏:Lightmap UV 的相邻 UV 岛之间需要足够的间距(建议 ≥ 2 Lightmap 像素),否则烘焙时光照/遮蔽信息会从一个 UV 岛泄漏到另一个。在 Unity Lightmap Settings 中增加
Lightmap Padding。SampleAmbientOcclusion在编辑器 Scene View 中始终返回 1:SSAO 在 Scene View 中默认不激活(只在 Game View 中工作)。如果想在 Scene View 中也看到 SSAO,在 Scene View 的 Camera 组件上确认启用了后处理(Post Processing勾选)。
系列总结
经过这十篇文章,我们已经建立了完整的 Unity URP Shader 知识体系:
- 2D SDF UI Shader → 圆角矩形、血条、技能 CD 遮罩
- 程序化噪声 → FBM 火焰特效、域扭曲、程序化材质
- 矩阵变换体系 → 坐标空间链、顶点动画草地
- 纹理采样 → TEXTURE2D/SAMPLER、水面双层法线
- 颜色管理 → Linear/Gamma 工作流、后处理赛博朋克效果
- 3D SDF 应用 → URP 体积雾、软粒子深度融合
- 法线体系 → TBN 矩阵、UnpackNormal、陡峭视差贴图
- URP 光照系统 → BRDFData、卡通渲染、各向异性布料
- URP 阴影 → CSM、PCF 软阴影、植被顶点动画 + 正确阴影
- URP AO → SSAO Renderer Feature、烘焙 AO、洞穴双层 AO 材质
这十个技术模块覆盖了 Unity 游戏开发中 Shader 编程的核心领域。从 UI 特效到 3D 材质,从程序化特效到物理正确的 PBR 光照,每个模块都包含可直接运行于 Unity 项目的完整 Shader 代码。接下来可以深入研究 URP 的更多进阶特性:自定义渲染流程(Scriptable Render Pass)、GPU Skinning、计算着色器(Compute Shader)等。