介绍
AO(环境光遮蔽)
在具体介绍SSAO之前, 先介绍更加广义的AO(Ambient Occlusion 环境光遮蔽)。简单来说,AO是一种基于全局照明中的环境光(Ambient Light)参数和环境几何信息来计算场景中任何一点的光照强度系数的算法。AO描述了表面上的任何一点所接受到的环境光被周围几何体所遮蔽的百分比,因此使得渲染的结果更加富有层次感, 对比度更高。它是模拟光线到达物体能力的粗略的全局方法。
计算 AO 可通过在半球面上对可见性函数的积分来得到,公式为:
其中:
- Ω是 p 点朝向法线方向的半球面上的方向集合;
- d(ω) 是 p 点到其沿ω方向与场景的第一个交点的距离;
- V(ω)是距离衰减函数衰减函数从单位距离 1 开始衰减并在某个固定距离下衰减到 0;
SSAO(屏幕空间环境光遮蔽)
一般光照模型中,环境光用于模拟光线的二次散射(向外散射,反射),从而使得不受直接光照的地方也能有一定的亮度。但很明显,暗处不应该有太多的光被散射出来,所以暗处和直接被环境光照射的地方亮度不应该相同。而在光照模型中,环境光是一个定值。所以ssao出现了,它解决的就是如何定量环境光照射不到的地方应该吸收多少环境光的问题(二次散射不出去的光自然大部分都被物体吸收)。下图左边的暗处就太亮了,而右边暗处更加真实。
通过获取像素的深度缓冲、法线缓冲以及像素坐标来计算实现,来近似的表现物体在间接光下产生的阴影。基于顶点的AO计算需要进行光线与场景的求交运算,所以是十分耗时,所以实际应用中主要使用SSAO算法,SSAO 算法将深度缓存当成场景的一个粗略的近似并用深度比较代替光线求交来简化 AO 计算。
原理
概述
- 计算深度、法线缓冲
- 深度 -> 像素坐标
- 法线 -> 法向半球随机向量
- 计算像素随机后的坐标(多次采样)
- 获取随机后深度并比较
- 判断加权 AO
- 后期(模糊等)
样本缓冲
深度缓冲
深度缓冲中的 depth 值用于当前视点下的场景的每一个像素距离相机的一个粗略表达,用于重构像素相机空间中的坐标(Z),来近似重构该视点下的三维场景。如下图为深度缓冲的图,越黑代表离摄像机越近,深度值范围为0-1,越小越近。
法线缓冲
相机空间中的法线信息,用于重构每个像素的”法线-切线-副切线”构成的坐标轴(切线空间),用于法线半球中的采样随机向量(随机向量用于判断、描述该像素的AO强度)。
法向半球
前面说过,SSAO是为了定量环境光照射不到的地方应该吸收多少环境光的问题,也就是光线的二次散射。因此需要为每一个片元模拟一个随机的光线散射模型。
对屏幕空间内每一个像素计算其在三维空间里的位置 p,执行下列步骤:
- 在以 p 点为中心、R 为半径的法线半球体空间内随机地产生若干三维采样点;
- 对于铺屏四边形(Screen-filled Quad)上的每一个片元,我们都会根据周边深度值计算一个遮蔽因子(Occlusion Factor)。这个遮蔽因子之后会被用来减少或者抵消片段的环境光照分量。遮蔽因子是通过采集片段周围法向半球(Kernel)的多个深度样本,并和当前片段深度值对比而得到的。高于片段深度值样本的个数就是我们想要的遮蔽因子。上图中在几何体内灰色的深度样本采样点都是高于片段深度值的,他们会增加遮蔽因子;几何体内样本个数越多,片段获得的环境光照也就越少;
- 红点表示我们需要计算的样本,红色向量表示样本的法向量;白色灰色点为采样点(很明显,采样点的多少影响最后的渲染效果),其中灰色点表示被遮挡采样点(深度大于周围),据此判断最终AO的强度。
很明显,渲染效果的质量和精度与我们采样的样本数量有直接关系。
- 如果样本数量太低,渲染的精度会急剧减少,我们会得到一种叫做波纹(Banding)的效果,如下左图;
- 如果它太高了,会影响性能;
- 我们可以通过引入随机性到采样核心(Sample Kernel)的采样中从而减少样本的数目。通过随机旋转采样核心,我们能在有限样本数量中得到高质量的结果。然而这仍然会有一定的麻烦,因为随机性引入了一个很明显的噪声图案,如下中间图。我们将需要通过模糊结果来修复这一问题,如下右图。
这里之所以使用法线半球体,是因为如果使用球体会整体画面会变得灰蒙蒙,因为针对大部分像素,采样时总有一半的采样点在物体后面,也就是说大部分像素的遮蔽率最高就是0.5,所以整体画面会显得灰蒙蒙:
估算每个采样点产生的 AO 情况,具体来说,就是对每个采样点做深度测试,判断采样点是否存在遮蔽。再统计所有采样点通过深度测试的比例,该比例就是屏幕空间中该像素粗略的遮蔽率。当大部分采样点通过深度测试说明p点附近采样点大部分都没有被遮挡,p点大概率不会被遮挡。
网上流行的另一种计算AO的方法是:直接计算采样点在屏幕上的投影点跟 p 点的深度差异,来计算遮蔽情况。如下图所示,下图大部分投影的的深度值都小于P点深度,说明P点被遮挡的概率较大。该方法往往会带来自身遮蔽等走样问题,因此使用情况较少。