TGDC | 腾讯互娱谢渊:还原真实世界光照 光线追踪技术的应用

GameLook报道/2020年12月7日- 10日,由腾讯游戏学院举办的第四届腾讯游戏开发者大会(Tencent Game Developers Conference,简称TGDC)在线上举行。

TGDC自 2017年创办以来,一直坚持以开发者视角与需求为出发点,结合行业发展趋势,对大会内容进行不断升级和扩充,旨在为国内外游戏专业人士打造开放的交流分享平台,推动游戏行业良性发展、探索游戏更多可能。

光线追踪技术从2018年应用在民用级别显卡上之后,大量的游戏开发商都对此技术进行了相应的游戏开发工作。光线追踪是什么?如今的光线追踪技术还有哪些技术难点?腾讯NExT工作室的谢渊先生为我们进行了详细的演讲分享。

以下是演讲实录:

谢渊:大家好,我是来自于腾讯NExT工作室的谢渊。今天有机会跟大家一起聊一聊光线追踪。

首先在我们了解光线追踪之前,我们先看一看真实的世界,它的光照是如何进行的,我们现在看到的这张图。

通常我相信大家应该不会用人眼直接去看太阳吧,或者说去看一些光源。大多数的时候光照直接从窗户、门直射进来,进来之后经过墙壁或者物体进行一些二次反弹、三次反弹,随着光的能量逐渐的衰减,我们大多数时候看到的是现在这么一幅图像。

那么从微观的角度呢?我们再看一看这个光线是如何运作的。假设说一束光打到一个平面上面,那这时候的平面在自然界的视角里,当我们把它无限放大以后会发现,它的表面并不是那么的完美,那么的平整,所以说它的表面上,会有很多小的起伏,我们称之为微表面。那么光线打到这个微表面上面以后又会随着这个凹凸不平,反射到不同的方向。

在用电脑进行模拟自然界的这么一个光线的时候,比如说我们现在看到右方的这个图。

这是一个很简单的一个场景,一个很小的屋子里面上面有一盏灯,这盏灯它的光源发散的方向是四面八方的。我们可以想象出每一束光线打到周围的墙壁上之后,又随着墙表面凹凸不平,又发散出更多的一些二次反弹,二次反弹之后又打到一些桌子上、地面上、房顶上,每接触到一个平面又进行了一些更多次的反弹。我们可以想像这样的一个运算量其实是非常巨大的。

所以通常我们在模拟这样的一个光照情况下的时候,之前都通过一个离线渲染的方式呈现出来的。

好了,那现在我们想想,如果我们在实时渲染领域,如何去呈现这样的一个自然的一个情况?这时候我们要引入一个概念:光珊化。

什么是光珊化?其实我们可以想像,当我们眼睛看到一个屏幕之后,我们所关注的所有的内容是在这个屏幕内的这些物体,所以这个时候我们会以屏幕空间做一个裁切,也就是屏幕外的东西,我们暂时先不考虑到它的一些计算,然后我们把屏幕上的这些三维物体的信息,投射到屏幕的每一个网格像素上,同时在整个三维的场景里面,把转换到屏幕上的这些信息进行分类,比如说有一些法线信息、一些深度信息、一些ID信息诸如此类等等,最后当我们渲染的时候,我们会调用这些储存到显存里面的不同信息,进行一个合成运算,这样最后就是我们看到了最终的一个画面效果。

通过刚才的一个简单的描述,我想大家应该可以理解到这种方式,它最大的优势是在于快,非常得快。因为它会刨去掉很多看不见的一些信息,比如屏幕外的信息统统不算。第二个它会把很多三维信息,转换成以屏幕像素的形式作为计算,这样就大大节省了很多运算量,不过从另外一个角度去看,这样的方式它已经大大地削弱了一些信息,去还原真实的一个场景,所应该呈现出来的一些效果,所以很多基于物理上面的一些渲染或者说很好的效果,比如说屏幕外的一些反射等等,在光珊化的渲染下面并不能很好地呈现。

现在我们屏幕上看到的这个就是《重生边缘》这个项目。它采用了一个RTX的实时渲染,在这个过程中我们会看到光线跟踪开和关之间的一些对比。右上角RTX ON的时候就代表此时此刻光线追踪是开着的,如果是OFF就代表光线追踪关掉了。

