gdc19年,一直开发地铁系列的4A games;
4A games是成立于2006年,乌克兰开发商,一直做metro系列游戏,三个大版本,中间两个重制版。
技术上一直metro是比较激进的,是硬件厂商show技术的常客,这次raytracing也没有缺席.
一些细节的效果对比可以看这里:
https://www.bilibili.com/video/BV1M5411s7v4/
本文聊得是gdc19上4AGames的talk,也是个人认为到目前为止(2020.5.6)讲游戏中使用raytracing中最好的一篇。
我们可以看到从整体上看,rt版本的光照更加的完整自然。
4AGames是用stochastic的方式,用raytracing做了RTAO,RTGI
这里也代表了raytracing技术带来的几个明显提升点:
btw:
stochastic的方式,就是以一些随机分布的方式在空间上低频采样,然后再通过denoise来复原画面的方式:
(如图,左边是stochastic根据一些概率分布函数在空间中采样计算,然后结合空间&时间(temperal)信息做denoise,就是右边的结果了)
这里是整体的pipeline。
这个部分介绍整体pipeline的情况,其中两个要点:irradiance表达和denoise后面单独章节来说。
在nvidia目前的turing架构下,是要建立bvh((bounding volume hierarchy))作为acceleration structure。
compute shader有的特性,在bvh构建的时候都有,比如async compute。
这里有top level acceleration structure和bottom level acceleration structure。
各自更新原理比较简单,地铁里也介绍了些技巧,不赘述。
1,pre trace,
这里先通过一些更便宜的计算,尽量规避掉比较费的raytracing,比如raymarch地形的depth等等
这部分raymarch会和bvh构建一起通过async compute同时做,
3,ao
有了distance,RTAO就很自然了,做AO+filtering
4,gi
以trace的结果做lighting计算,能用上的优化都用上,比如重用deferred lighting已经计算好的部分,用atmosphere中计算好的部分;
已经计算好的部分(也就是frustum之外的)就再做次计算。
这里真正麻烦的部分是denoise,可以看到做了两遍denoise。
在lighting阶段,会计算raytrace到的hit点的光照,这个光照如前所述,可以预计算,可以重用deferred lighting,可以重新计算。
结果是一个hdr的rgb的值,metro在encoding的时候是转到ycocg空间,然后y分量用L1的spherical harmonics来表达,cocg还是标量。
分离cocg这里还是人眼对颜色不敏感,而对于亮度敏感所致。
然后后续的所有denoise和accumulate都是在这个空间里做的。
一共耗费96bit。
其他情况,压到ldr空间等等,在一些极限情况,会损失效果,对于大范围denoise结果不好。
这里metro只是泛泛而谈,实际做的话,可以实际尝试下,拿到切实的原因。
然后trace的结果用sh存的,也是一个低精度的cubemap,所以用来做非常glossy的reflection也是可以的。
raytracing通过硬件能做到相当的实时,但是还远不到可以计算足够的ray的情况。
所以我们只能用少量的ray来模拟近似,也就是用stochastic(随机)的方式,然后通过denoise来恢复画面。
这里denoise总体上两个方向:convolution based(卷积)和deep learning based。
目前相对成熟的是convolution based,比较期待deep learning方向的发展。
metro也提到denoise是最繁琐的阶段,nvidia在gdc2020上的talk也建议大家把denoise尽量早的开始(确实很难也很烦)。
denoise部分主要考虑两个因素:
1,screen space or world space
使用world space更加正确;
2,uniform or not
metro用的quadratic kernel来做。
3,权重使用normal base还是plane base
权重是基于geometry表面的tangent plane来,可以让结果更加稳定,而不是基于normalmap的结果。
4,半径和sample数量的adaptive选择
这里就是尽量减少sample的数量,实际情况会根据,距离,方差和ao来选择;
距离不解释了。
ao就是这里会比较暗,所以少sample一些ok。
(可以看到方差不同的地方,sample数量有所不同)
variance就是变化比较小的地方,就blur的少一些,sample点也少一些。
当帧的sample点方差都是比较大的,随着temperal的积累,方差会逐渐降低。
temperal这里就是用了积累多帧的情况,类似taa方面。
这里metro主要做了两件事情:
这里列了下temporal->denoise和denoise->temporal两种方式下各自优劣势。
实际做的时候,ghosting一直也是非常让人头疼的地方。
这里是我们自己在做开发时候遇到的,就是denoise的时候会做blur,把周围的像素blur过来,这时候遇到动态物体的部分,就会出现ghost,然后通过temporal accumulation蔓延出去,变成ghost。