【博物纳新】专栏是UWA旨在为开发者举荐新鲜、易用、乏味的开源我的项目,帮忙大家在我的项目研发之余发现世界上的热门我的项目、前沿技术或者令人惊叹的视觉效果,并摸索将其利用到本人我的项目的可行性。很多时候,咱们并不知道本人想要什么,直到某一天咱们遇到了它。
明天举荐的我的项目来自UWA开源库:https://lab.uwa4d.com/lab/5b5...
一、概览
AO(Ambient Occlusion)是一种基于全局照明中的环境光(Ambient Light)参数和环境几何信息来计算场景中任何一点的光照强度系数的算法。AO形容了外表上的任何一点所承受到的环境光被四周几何体所遮蔽的百分比,因而使得渲染的后果更加富裕层次感,对比度更高。
该我的项目介绍了一种疾速的基于顶点的AO算法,将AO看做模型顶点的一个属性,通过深度相机对模型多地位的采样,联合模型顶点的深度校验来计算对应的AO值。该办法相比拟于SSAO,是一种比拟玲珑快捷的繁难办法。通过对该项目标学习,读者能够初步理解AO算法的思维,也能够学到该算法的具体简化策略。
二、原理概述
总体来说,该算法能够分为两个步骤:
1.采样:通过扭转深度相机的地位并对指标物体渲染,把各个地位获取到的深度图保留下来作为采样数据。
2.计算AO:将采样数据通过深度校验来辨认出须要遮蔽的模型顶点并依照肯定权重累加遮蔽值,以达到暗影成果。
该办法并不是一个实时计算的办法,而是一个一步到位的办法,实质上是在运行刚开始时就计算好了一个带有AO的材质并替换掉模型原有的材质。所以它并不会随着光照的扭转而扭转,艰深来讲就是“把容易变暗的中央的色彩画得暗一点”。
三、具体实现
从geoAO.cs来看,所有的工作都是在Start()中实现的,如下图,而采样和计算AO的次要逻辑大都在DoAO()中。
1. 采样
该步骤须要一个深度摄像机来采样深度图,摄像机的创立在CreateAOCam()中实现:
该摄像机从创立开始就是暗藏状态(148行),因为咱们并不需要OnRenderImage()每帧都执行,咱们想要它“按需执行”,确切来说是为了让Blit函数“按需执行”(如下图),那么咱们能够通过把相机暗藏,用Camera.Render()来手动调用OnRenderImage()。
除此之外,咱们也留神到为了模仿平行光成果而把摄像机模式改成了正交(150行),且开启了深度模式(158行),这时一个深度相机就曾经筹备实现了。
采样环节最外围的环节如下图,该局部在DoAO()函数中:
首先,该for循环的循环次数对应着采样次数,也就是最终渲染进去的深度图样本数量,而样本个数决定了AO的精度高下:
在每一轮采样过程中,AO摄像机(AOCam)作为一个独自的深度摄像机,会达到一个新的曾经计算好的地位(256行),而后看向模型(257行),接着把筹备好VP矩阵传给Shader,最初渲染。
这里能够留神到276行就是在手动调用OnRenderImage()函数,但其实计算AO这一步就是在276行在Shader(VertexAOCompute.shader)中进行的,相当于每一轮循环都会做一次AO运算,而后每轮得出的AO值最终会累加在一起附给一个新的材质。
2. 计算AO
AO的计算在VertexAOCompute.shader中。下图是片元着色器局部:
判断到底哪些点须要有“遮蔽”的局部就是120-121行。从118行的正文咱们也能够晓得,变量o“决定了遮蔽会有多暗”,而120行通知咱们,对于vertex.z和z相差过大的点,也就是被遮蔽的点,o不会参加累加(121行),因为o越大模型就会越亮。最初的累加会带上权重,只不过每次采样的权重都一样而已(124行)。
而上一步计算出的AO(65行)作为上图中的_AOTex参加了最终图像插值时的权重值(67行)。最终渲染出的图像会附着在一个新材质球上,而该材质球会替换掉模型原有材质(如下图),至此AO成果就增加到了模型上。
3. Tips
该工程计算AO的过程很间接地体现出了AO算法的思维。
概括来讲,环境遮挡被定义为从外表上某一点可能逃离场景的射线的比例。上文提到的每一轮AO采样计算相当于图中每条绿色的射线,而判断深度是在看该射线是否会被遮挡,最初的累加就是在计算比例,而这里通过样本均值来估算积分的过程也是蒙特卡洛积分思维的体现。
四、性能剖析
本次测试用的是低端机型OPPO A32(4G RAM),测试分为开启和不开启GeoAO这两种状况。首先,下图显示的是开启状况下的FPS均值和GPU耗时状况:
下图是不开启该插件的状况:
能够看出即便在低端机型上,该工具的开启也没有为GPU和FPS造成压力,相同的是,GPU耗时反而比不开启的状况下要低,这是因为该插件只是在Start()函数中置换了一下物体材质,而新材质比不开启时的材质(Standard)更轻量化的缘故。
提醒:并不倡议在游戏中途加上该成果,因为它会因为Shader.CreateGPUProgram和AO计算而引起卡顿。其中,Shader.CreateGPUProgram的耗时能够进一步通过收集变体并预热的形式排除,能够参阅《一种Shader变体收集和打包编译优化的思路》;而剩下的AO计算局部放在场景加载阶段实现则是能够承受的开销。
综上所述,该插件是一个比拟轻量级且成果尚可的计划。
作者公布我的项目时的介绍应用的是英文编写,为了不便大家浏览,UWA开源库已将其翻译成中文版本,欢送大家独特学习。
明天的举荐就到这儿啦,或者它可间接应用,或者它须要您的润色,或者它启发了您的思路......