目前我们会看到此时此刻RTX就是光追已经关掉了。那么在RT关掉的时候它地面这个水潭上面的反射的信息,大家可以看到,由于受到屏幕空间的限制,它反射的信息非常少,屏幕外很多的信息并不能正确的反映过来。当我们在RTX ON的时候就反射到很多屏幕外的一些信息。

这块大家看到的是一个铁丝网的一个投影,在光追下面的一个投影的一个效果。这个投影它来自于我们铁丝网,是采用Alpha test贴图进行制作的,所以说在光追开的时候,随着光源与被投射物体的 距离的近和远,它有一个半影的一个效果。

当我们在光追关掉的时候会发现,此时的这个投影是清晰的,但是这样对于我们在自然界观察的物体来讲的话,其实并不是很正确,因为随着物体投影距离的长和短,它的影子会有一个逐渐扩散的一个半影效果,这就是非RT情况下面看起来一个不真实的一个表现。

那这个场景里面,我们为了展示RT也是营造了很多一些,关于反射、投影、动态物体这样的一些情境。

这块也是一个水潭,它也是在一个阴影下面的。我们通过水潭里面的反射也会看到天空上面的一些信息,哪怕这个天空它并不在我们屏幕内显示。

反之大家看到关掉以后是乌黑一片,所以说这就是光线追踪带来的视觉上比较大的差异性。通常我们在设计一些光线追踪场景的时候,也会考虑到有一些比如说夜晚或者一些反射金属物体,比较多的这么一个情景,因为这样是比较容易去展现光线追踪的。

大家看这时候是角色在动态灯的投影情况下面的阴影的效果。此时RT是关着的,所以你会发现它的影子从近处到远处,一直都是比较实的,比较锐利的。

那反之,当RT开了以后,它有一个半影效果,动态物体的半影效果是非常明显的。大家可以考量一下,自己平时在路灯下走路的时候,你发现自己的影子是怎么样的一个效果 。所以整个这个场景里面,我们尽可能用了一些动态灯、动态物体、反射,更多地去营造光线追踪呈现出来的一些特有的效果。

好,那么通过刚才那个视频我们看到了RT在实际游戏项目中的一些呈现。那这个时候我们就要回到我们一开始的话题,到底光线追踪是如何去渲染的?

那么在一开篇的时候,我提到了我们自然界的光线都是从光源出发,对所遇到的物体进行一次二次的这样的反弹。

光追恰恰相反,它是从我们的摄像机作为一个射线投射出来,当这个摄像机,如果在我们的三维场景里面,求交了某一个物体的一个面,那么相应它也会发生这样的一些反弹,经过多次的这样反弹以后,可以追溯到这个物体,乃至光源,然后依次把这样的信息再反弹到我们的眼睛当中,这样就是形成了整个一个光线追踪的 一个路径的循环。

那么可以知道光线追踪,它是有反弹的这么一个概念在里面的。所以大家看看现在右边的这张图。

当我们把反弹的次数逐次提高以后,我们会发现每增加一次它反弹的次数和数量,都得到了巨大的提升和变化。所以说在实时渲染领域,尽管我们已经做了从屏幕出发的光追渲染方式,但是它的计算量,依旧是比较巨大的。这也就是为什么光线追踪,在实时渲染领域迟迟不能落地,迟迟不能在真正的项目中进行大批量推广的一个原因。

现在我们可以看看这张图。这个是近30年来CPU和GPU 整个的发展的路径。下方这个蓝色的线是CPU性能的一个提升,上方绿色的是显卡GPU的一个提升。通过这张图我们很明显地看到,我们GPU发展的速度远远超过了CPU 提升的这个幅度,特别是在2018年的时候,微软发布了DXR,一个基于Directx的RT的 API的结构。同年Nvidia也推出了RTX显卡,我们之前的显卡一直是GTX,2018年的时候,终于出现了一个RTX显卡。那这个显卡它和以往的显卡有什么区别?

它采用了一个基于光线追踪硬件加速的这么一个内核,所以说从RTX显卡开始,我们可以真正地把光线追踪应用到实时渲染领域。

下面这个视频我们可以看一看:

自从光线追踪在实时渲染领域应用以后,我们就可以在它上面应用原来基于离线渲染,物理的折射、反射、焦散的效果。这个视频我们是截自于UE4。

在我们实际的项目当中,光线追踪它通常是由四种形式得以呈现的。一个就是光追的AO,包括它的阴影、反射以及它的Global Illumination,就是GI。

我们逐个来去了解一下。光追在游戏当中究竟能给我们带来些什么?

这是一张截自于一个游戏画面的一张截图。我们可以关注一下,绿色箭头所指的方向。这是一个水潭和一个镜子,当我们光追开了以后的变化。

所以这张图一个对比,大家就可以比较容易地去发现,当它左侧的这个黄色的栏杆,在非RT的情况下,并没有比较准确完整地把它渲染出来,包括下方的水潭,其实它的上方有一个黄色的广告牌,但是在屏幕空间反射的时,因为没有看得到这个广告牌,所以说也就没有办法正确地反射出它在水面中的倒影,相对RT这块可以呈现出很多的细节,包括一些准确的位置,这也是我们通常在游戏开发里面会遇到的一个情景。

我们会在屏幕空间反射之外,有的时候我们会加一个反射球Reflection Capture。这个东西即是中间那个白色的那个球,它主要的目的就是以它为所在位置中心,在它的这个半径范围内 会抓取一些当前三维场景的一些信息,并烘焙到一个图上面。通过这种形式去弥补一些屏幕空间反射所不能呈现出来的一些信息,但是它的劣势也显而易见,第一个由于本身它的计算的精度的问题,它并不能非常准确地呈现出反射的位置,第二个本身这张图它的尺寸由于也是受限的,为了尽可能地去减少显存的一个开销,所以说它的反射出来的内容也是比较模糊的。

同时当我们在一个游戏场景中,大批量采用这样的技术的时候,对显卡的这个显存性能开销也是比较巨大的,而我们如果在这样的一个开阔场景中,我们采用了一个RT的一个反射,这样的话我们看到的内容,无论是准确性、清晰度都大大的改变,而且也会减少一些显存的开销。

下面这张图是一个动态物体的一个反射的展示。

我们知道动态角色在游戏中他们的反射,之前提到Reflection Capture是没有办法的,因为它只能抓取一些静态的物体,所以说在动态物体的时候,只能是一些屏幕空间的反射来支持它,比如像现在水面上的一些效果。

我们看一下RT开了以后,在动态物体移动的时候它的投影反射依然是比较清晰可见的。

好,下面这张图我们可以看一下。

当整个海量AI的场景呈现在我们视觉当中的时候,角色身上这些材质的Roughness 它是相同的,这样的话 我们可以进行一个渲染的合批,在这么多角色被RT的反射渲染下,我们依然可以达到50帧,所以说这一块优化性能与我们在整个大场景的渲染也是很有帮助的。

好,下面这张图。大家不知道有没有发现什么问题。

这是一个在屏幕空间AO的效果,当我们的视角由俯视变视到平视的时候,它的这个柱子的AO会发生一个很奇怪的一个现象,为什么会产生这样的效果?我们来分析一下,当我们比较俯视的时候会发现柱子边上的AO ,它的屏幕空间产生的AO的原理,其实基于一个屏幕深度图的这么一个缓存计算,也就是说它会比对当前物体前后的像素,谁深度更深一点,当两者的深度差值如果小于AO的采样半径的时候,那就会被认为前方物体对后方物体产生了一个环境的闭塞,产生了AO。

正因为我们是俯视的角度,所以说这样的话它的深度的差值的对比也是比较小的,这样电脑就会误认为是这个杆子离这个地面比较近,从而产生了这么一个错误的效果。

如果我们把它的视角稍微平视一点,这样你就会发现它的这个出错的现象会稍微好一些。这其实也是因为,当这个角度看上去的深度的时候,它差异性会比较大,当它超出了我们的这个采样半径以后,相对来讲这样的一个被误认为遮挡的AO关系,就随之而减少。

这个就一目了然了,这就是光线追踪的AO,它基于物理运算,所以说你会发现它呈现的AO的效果是非常正确的。

好,下面一张图。也是一个我们之前经常会遇到的屏幕空间AO的问题。

红色箭头所指的这个区域,大家看到它是没有任何AO的效果的,它之所以没有任何AO的效果,其实就因为它上方的这块板子的底面,现在因为看不见,因为看不见以后它不被渲染,那么它的深度信息也没有办法被画出来,那这样自然就不能对地面产生AO的影响。

而反之在光线追踪的AO下面,这块所有的计算是比较基于真实的。

下面我们来聊一聊,光线追踪的一个阴影。

那么现在在,光追被关掉的情况下面,角色它的投影来自于一盏光,这盏光我们采用的是CSM的一个投影,我们把contact shadow其实已经开了,但尽管如此我们会发现,在他的衣领上包括他的衣服上面,依然没有明暗关系,显得这个衣服是浮在人身上的,包括眼镜周围都没有一些立体的这种感觉。

这是一个光追开了以后的效果。首先他的这个衣服和身上的这个内衣之间的半影效果非常真实,包括他的颈部、颈部的衣服,尽管它的厚度很薄,但我们依然很清晰地会看到它的一些投影,投在颈椎上面,包括整个眼镜这一块都显得非常自然,接近于我们真实的效果,这就是基于光追的一个阴影,所呈现出来的投影和传统投影 之间的一个区别。

好,下面这张图,这是一个场景的截图。

这个铁丝网是用Alpha test 贴图制作的,我们在绿颜色箭头这块会发现几个比较奇怪的现象。第一个就是当它左侧这个箭头,明显处于一个阴影的暗部,但是在它的背面依然是比较亮的,没有被阴影所覆盖,中间这个绿色的箭头类似于像一个门框的结构,但其实它的投影的位置并不是特别的准确,最后就是右侧这个投影,之前也提到,随着光源和阴影距离的远和近,它应该在真实世界当中有一个半影现象的。

那么可以看到,如果我们采用了RT的效果,它之间的这个对比还是非常巨大的,不论是阴影里面的铁丝网,还是阴影投射的距离,包括近处和远处的阴影的半影效果,都非常真实。

这块是一个场景,我们是在一个灯光模式下进行的一个截图,中间绿色框的一个区域我们现在使用的是CSM的投影,这块我们可以看到它暂时全部覆盖于整个阴影下面,没有任何细节,但其实你要仔细去看一看就会发现它的上方,其实还是有很多类似于像脚手架这么一个结构。

所以说只有在RT的情况下,当它被开启之后这块的细节会比较精确并且细致地被投影出来。

除次之外我们在用传统的CSM阴影的时候也会出现,我们现在看到的一个常见问题,就是当我们的视角和影子距离过大的时候,CSM的影子由于性能上面的考虑,它会被切换成精度比较低的一个Shadow map,这样的话它的影子的精度就会降低并模糊,但是从我们现在的视角看上去,它就会在这个集装箱的内部产生了一种漏光的现象。

而RT这块就是呈现得非常精准,因为基于物理的运算。有的时候我们也会说我们CSM可以把精度提高,这样也是可以的,但是首先这就牺牲了性能,所以实际在游戏当中,我们是要在视觉上和性能上去找一个平衡点。

下面我们介绍一下光追的GI。

目前是一间简单的小房子,里面放了一个绿色的球。目前这个效果我们没有开RT。整个场景里面它只有两盏光,一个是sky light的天光,包括一个directional light的直射光,通过这张图我们会看到,整个室内的效果是很平的,因为它的一个漫反射并不能很好地被遮蔽,所以这样看起来的这个场景就会显得比较缺乏体积感,会比较平一点。

这是开启的一个RTGI的效果,和刚才这张图大家可以看一下,我觉得是天壤之别,所以有GI和没GI真的差了很多。

GI这张图我们可以切换到灯光模式下去看一看。

首先它在室内会产生一个漫反射的一个遮蔽,体积感瞬间就出来了,同时我们中间这个球之前是有绿色的,光追经过它的一次反弹,二次反弹之后,它会把球上面的一些颜色,带到周围的一些墙壁或者地面甚至天花板上面,那右下角的这个参数,大家可以看一下,我们现在使用的这个Bounce也就是它的反弹,其实是两次,两次已经可以达到这样的效果了。这块我要说一下,就是我们在实际项目中并没有采用RTGI,第一个原因是我们整个开发的团队自己本身有一个动态的GI的一个系统,第二个是动态GI开起来以后,我们需要面对的最大问题还是一个性能问题,如果我们的性能不能满足,那么我们可能会降低它的质量,但降低质量以后它的RT的GI会有一些噪点产生,这样也就是为什么,我们暂时没有在项目当中直接使用RTGI的原因。

下面第三块其实我个人也觉得也是比较关键的一块,关于光线追踪的一个优化。因为如果光追再好,但是不能把它优化到我们需要的一个性能标准,其实在真正的游戏项目里面也没有办法去推广的。

这个场景我们可以看到在它的这个左侧有一面镜子,它的右边有一个纯金属的一个管子,现在我们在这个场景里切换一下它的视角。

这块儿大家可以看到,我们是通过这个镜子来去看它对面的纯金属的管子,这时候我们发现了一个很奇怪的现象,就是管子变黑了,这是为什么呢?

因为大家可以想像我们通过镜子里面能看到管子,首先这已经是光线反弹的一次,那么这也就是我们下方看到的所敲的一个反弹次数的一个命令,当前帧数是在将近于60帧的状态,但是如果我们希望镜子里面的这个金属体,它上面依然有反射效果,这就得二次了,这也就是为什么你现在看到的是一个黑管子。

现在我们把它提到二次,现在金属管子上面的一些细节,周围的一些物体也就被能准确地呈现出来,但是很不幸的是我们会发现它的帧数,已经瞬间掉到了19帧左右。好,我们接着继续增大,它的反弹的次数到三次。

这时候其实画面上可能对比起来跟之前没有太多的变化,但是帧数掉得依然比较可观,现在就是8帧都不到了。

所以通过这么一个简单的演示我们可以得出结论来,在我们使用光线追踪反射的时候,随着它的Bounce的增加,它的性能掉得是非常非常的厉害。样就带来了一个问题是我们如何去平衡这个点?

那这个时候我们可以 在这个管子的附近加一个反射球,让它抓取这个管子周围的静态模型的信息,然后我们可以通过RT的命令,让这个渲染在第二次反弹的时候,采用这个反射球作为一个视觉上的弥补,这样既平衡了我们性能上的不足,同时又带来视觉上的一个比较好的一个体现,所以通过这种方式在很多比如说一些镜子、金属比较多的地方,我们可以用一下。

这个场景也是一个室内场景。我们知道RT其实对于反射这块,无论你反射的Roughenss 是多高多低,Regardless它都会进行一些反弹,但我们可以仔细地稍微考虑一下,如果当我们遇到的这个物体的平面是比较粗糙的,那其实就算它上面有些反射,我们从视觉上带来的体验并不是很大,所以这个时候,我们可以限制一下它最大的Roughness反射的一个值,比如说像这张图上面,我们把它小于等于0.2的Roughness值才认为需要参与到RT的反射当中。

但是这样又带来第二个问题,因为对于一个美术制作人员,他如何能比较精准地知道,哪些地方的材质Roughness是小于等于0.2?是参与到RT的反射当中?

所以这个时候,我们也可以做一个后处理的一个材质,我们把所有小于等于0.2的Roughness的这个区域,把它以这种绿色形式标注出来,这样的话对于美术同学来讲,可以一眼就会知道,我哪些地方是参与了RT的反射的,我需不需要有这么多的地方进行反射,同时这也作为我们性能上的控制,可以很好的预览。

现在大家看到这个图是一个材质的节点的图。因为我们整个项目当中,我们采用了一个母材质的 一个流程,也就是所有的美术人员,他们自己并不需要制作母材质,只要通过TA做好的一个母材质直接生成instance material,直接可以调参数就可以用了。

那这样的话,我们母材质的一些功能相对来讲是比较复杂的比较多的,但是我们可以试想一下,假如说有一个场景我们有一个镜子,然后旁边有一个很华丽的比如说有一个物体,用了非常复杂的材质,比如说一个瓶子的话,这个瓶子用了很复杂的材质,从镜子里面去看这个瓶子的话。

首先第一点反射里面这个瓶子的像素肯定是比较小的,但是如果我们在反射里面看到所有的材质效果,依然是沿用了这么复杂的一个运算的话,其实在视觉上的体验并不能让我们能明显地感觉出来。

这样的话我们就引入了RT Quality Switch的节点,即当我们从反射的物体里面去观察细节的时候,我们并没有让它完完全全以实打实的全节点的运算参与到RT反射当中,我们只给了相对来讲比较简单的PBR的节点,比如像Normal、Roughness、Metallic这样的值,这样就会大大精简我们的一个运算效果。

这边是有个例子,目前在这个镜子前面站着三个角色,我们仔细可以看一下,角色的衣服上面增加细节,我们叠了一些细节纹理,此时此刻我们的RT的Quality Switch并没有开启是关闭的,所以说在镜子里面这些黄颜色的衣服上面,它也是有这些细节的纹理呈现的,但这个时候,我们会看看整个光线跟踪的反射所需要的毫秒数是在4.46毫秒。

当我们开启了RT Switch以后,我们把反射里面的黄色衣服上面的细节材质就直接干掉了,不需要再去渲染了,所以说从画面上面来看并没有太大的差异,但这个时候它的RT反射所需要的毫秒数降低到4.1毫秒。今天仅仅是一个小的例子,我们可以想象出如果所有的母材质都应用了这些RT Switch的优化节点,在很多大场景中会提供我们很多性能上的优化的节省的资源。

这块就是我们用的蓝图,把蓝图上面经常需要用到的有一些RT的一些参数,预设到这个蓝图里面。

然后我们可以把这个蓝图以Volume的形式,以体积框的形式放到两个不同场景的一个交界处,比如像这样一个室内和室外的这么一个区域,因为室内和室外,首先它的光照信息不太相同,同时它内部摆放的一些物体的结构、密度、材质也有可能差别比较大,我们通过这样的一种形式,就可以在不同的环境下,切换两种不同的RT的优化参数,这样就会得到整个游戏性的平衡,同时也能满足视觉上的效果。

最后这块就是列举了,项目当中常用的一些RT优化的方式 、命令、参数。总体说来优化这块你得牺牲可视化的细节来换取性能上的提升,然后最后去寻求两者的平衡点。

我觉得无论是光线追踪还是我们传统的光珊化渲染,他们的目的其实都是为了将很好的画面带给我们,但是自从我们采用了光线追踪以后,这将为我们打开一个通往真实世界的大门。以上就是今天,我给大家带来的一些分享。

Q&A:

Q:光追研发过程当中,遇到的最大的技术难点是什么?

A:这个问题问得非常好,因为我们在整个光追的研发当中,其实也踩过很多坑,遇到很多问题。总体来说我觉得还是如何去减少这个性能的开销是最大的技术难点。因为说直白一点光追就是实打实的真实地去模拟现实中的一些计算,但矛盾点在于我们的显卡,我们的PC 我们的整个需要加载的这些资源,都不可能无限制地被放大,我们还是要寻求良好的性能,这个时候我觉得最重要的一点,首先在一个游戏设计的初期应该就要知道,如果我们采用了光追,我们哪些环境和哪些场景需要迎合它?展现哪方面的一些优势?那么我们为了这个优势而要去设计对应的情景来去展现,同时这样也便于我们后期的一些渲染。这块就是光追的一个我们研发当中会比较大的一个难点吧。当然我相信随着硬件的开发,包括引擎不断的提升,包括技术不断的去发展,这个过程也会不断地去迭代的。

Q:光追应用到移动端有哪些适应性?

A:确实很多移动端的一些游戏也会尝试使用一些光追,我们可以想到的是有类似于light probe这种东西,我们可以用光追进行加速,因为它也是一个类似于像离线烘焙,可以通过光追进行一些加速。第二个是我们在烘焙比如像light map,这样通常手游都会使用的手段上面,我们加入了RT,除了RT可以帮我们加速以外,它也可以帮我们进行一些实时预览,这样的话就可以在实时的状态下面,我们会看到在烘焙light map这个过程中,哪些地方烘焙得不好的,我们可以直接把它暂停掉,重新调参数,重新去渲染,而不用像以往那样要等整个light map烘完以后,才发现这儿不行那儿不行,其实这也是一个很痛苦的一个过程。

那今天问答环节就是这些,最后谢谢大家。

如若转载,请注明出处:http://www.gamelook.com.cn/2020/12/408495

关注微信