赞
踩
近些年,随着画面表现要求越来越高,游戏渲染加入的细节也越来越多。本文将介绍两个项目常用渲染效果在Unity中的实现思路:地形贴图融合以及HBAO。
一、地形贴图融合
这个效果本质上是处理模型与地形之间在视觉上形成硬接缝的问题,这里先放一下效果开关的对比图:
效果开
效果关
个人认为,这个效果对于整体观感的影响还是非常显著的,而代价可以说是比较低廉。目前的做法是在渲染场景物体之前,把地形的albedo,smoothness,normal,以及depth,先渲染到三张1/4分辨率的rt上。其中,albedo和depth是必须的,其他量可以根据项目的性能要求和美术要求进行取舍。然后,在渲染场景物体时,根据当前点地形深度与着色点深度差(即视方向深度)作为权重来混合对应的量。
此效果是使用RenderFeature接口,LightMode接管pass的方式来实现的。需要注意的是,在地形Layer数量大于4的时候,unity会自动调用TerrainLitAdd shader把地形再渲染一遍,所以相关的计算要同时加在TerrainLit和TerrainLitAdd中,以及注意相关的宏设置。至于TerrainBase,只是会在远视距下低精度渲染地形,就不需要添加了。
先说一下做这玩意时候的几个坑点吧:
地形部分的修改没啥好说的,把原来的pass拷一份,把不要的计算去掉,输到自己声明的rt上就完了。接下来就在需要融合的场景物体shader中加入采样代码:
这里设置了一个逐材质的_BlendDiffer参数,可以逐材质调整深度差阈值,从而调节融合区域的大小。Smoothstep计算出来的权重用于参数柔和过渡效果。
二、HBAO
此效果属于是SSAO的升级版。虽然说性能开销在移动端上依然是不可忽视,但是确实能够极大提升场景的立体感,如下两图:
效果开
效果关
看过这个后处理的渲染效果之后,咱们来简单地说一下背后的理论和计算。实时渲染的所谓AO(ambient occlusion,环境光遮蔽),其实本质上是一种全局光照效果的简单近似。直观地说,它来自于一个很简单的生活观察,即物体与物体接触的一定区域内会显得比较暗(contact shadow,接触阴影)。在光线比较充足的情况下,在这块区域中甚至会染上另一个物体表面的颜色(color bleeding)。这种现象背后的原因自然是光线在空间中的无数次弹射,在渲染中对应的是近来很火的光线追踪技术。但是光追啊,好是好,就是太费了,移动端那点捉襟见肘的性能根本不够看。所以,大伙就把全局光照效果拆成好几种渲染技术,对效果和性能进行了不同的取舍,在实际使用的时候进行灵活组合。AO就属于是这一类效果中比较好实现,性能不错,对画面观感提高比较大的效果之一,性价比很高,所以得到了很普遍的使用。而这个效果本来就是一种近似,输出也比较低频(糊),所以各种AO技术基本都是在屏幕空间(screen space)进行降采样计算。
在这里,有必要说一下,材质面板的AO贴图,插在光照计算中的SSAO,以及后处理的SSAO三者之间的关系。
接下来,该说一下咱们标题的HBAO,是个啥玩意了。HBAO(Image-space horizon-based ambient occlusion),总之就是Nvidia在2008年提出的一个对SSAO技术的改进,介绍的PPT链接:https://developer.download.nvidia.cn/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf。过了这么多年,这个算法各种语言版本的实现可谓是铺天盖地。本着不重复造轮子的理念,核心代码直接从英伟达那边搬了过来。也不是什么复杂的东西,就先大概说一下它的计算逻辑,图片均截取自英伟达的PPT:
1.
首先,我们需要的输入是视空间深度图和法线图。
2.
P为当前着色点,以P为圆心往外均等分布采样方向(如图是四向,越多方向就越费,效果越好),同时给每个像素一个随机值使得采样方向有区别。
3.
然后在每一个方向上,我们就能得到一个一维的高度场。
4.
沿着采样方向,以设定的步进次数与AO半径计算出步进距离,记录每次步进的horizon angle。
5.
比较出最大的horizon angle为h,这个方向上的AO值计算公式如图。
6.
对各个方向计算的AO值取平均,则为当前点AO值。
7.
整体流水线。可以见到后续还有模糊操作(因为在角度旋转时使用了噪声)。
至于原文还提到的一些实现的小细节,譬如法线角度阈值,衰减公式等,这里就不再展开了,感兴趣的读者可以在网上搜到非常多详细的技术文章。接下来主要分享一些HBAO计算并入现有管线的一些需要注意的地方。
只要把HBAO最终输出绑到这几个变量上就好了
当然要记得开启一下关键字
2. 既然我们最终都要进行一次模糊,而AO只是占用一个通道,那么如果管线中开启了屏幕空间阴影的话,可以通过ColorMask参数控制AO只写入RT的一个通道,然后与屏幕空间阴影共用一张RT。两个pass都走完之后,再对这张RT进行统一的模糊操作。
3. 如果对于降采样的AO效果噪点有点不可接受的话,可以对于HBAO这张rt单独进行一次TAA。在旋转方向和步进中加入jitter,然后和历史帧进行混合。目前测试使用的序列如下:
当然,AO效果单独走一个TAA什么的,后期优化的时候很容易就被砍掉,所以还是看项目需求。一般来说只要不是降采样太夸张,模糊了之后统一走一遍全屏抗锯齿最后效果应该也还行。
4. 如果一定要在前向管线用,又不想加入深度法线的prepass,可以把AO计算放在光照之后,然后加入一个MultiBounce操作。(来自一个更新的AO技术,GTAO的论文:https://iryoku.com/downloads/Practical-Realtime-Strategies-for-Accurate-Indirect-Occlusion.pdf。)
。A为计算出的AO值,ρ为场景albedo值。虽然这个方法本来不该是这么用的(捂脸),而且咱们前向也拿不到场景albedo值只能拿光照结果来凑数(甚至带着阴影),但总比直接黑一片要强。反正就是要视觉上减弱ao效果,强行乘上系数或者自己拟合曲线都显得有点不太靠谱,不如用人家大佬拟合的曲线,似乎还有几分道理(强行解释)。
5. 除了以上的方法,想要“稍微合理一点”地减弱AO,还看到过一种方案,伪代码大概是:
。最终可以出来一种物体接触部分一定半径内color bleeding的效果(有点SSDO的意思?)。至于这个性能开销值不值得,效果好不好,那就是见仁见智了。
这次的分享到此就结束了。本文权当抛砖引玉,如果上文有任何错误的地方,或者有更好的做法,还请不吝赐教,感谢您的阅读!
欢迎加入我们!
感兴趣的同学可以投递简历至:CYouEngine@cyou-inc.com
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。