环境光遮蔽
Ambient Occlusion
环境光遮蔽 (AO) 是余弦加权后半球上未被遮挡的比例,用来在光照缺乏方向变化时仍给出形状线索(缝隙变暗)。它由 Landis 在 ILM 为《珍珠港》开发,可离线烘焙,也可在物体空间或屏幕空间动态计算(SSAO、HBAO、GTAO 等)。AO 适合漫反射和平滑环境光,不适合点光源或小面光源的可见性(RTR4 11.3 节)。
理论
假设朗伯表面、入射亮度处处恒为 ,辐照度 ,与位置和法线无关,画面平淡。加入可见性函数 (被挡为 0,否则为 1,并假设被挡方向入射为 0),即 Cook 与 Torrance 提出的形式,定义:
- 从 0(完全遮挡)到 1(无遮挡)。凸物体(球、盒子)不遮挡自身,单独存在时处处为 1,只有凹处小于 1。
- 朝向也有影响:未遮挡立体角相近时,开口集中在法线附近的点余弦权重大, 更高。
- 弯曲法线 (bent normal):未遮挡方向的余弦加权平均方向(归一化),着色时代替几何法线,几乎无额外开销却更准确。
可见性与遮蔽度 (Obscurance)
- 只考虑物体自身会漏掉附近物体的遮挡;常把物体放在一个平面上一起算,地面的遮蔽还能当接触阴影。
- 封闭房间里所有光线都会击中东西, 全为 0,此时经验方法更好(受 Miller 可达性着色启发,模拟缝隙积灰)。
- 遮蔽度 (Zhukov 等):把 换成随交点距离连续变化的 ,距离 0 时为 0,超过 或无交点为 1;超过 不必检测,计算更快。它不物理正确, 要手调,但结果可信、比无限长光线的 AO 亮。
相互反射
AO 假设被挡方向入射为 0,比完整 GI 暗。
- Stewart 与 Langer:朗伯场景在漫射光照下,从某点可见的表面亮度相近;假设被挡方向入射亮度等于当前点出射亮度,递归被打破,得到解析式,相当于把 换成
它会提亮 AO,强烈依赖反照率 ,并假设附近表面颜色相同,有点像颜色渗透。Hoffman 与 Mitchell 用它给地形算天光。
- Jimenez 等:对白色无限远环境光照下的场景离线路径追踪,用三次多项式拟合从 到提亮后 的映射。
预计算(烘焙)
- 用蒙特卡洛在半球上投射 条光线:。更高效的做法是重要性采样:直接按余弦分布发射光线(Malley 方法)。
- CPU 常用 Embree,GPU 常用 OptiX;结果存在纹理、体积或顶点里,与其他预计算光照的存储方式相同。
- 物体间 AO:Kontkanen 与 Laine 的 AO 场用立方体贴图存二次多项式倒数的系数,描述遮蔽随距离和方向的变化;Malmer 等的 AO 体积直接在三维网格存 (及可选弯曲法线),运行时读取更省计算。适用于刚体,少量活动部件可分开处理。
- 存储时要把它当连续信号:采样后插值是重建。Kavan 等的最小二乘烘焙求顶点值,使插值与采样值的总差最小。
- 案例:《命运》在跨两代主机上用预计算 AO 作为间接光照基础,因 AO 把可见性与光照解耦,动态昼夜也能复用同一数据;育碧《刺客信条》《孤岛惊魂》渲染俯视深度图,用启发式得到大尺度的世界空间 AO (World AO),按物体世界坐标投影查询。
动态计算:物体空间
- Bunnell:把表面表示为顶点处的圆盘,圆盘间遮挡可解析计算。简单相加会双重遮蔽过暗,用两遍法:第二遍按第一遍的遮蔽削弱各圆盘贡献。层次树把 降到 ;曾用于《加勒比海盗》最终渲染。Hoberock 加入距离衰减,效果近似遮蔽度。
- 有向距离场 (SDF):Evans 沿法线在若干逐渐变远的点采样 SDF,用启发式组合(非物理但好看),也可用于解析 SDF (Quílez)。Wright 改为锥追踪:沿锥轴步进,若 SDF 值小于该处球半径,这部分锥被遮挡;单锥不准且无法计入余弦,因此用一组覆盖半球的锥,并结合全局 SDF 与物体局部 SDF。Crassin 等用稀疏体素八叉树做类似的事。
- 球体近似 (Ren 等):AO 很模糊,几何可用一组球近似。单球可见性用球谐表示,多球可见性是乘积;乘法昂贵,于是对 SH 取对数求和再取指数。0 阶系数即 ,1 阶给出弯曲法线,更高阶可给环境贴图或圆形光源投影;无法表现折痕等小细节。Sloan 等在屏幕空间累加;Hill 只用二阶系数,乘积只需几次标量乘,甚至可用固定功能混合硬件,适合性能有限的主机,但只能得到大致无方向的遮蔽。
动态计算:屏幕空间
代价只与分辨率有关,与场景复杂度无关(实际还受深度/法线数据分布对缓存的影响)。
| 方法 | 做法 | 特点 |
|---|---|---|
| Crytek SSAO(《孤岛危机》) | 全屏 pass,只用 z-buffer;在像素周围球内取点做深度测试,通过比例决定 ,样本权重随距离衰减 | 没有余弦加权、表面下方样本也计入,平面会变暗、边缘偏亮,但观感好 |
| Shanmugam 与 Arikan | 细尺度:用深度和法线缓冲,把邻近像素视为球;粗尺度:在屏幕空间用公告板累加球体遮挡 | 都不处理双重遮蔽,略暗 |
| 《星际争霸 II》、可扩展环境遮蔽度 (SAO) | 经验启发式 | 性能好,参数可调 |
| 体积遮蔽度 (Loos 与 Sloan) | , 取常数,即邻域球内占用率积分;屏幕 xy 随机采样,z 方向用深度缓冲解析积分 | 一维精确积分,同等质量所需样本更少;可用法线平面截断 |
| 体积环境光遮蔽 (Szirmay-Kalos 等) | 去掉余弦项,改为在半径减半、沿法线偏移、内切于半球的球内积分 | 用球体模拟余弦分布 |
| HBAO (Bavoil 等) | 把深度缓冲视为连续高度场,按方向求地平线角;忽略余弦时 | 内层积分解析,外层按方向数值采样;含经验衰减 |
| GTAO (Jimenez 等) | 同样用地平线角 ,加入余弦项、去掉衰减,在视线坐标系中积分,归一化为 | 在高度场假设下与 AO 定义完全一致 |
- Timonen:沿屏幕空间直线扫描整个 z-buffer,同一直线上像素复用地平线样本,每个方向存一张缓冲,再据此计算遮蔽。
- 深度缓冲只存最近表面,不知道物体厚度,各方法用启发式推断;多层深度方案因集成复杂、开销高未普及。
- 高质量需要上百样本,实时只能取 10–20 个甚至更少(Jimenez 等为 60 FPS 只能每像素 1 个样本)。常用空间抖动(每像素旋转/偏移样本)+ 联合双边滤波(用深度或法线避免跨表面模糊),或固定 4×4 重复样本模式 + 限定邻域滤波。
- 时间超采样:每帧换样本模式,指数平均,用上一帧深度、相机变换和运动信息重投影,用深度/法线/速度启发式丢弃不可靠历史。成本低,偶有错误也因 AO 不直接显示、与法线贴图和直接光混合后被掩盖。
用 AO 着色
对朗伯表面,反射方程可改写为 ,其中 是覆盖法线半球、积分为 1 的方向滤波核。用归一化余弦核 近似 (忽略可见性,但 仍保留),得到:
即辐照度乘以 AO,辐照度可来自辐照度环境贴图等任何来源。光照在球面上平滑变化时可信;光照恒定(全白环境)时完全准确。
- 不适合点光源和小面光源:它们立体角极小,可见性近乎二值地决定贡献,用 AO 会让阴影缺乏方向和清晰度,应使用阴影贴图。例外:用小的局部光模拟间接光时,用 AO 调制是合理的。
- 镜面 BRDF 的 依赖视线方向,单一固定形状太粗糙,因此 AO 主要适用于漫反射。
- 弯曲法线让核的最大值对准平均未遮挡方向,更接近 ;Landis 甚至用它代替部分直接光的阴影。Pharr 用纹理过滤硬件动态滤波环境贴图:核中心为弯曲法线,大小由 决定。
GEA 的视角:AO 与 SSAO(卷 II 12.4.1.1、12.5.7、12.7.2)
- GEA 把 AO 定位为模拟接触阴影的技术:只有环境光照明时产生的软阴影,描述表面每一点对光的"可达程度"。例子:管子内部比外部更难被环境光照到,阴天放在室外时内壁更暗(卷 II 12.5.7)。
- 测量方法:以表面点为中心构造一个半径很大的半球,算出从该点能看到的半球面积比例。由于 AO 与视角和入射光方向无关,静态物体可以离线预计算,通常存在纹理里。与本页「理论」相比,GEA 的定义没有提余弦加权。
- 在着色方程里,环境光项是低频的,表达不了表面细节和自遮挡,所以通常再乘一个 AO 项(卷 II 12.4.1.1,见 着色方程与经典光照模型)。
- SSAO:先不带 AO 渲染场景,再画全屏四边形,对每个像素读取自身和邻近像素的深度与法线(来自深度缓冲和 G-buffer),近似估计遮挡程度并据此变暗。暴力做法要比较数百个邻近像素;实践中预先生成 N×N 采样核,在每个像素随机旋转,只随机采少量邻居。SSAO 结果可信,但只是近似,容易出现条带等瑕疵(卷 II 12.5.7)。GEA 在后处理一节也把 SSAO 列为全屏后期效果(卷 II 12.7.2)。
- 与本页表格的关系:GEA 描述的"深度 + 法线、随机旋转采样核"是一般化的 SSAO;本页的 Crytek SSAO 只用 z-buffer,Shanmugam 与 Arikan 等方法才用法线缓冲。
LearnOpenGL 的视角:法线朝向半球核与噪声旋转(Advanced Lighting / SSAO)
来源:SSAO;摘录 Advanced Lighting — SSAO。Crytek 球核易使平面发灰;教程用 法线朝向半球(John Chapman 变体),常搭延迟 G-buffer(观察空间位姿/法线)。
CPU 生成最多 64 个切线空间半球样本(z∈[0,1]),用加速插值把样本压近原点;4×4 随机旋转向量纹理 REPEAT 平铺。SSAO pass:Gram-Schmidt 从噪声与法线建 TBN → 样本变到观察空间 → 投影采样位置缓冲深度 → 比深度累加遮蔽;smoothstep 做半径 range check;输出 1 - occlusion/kernelSize(可再 pow)。随后对噪声图案做小核模糊。光照:环境项 × AO。
参数强依赖场景:kernelSize、radius、bias、噪声尺寸。链 方向遮蔽、上文屏幕空间 AO 族。
GPU Gems 的视角:层级圆盘 AO 的高质量修正(GPU Gems 3 第 12 章)
来源:Hoberock & Jia《High-Quality Ambient Occlusion》;摘录 Chapter 12. High-Quality Ambient Occlusion — Hoberock, Jia。建立在 Bunnell(GPU Gems 2)动态 AO 之上,与上文 SSAO/HBAO/GTAO 互补:这是物体空间层级近似,不是屏幕空间。
Bunnell 法用顶点圆盘近似邻接多边形,以形状因子累加遮蔽,并用「圆盘自身的遮蔽」近似可见性,迭代几遍后像 AO,复杂度 。原法只适合光滑逐顶点结果:逐片元或加密网格会出现层级切换处的圆盘状断裂,以及靠近细圆盘时 主导的夹捏高光状错误。
修正三点:(1)在穿越层级的过渡带里对父子贡献做面积比加权混合,强迫阴影连续;(2)最细一层圆盘放在面心而非顶点;(3)树叶改算解析的点到多边形形状因子(Sillion & Puech),并先把三角形裁到着色点支撑平面得到可见四边形。实现上常用加权 强迫相邻两帧迭代收敛(封闭场景易振荡);再用距离衰减与三角形遮蔽幂次做艺术向亮度/缝隙对比控制。同一套层级积分还可把 solidAngle 换成多次散射核,做廉价次表面外观。与屏幕空间 AO 比:无视角依赖、能出接触阴影,但依赖预处理层级且可见性仍是近似,整体往往偏暗。
GPU Gems 的视角:动态圆盘 AO 与间接光(GPU Gems 2 第 14 章)
来源:Michael Bunnell《Dynamic Ambient Occlusion and Indirect Lighting》;摘录 Chapter 14. Dynamic Ambient Occlusion and Indirect Lighting — Michael Bunnell。Gems3 第 12 章高质量 AO 的直接前身。
把网格变成朝向圆盘(每顶点一个,面积取邻接三角 1/3),用定向圆盘立体角近似互相遮蔽,不算显式可见性。第一遍累加立体角得可及度;第二遍用发射体可及度调制,去掉双重阴影,并累积弯曲法线。父子圆盘层级把复杂度从 降到实践 ,可动画变形。同一框架把立体角换成圆盘形状因子,就能做一跳间接漫反射/面光源。局限:三重以上遮蔽仍偏亮,需加权混合多遍;Gems3 Ch12 再修圆盘断裂与夹捏。
出处
- realtime_rendering_4ed.pdf 第 11 章 Global Illumination
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 12 章 12.4.1.1、12.5.7、12.7.2 节
- Chapter 12. High-Quality Ambient Occlusion — Hoberock, Jia
- developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-12-high-quality-ambient-occlusion
- Chapter 14. Dynamic Ambient Occlusion and Indirect Lighting — Michael Bunnell
- developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-14-dynamic-ambient-occlusion-and
- Advanced Lighting — SSAO
- learnopengl.com/Advanced-Lighting/SSAO