03 - 屏幕空间的实时全局光照算法
本文将介绍一些屏幕上的实时全局光照算法,例如 屏幕空间环境光遮蔽SSAO
,屏幕空间方向性遮挡SSDO
和屏幕空间反射SSR
。
屏幕空间算法
如果全局光照算法在生成间接光照效果时,只根据从相机视角能得到的信息,对只有直接光照的渲染结果进行后处理(post processing)以加上间接光照效果,即只用到了屏幕空间(screen space)信息,则这该算法属于屏幕空间算法。
SSAO
简介
SSAO(Screen Space Ambient Occlusion) 是一种在屏幕空间中对全局光照的近似。

如下图,SSAO 可以让场景看起来更真实,因为它让物体富有立体感。而且 SSAO 的实现也比较容易,因此是必要的。
SSAO 的核心思想如下:
- 不知道间接光照的具体内容(屏幕空间),于是假设它是个常数。
- 认为各着色点所有方向上的可见性不同,因为着色点间存在 “遮挡” 关系。
- 认为物体材质都是漫反射 (diffuse) 材质。
这样就可以通过估计着色点的可见性,直接地计算出间接光照效果。
理论推导
需要解 RTR 渲染方程,使用积分近似将其拆分成可见性 V 项 + 其他项:
其中:
- 可见性 V 项:即
,从着色点看向周围所有方向可见性的加权平均,范围 0~1。 - 间接光和 BRDF 项:两个常数的乘积
,即间接光强与漫反射 BRDF。
有关积分近似拆分:
可以理解为将
f(x)
,g(x)
拆开,顺便求了f(x)
的均值。上面这种拆分是准确的,因为f(x)
和g(x)
都是常数。为什么拆出来 3 个 cos 项?是因为要进行换元,引入 “投影立体角” 这一概念,即球面立体角在它单位圆上的投影,有
。于是变成了在 “半球” 上的积分,且 。
间接光和漫反射 BRDF 项均为常数,于是可以将它们从积分中提出来:
也就是
计算 Ka
从上面的理论可以得出,要计算 SSAO 只需计算
如图,SSAO 算法在以着色点为中心,一定半径的球里进行采样,得到被遮挡(红)和不被遮挡(绿)的点的数量。在屏幕空间如何判断着色点和采样点的遮挡关系,可以利用屏幕空间的深度值来判断,若采样点深度比屏幕空间中该点深度大,说明该采样点被遮挡了。
当超过一半的采样点均被遮挡时,认为该着色点是不可见的,应用 SSAO。
计算出的
在估计可见性时没有考虑法线方向,导致出现 “假遮挡” 现象,如上图中间红虚线右边的点,应该是绿色的,但被 SSAO 计算成了红色。不过影响不大,可以忽略。
算出来的
没有被余弦加权平均,在物理上不准确,但看起来还算正确。
避免 “假遮挡”
要想避免假遮挡现象,就得进行更多采样,但实时渲染的性能要求不允许我们这样做,可以用下列技巧来缓解 / 避免 “假遮挡” 现象:
可以用较少采样得到有噪声的结果,然后降噪,获得 “更多” 的采样点。
现代图形渲染管线通常是 延迟渲染 (Deferred Rendering) 的,可以通过其中的 G-Buffer 获取当前着色点的法向量,有了法向量就能将采样点的范围缩减至一个半球,让结果更准确。
这也是 HBAO 的思想:
HBAO 的结果是准确的,因此可以避免假遮挡现象。
SSDO
简介
是 SSAO 的升级版,比 SSAO 考虑的更全面准确。SSAO 假设间接光来自远处,而 SSDO 则认为间接光来自附近,因为场景中的间接光照信息还是知道一部分的。
由于是屏幕空间算法,SSAO 无法像 RSM 那样获取间接光照信息,于是 SSDO 认为 屏幕里能被直接光照射到的物体就是间接光源。
SSDO 的核心思想和路径追踪很像:
在着色点 P 上向任意方向射出若干光线,如果
- 光线没有打到物体,说明射向 P 的光线是直接光;
- 光线打到了物体,说明射向 P 的光线是间接光。
和 SSAO 对比
如图,SSAO 和 SSDO 最主要的不同点就是 间接光的来源不同:
- SSAO 认为着色点一定能够接收到部分间接光(红圈),另一部分则因为遮挡没有间接光(橙圈)。
- SSDO 认为着色点射出光线后,打不到物体的是直接光(红圈),打到物体的则为间接光(橙圈)。
因此,SSAO 认为 间接光来自远处,SSDO 认为 间接光来自近处,理论上它俩应该结合起来做才科学。
理论推导
还是解渲染方程,将其分为可见和不可见两部分:
重点考虑不可见(间接光贡献)的情况,而这种情况是可以被算出来的。
具体做法
SSDO 的做法类似于 HBAO,在着色点为球心,一定距离的半球上进行采样,然后将采样点和摄像机视角深度值比较,如果采样点深度比摄像机视角深度大,说明采样点和摄像机连线与物体的交点所在面片是一个次级光源(如左图 A,B,D);反之则不是次级光源(如左图 C)。
最后利用渲染方程将所有次级光源对着色点的贡献求和即可。
但 SSDO 也存在误差,如右图 A 点,本来是直接光源,却被 SSDO 误认为是次级光源。
优缺点
优点:
- 效果很好,接近离线渲染
- 轻量化
缺点:
- 只能表示小范围的全局光照,这说明它仍会丢失一些来自于远处次级光源的信息。
- 屏幕空间算法的缺点,有来自屏幕外的误差和信息缺失。
SSR
简介
SSR 也是一种屏幕空间实现全局光照的方法,它在屏幕空间上进行模拟光线追踪,不需要场景图元信息。
SSR 的核心问题如下:
- 求交问题:解决任意光线和场景求交的问题。
- 着色问题:计算光线与场景相交的像素点们对着色点的贡献。
具体做法
基本 SSR 算法
为了充分利用屏幕空间提供的信息,该算法是基于 镜面反射 的。
对于每个着色片段:
- 计算反射光方向
- 让光线和场景求交,获得交点
- 让交点颜色作为反射的颜色
可以做镜面反射,也能调整地面粗糙度,配合法线造成模糊 / 凹凸效果。
接下来说说如何具体进行求交和着色操作。
解决求交问题
起初人们使用 Linear Raymarch 算法进行光线和场景求交。反射光线在着色点往反射方向以一定的距离步进,直到它的深度比场景物体深度大停止步进,视为光线和场景物体相交。
在这个算法中,步长为定值,太大太小均不好。于是能 让步长动态调整 的算法 Hierarchical Ray Trace 便出现了。
就像世界空间光线和场景求交可用层级结构加速(如 BVH 树、KD 树)一样,屏幕空间中光线和场景求交可用 深度 Mipmap 来加速。该深度 Mipmap 和平常的 Mipmap 不一样,平常的 Mipmap 使用下层 4 个像素均值作为上层像素,而 深度 Mipmap 使用下层 4 个深度最小值作为上层深度。
这样就让场景深度值有了类似于树状的层次结构关系,方便光线动态步进:
解决着色问题
对 SSR 的着色要达到如下要求(在正确考虑物体 BRDF 前提下):
- 根据反射面材质做出不同反应(如镜面地板,粗糙地板等);
- 离物体越近,反射得越清晰;
- 类似雨天路面效果,反射物体会上下拉长一点(如果有场景是雨天)。
可沿用路径追踪算法,不过要假设:
- 反射物材质是漫反射材质,这样就不必考虑方向导致贡献的不同;
- 只有次级光源。
因此可用 BRDF 重要性采样 来获取着色点反射光线的方向分布。然后为了复用采样结果,可以在采样前预过滤一次,然后用加权 BRDF 加速运算。这里的 “加权” 就是利用该像素旁边一圈像素的结果,用它们深度值以不同贡献求均值。
优缺点
优点:
- 对镜面 / 光滑材质地板性能高
- 效果好
缺点:
除了对漫反射材质地面性能和效果不好外,还是屏幕空间带来的信息不足的问题:
屏幕内物体信息丢失,如下图没有手心的信息:
屏幕外物体信息丢失,如下图没有帘布的上端:
对于第二种情况,我们可以随反射距离衰减着色结果来解决: