当前位置:主页 > 技术方案 >

AmbientOclusion(AO)是一种技术方案

发布时间:2021-01-08 22:27   浏览次数:次   作者:admin
AmbientOcclusion(AO)是一种技术方案,用于在某一光源射向某一物体表面上某一点的光线被其他物体遮挡的情况下,计算该点反射到相机的光线数据。实际上,AO是全局光照的一个副产物,但由于目前硬件条件下,要实现实时全局光照太难了,所以会通过各种表现效果的叠加来模拟全局光照,而AO是其中应用非常广泛的一个。
AO技术能给出物体表面弯曲信息等几何形状线索,是一种常用的提高画面质感的实现方案,为了达到这种效果,人们提出了各种各样的技术思路,这里就专门来对平时工作中遇到的有价值的实现思路进行总结,一方面是为了巩固积累,另一方面也希望以后能快速筛选出适合的方案,以后再需要的时候也可以。
一、SSAO
SSAO是ScreenSpaceAmbientOcclusion的简称,它是Crytek于2007年在Crysis上首次提出的实时AO方案。
该方案是通过后处理过程完成的,也就是说,只需要一个PS,整个过程所依赖的资源贴图就是屏幕空间的深度贴图和法线贴图(也可以由深度贴图导出)。
用文字描述的具体实现原理大概可以概括为:
对于每一个需要计算AO数据的像素(即屏幕空间的每一个像素),将该像素对应的法线作为up方向,并以给定的长度作为半径,朝上半球发射几条长度为半径的射线(事实上,CrytekSSAO的方案不局限于上半球,而是分布于整个球体,这会使墙面看起来灰蒙蒙的,可参考文献[2])
光线和采样点的示意图。
基于深度贴图信息,对单个光线的碰撞进行统计。
假定碰撞的射线数为N,总的射线数为M,则该像素的AO结果只需简单统计为1-N/M即可。
实施这一方案的效果取决于每像素发出的光线的数量和长度,如果数量太多,长度太长,就会导致性能的急剧下降,如果数量太少,就会造成条带误差,如下图所示:
萨姆普斯纳姆结果。
为尽可能减少采样点数(射线数),同时保证AO质量,采用了一种随机算法,即在放出射线时,使每一像素的放出射线的方向被打乱,这样可以明显地降低前面提到的带状误差,尽管实际上误差总量没有发生变化,但由于人眼对规则值的误差容许范围较低,这种方法仍然能够改善显示质量,随后如果在噪声的基础上增加一种模糊处理,还可以进一步改善显示质量,如上图右边的小图所示。
这个方案执行的对比结果如下图所示,可以看出,在SSAO启用的场景中,效果仍然有很大的变化。
萨索·卡帕里森
二、HBAOorHDAO
horizonbasedambientocclusion的简称HBAO,而HDAO是HighDefinitionAmbientOcclusion的简称,实际上两者是等价的,只是后者由AMD提供,而前者由NVidia提供。
HBAO和SSAO一样,是一种基于深度贴图+法线贴图的后处理过程,它可以直接通过一个PS完成。
某一点P上的遮挡信息AO可以简单地表示为如下公式:
这里所表达的是在整个球体空间中各个方向上的可见函数,当从一点开始,认为方向的射线发生碰撞时返回1,否则返回0,而表示的是线性衰减函数(用来表示亮度源的亮度衰减,这在SSAO中没有体现,而是把每个点的亮度数据做了简化,直接等效)。
实施原则示意图
以下是HBAO的实现原理。正如上面(a)小图所示,我们用球坐标表示,其中待计算点P和摄像机之间的连线用来表示球坐标系的上部方向,指向整个球面的天顶(zenith),而方位角(ezimuthangle)用来表示球心垂直横截面Plane上的直角(Plane),方位角(elevationangle)用来表示球心垂直横截面上的直角(Plane),方向指向该平面上对应射线投影方向的顺时针夹角(elevationangle)。
球坐标系
然后,如前面(b)小图所示,使用一条直线(这条直线我们称之为horizonline,尽管它看上去不像是水平的)。为了拆分球面,这条水平线用一个符号表示水平角,水平角实际上代表了这条水平线的仰角,它的定义是一个最小仰角,它从前方横截面不断地增大,直到没有碰撞为止。
本例中,如果点P附近的高度信息是连续的,那么水平线下面的射线必然会与周围的场景发生碰撞,这样就不需要再进行进一步的射线相交检测,所以前面的公式(2.1)可以改为如下形式:(也就是说,只考虑可能发生碰撞的区域,对球面积分进行展开):
对于仰角的起点和终点,积分的起点和终点分别是和,前面已经提到过,它是水平线的仰角,而实际上它是指tangentangle,也就是当前点的切线所对应的仰角,由于符号的原因,这个值在这个图表中是负的。与公式(2.1)中的整型相比,这里只考虑了朝向法线的半球区域,这与前面SSAO的半球区域相吻合。
若线性衰变函数
这里提到了P点到方向上水平点的距离,它表示射线的作用范围,也就是积分球面的半径,在这种情况下变得不相干,可以单独提取,先完成内部积分:
此公式也是连续积分,还是需要在PS执行时通过蒙特卡洛算法转化为累加形式,累加形式给出如下(对于某一像素,其法线与视线方向相同,那么,其tangentangle对任何一个像素来说都是不变的,所以下面的累加直接用来表示P点位置的tangentangle):
此公式中的N代表P点发出的射线的数量,而对于每一条射线,通过射线上多个深度的sample(具体sample数量取决于AO的覆盖半径R)才能确定下一个值,如前面实现原理示意图的(c)小图所示,至于每个方向的输入光亮度(可直接获得简化处理)。
当使用regularsamplepattern时,很容易出现SSAO的bandingartifacts,同样,这里可以对每个像素的射线角分布进行随机化处理,而对每个射线上的sampledistance进行随机处理,这将极大提高显示质量。
上述HBAO算法的基本思路是HBAO算法在实际应用中,还会遇到一些问题,参考文献[5]为这些问题给出了相应的解决方法,感兴趣的同学可以去看看。
HBAO算法与SSAO算法相比,在物理上更为正确,因此其效果也更接近真实,但其性能消耗远大于SSAO算法,在实现过程中为了降低消耗,通常都是在1/2分辨率上进行计算,但这种方法一方面仍然比SSAO算法慢,另一方面也会导致效果出现闪烁现象,LouisBavoil为解决这一问题,进一步优化了原有的HBAO算法,提出了新一代HBAO算法,我们通常称之为HBAO+。
三、HBAO+
首先,在引入具体实现细节之前,我们要对HBAO+和HBAO+的效果进行比较,HBAO+的执行速度一般是HBAO+的三倍,并且能够呈现出更丰富的细节,听起来很神奇,那么到底是怎么做的呢,我们一起来看看吧。
总体而言,HBAO+算法实际上是HBAO算法和Cache-EfficientPost-Processing算法结合在一起的一个结果,该算法通过将多张子图A的AO输出分解为多张子图A。