AMD王文涛:如何在Unity里做VR渲染?

QQ图片20170117210519

来自AMD的VR内容开发工程师王文涛为开发者们整理了一份VR渲染指南,其中包括渲染方面的基础知识,并详细介绍了在Unity里面怎么去优化它的效率。希望大家看完这份指南后,使用Unity开发的时候能够有一个全局上的了解和判断。

自我介绍一下,我叫王文涛。我从研究生开始就是研究关于图形学和渲染。渲染对于游戏开发、包括VR其他内容的开发也是非常重要的议题。打个比方,你做房地产展示类的应用,那么渲染就是一个非常重要的点,房屋内的光照,日夜之间的切换,这是你应用的一个杀手锏。

但是,在现在的VR内容开发中,还没有很成熟的解决方案。特别是针对Unity开发者,大家都知道,虚幻引擎有比较好的效果,可以做出电影级别的画质,但很大部分的开发者使用的是Unity开发,包括我自己。Unity的效果大家都知道不太完美,那么我们在使用Unity的时候,不能因为它渲染效果不好,我就去做一个不完美的东西。这样不行,因为你的产品最终是要跟别的引擎做的东西去竞争。

所以,我今天来讲的就是渲染方面的基础知识,和包括在Unity里面怎么去优化它的效率,一些指南性的东西。这样主要是为了大家在之后使用Unity开发的时候能够有一个全局上的了解和判断。比如说,为什么我的游戏运行的这么慢?为什么我的帧率这么低?或者为什么我想要的画面和游戏运行出来的画面差的这么多呢?到底是我的全局光照出了问题还是说我的抗锯齿有问题?

我今天想要分享的就是这个东西,大家在听完我讲的东西之后能够对渲染或者说对图形学有一个基础的了解,能够自己去分析一些图形学相关、或者渲染相关的一些问题。

在开始之前,我想先给大家看一个Unity做的电影。它和传统电影制作流程不一样,它其实完全是在引擎里实时运行的。这个也是Unity做出来的效果,它的效果质量会这么高,我们应该怎么去达到。先看完,我们会逐步去分析它。

我们可以看到的是,首先这个机器人的材质非常的真实。金属的高光、地板上的反射。反射在我们生活中很常见,但在游戏引擎里是比较难实现的技术,不管是实时的还是烘培的反射。但它使用一些特殊的技术去实现反射的技能。我们看到这个过道光很自然,你自己在使用Unity开发的时候,打一个普通的面光源或者点光源,很难做到这么自然的光照。这个就是它在这里面使用了全局光照的技术,或者叫做间接光照。他这个影片主题其实就是说Adam是人类创造出来的亚当,这些机器人是人类的造物,或者说人类成为了上帝,这是我自己的理解。

大家看到那个电影很酷炫,有一种电影级的画质。当然我们不考虑显卡因素,因为刚才放的那个电影是用三块GTX980去交互渲染的。因为VR现在很多的开发者也有1080或者我们AMD的FURY X,Fury Nano这种级别的显卡。假如你有一块这么好的显卡,你怎么做出一个非常牛逼的画质呢?

“怎么理解渲染”

对我来说,我怎么去理解渲染?首先,当然是性能。你在某个固定的平台上必须要达到一定的帧率。就是说,你看起来至少每秒得能够有75帧,必须要达到90帧才不会晕眩。再一个是你必须要满足你游戏设计艺术家的要求,这个并不是说我特效堆的越多越好,或者说我做出来的渲染越真实越好,越接近现实就越好,并不是这样。比如说,你的游戏风格可能是水墨风格,可能是美术风格。但是你同样的用现有的技术去把它做的非常漂亮,这个是一个很好的渲染系统所必须拥有的特性。我们大家想到的现在比较优秀的作品,比如说《使命召唤》或者说《战地》,为什么它们能够在PS4上跑的这么优秀的效果?除了美术很牛逼之外,他们也使过非常多的光照上、贴图上、建模上的这些技术去实现这些东西。

然后我们讨论到了,在VR里面,这些渲染实现会更加的难。因为大家都知道,VR是两只眼睛,通过左右眼的视差去产生立体感。首先我至少要渲染两个runnertarget,也就是说两幅图像。再一个是大家都知道,HTC的分辨率是2k,Oculus的分辨率也是2k以上。那么,平常我们使用的PS4或PC上的分辨率1080p已经非常高了。现在你渲染的分辨率要2k,然后两只眼睛,同时你的帧率还不能说我只达到60FPS,我必须达到75FPS或者90FPS。在这种情况下,你必须要牺牲掉一些效果。甚至说,你要牺牲掉很多效果去达到基本的性能要求。那在这个情况下,优化就显得非常重要。

还有一个比较重要的因素,就是说我们在VR里眼睛离屏幕非常近。同时,我们的眼睛一直在运动的。那么,我们平常在用电脑玩游戏或者手机玩游戏的时候,一些比较不明显的画质上的差异它就会体现出来,特别明显的就是锯齿。大家知道,玩游戏比较多的人知道有个名词叫“狗牙”。比如说一个非常细的多边形,我看上去会有一段一段一段的“狗牙”,或者说一块金属反射的高光,我在玩的时候它会不停的闪烁,就会让人感觉画面很不稳定。而在VR里面这种情况更加的严重,也就是我们通常说的抗锯齿会变得更加的重要。

“怎么解决性能上的问题”

我们先讲一下,怎么解决这些性能上的问题。首先,一个比较自然的想法就是说我们能够把要渲染的图像变得小一些。那么怎么变的小一些呢?其实大家一个很明显的优化思想就是,我们的渲染并不是说我两幅图都是2k的图片,并不是要把这2k全部渲染出来,因为我们现在的头显是有FOV的,它在边缘是有畸变的。也就是说我们完全是可以只渲染中心一部分的图片,而并不是说我把整个图渲染出来。也就是说我们用一个遮挡的Mesh去把不需要的像素点剔除掉,对你真正的体验来说不会有任何影响。

QQ图片20170117210708

我这里弄一个例子,这个Demo其实大家很熟,这个就是Valve公司做的《The Lab》的Demo。它在这里面就讲到,用一个圆形的Mesh去保留所需要的像素。边缘哪些黑的我在VR头显里面,或者说我在HTC Vive或Oculus里面不需要的这些像素。它测算出来的结果是,我通过这个我能够把17%的像素去剔除掉。这是一个比较自然的想法。

还有一个类似的想法,就是说像素的着色或者说像素的渲染,是GPU里面损耗最大的部分。那我们能不能把这些像素不要再去扔掉呢?其实最简单的一个思想就是说,我们人在看东西的时候是有一个焦点的。打个比方说,我现在看到的这块屏幕,我的眼睛会集中在这块屏幕上。我不可能去太多的关注周围的窗帘、包括这块广告板,那我们是不是说,我们可以把更多的GPU的效率提供在这块板(焦点)上而不是我们同样的渲染整个视场中的,包括这边和这边的物体。

其实这就是一个非常简单或者说非常直白的叫做Foveated Rendering,就是注视点渲染技术。传统的渲染流水线中,我们会把三维空间的物体投影到屏幕上,然后我们去算我们每个像素都一个一个地按部就班的去着色。实际上在VR里面,它还真不是这样。因为在VR里面我们有注视点,可能说我们只看中间的那一小部分,而并不是说我们对整个的画面中的像素都是一视同仁的。所以说,有一个非常简单的实现技术,固定的注视点渲染,它并不是说我们需要实现眼球跟踪那么复杂的技术。

比方说,我在看的时候,我的眼球会往这边看或者往那边看。那我们做一个最基本的假设,就是说我的眼球总是看着最前方,然后我们通过一个算法去把周围像素着色的密度去降低,那我们就可以提高很多的效率。这里说的GameWorks VR,也就是英伟达推出的关于VR渲染的技术里面,也用了同样的思想,就是Multi-resolutionshading。这个思想其实是一样的,它就是说我也假设我的视点永远是在画面最中心,然后我把画面分成大概9个区域,分别按不同的着色密度去渲染。我看过官方的数据,这个Multi-resolutionshading能够提高15%或者20%的着色效率。

QQ图片20170117210718

大家其实可以看到这个图,这就是一个最简单的实现。绿色的mesh里面所能够看到的像素,我以正常的密度去渲染。蓝色的我以,打个比方说,0.5%或者50%的效率去渲染它。这样就能节省很多的时间。

还有一个比较浪费的就是,在VR里面你要渲染两遍,左眼和右眼。其实很多东西是不需要渲染两遍的。最基本的就是说,和灯光有关的东西,你根本不需要渲染两遍。比如说Shadow map,也就是阴影。因为,阴影是跟灯光有关的,和摄像机的位置无关。你的两只眼睛不管距离多大或者是差异性有多大,它都是一样的。还有一个比较值得研究的就是,比如说漫反射,高光我们可能在两个眼睛里面会有很大的区别,但是漫反射其实区别比较小。再一个就是说,比如说很多的后处理的特效,比如我们的光晕、HDR高动态范围,这个特效其实都不需要渲染两遍。

所以在这里我就推荐,基本上大家在做VR开发的时候能够用Unity 5.4,它在5.4里已经开始对这些东西做了一些优化。如果你用5.3的话,可能效率还是要低一些。我想在坐应该用Unity的会比较多一些,因为可能团队规模都不是很大,所以我推荐大家尽量用5.4,虽然现在还Beta版,我记得是出到b22了吧,它在这方面会有一些逐步的优化,能够省去你不少的时间。

QQ图片20170117210508

然后我再讲的这个科技就是刚才说的锯齿(问题),这个东西在VR里面会是一个非常严重的问题。大家都知道Unity里面摄像机可以设render pass,包括有前向渲染Forward Rendering和延迟渲染Deferred Rendering。在VR里面我们怎么去选择这个呢?因为你在做一个小游戏的时候,你可能根本不会care这个东西。我用前向渲染和我用后向渲染,我的显卡都是能够满足目标的。但是,我在这分析就是说前向渲染,它有一个天生的好处就是能够在硬件上支持MSAA。就是在我们玩游戏的都会知道一个选项,如果你去把《使命召唤》或者这样游戏里的图形选项打开,它有一项就叫MSAA。那MSAA实际上是显卡里它用硬件算法去支持的。如果你用前向渲染,它天然就自带了一个MSAA的效果,锯齿问题就不是那么严重。但后向渲染其实就是一个非常尴尬的事情,因为如果游戏玩的多的可能都知道现在有抗锯齿的FXAA,其实是基于一个图像分析,他这个图像分析在VR里面用处并不是很大,或者说你即使加上了对于锯齿的改善并不是很明显。

所以,这回我向大家推荐Unity里面非常强大的插件。就是做VALVE,它放出来叫做Lab Renderer。其实是VALVE的工程师在做The Lab这个Demo的时候,他去想到的这个事情。如果你了解过他们在GDC上的演讲,你就会说TheVALVE也用Unity做开发,他为什么不用Unreal呢?因为VALVE做的《半条命》《DOTA2》,大家都知道是非常高端、特效非常好的游戏。为什么它要用Unity呢?他们工程师就说了一句:“我们发现用Unity的团队,大部分都是小团队,而这样的小团队里面是不可能有一个人去专门研究图形,专门研究画面效果的,所以我们去专门研究这样一个插件叫做The LabRenderer的技术。”目的就是说能够帮助像我们这样的小团队去实现一个还不错的渲染效果。

我随便截了一张图,因为我本来是想把我的电脑带上来给大家看的,但是这边其实不是很好使用自己的电脑。我就先截张图给大家看一下,这个渲染其实特别容易。

QQ图片20170117210634

它就是一个最简单的一个pass forward renderer前向渲染器。然后它能够最大的支持16盏动态光源。我想16盏动态光源对于绝大多数游戏或者非常复杂的应用来说都是够用的。它最大的特点就是说MSAA,它能够天然支持MSAA,所以你刚才那张图看到的锯齿是非常不明显的,非常有用。它天生就自带了我放刚才说的那些注视点渲染、像素剔除这些技术。它相比Unity默认的渲染,你使用它渲染会有非常好的效率上的提升。

但然,它也有一些限制,它必须用它自己的Shader。比如说你在Unity用惯了标准材质,或者你自己买的一些Alloy Shader,贴图就要重画或者重新连接材质的节点。肯定是有一些限制,你用这个插件需要你去做一些修改。如果说你项目并不是很大,我非常推荐使用这个东西。去学习一下它的流程,一个是对你自己,对整个团队的图形学知识是个很好的。因为它整个代码是open source,在asset store上,搜The Lab Renderer就可以下载,不需要掏钱。再一个就是说,你不用花时间去纠结一些比较基础的。比如Unity没有注视点渲染、没有像素剔除的技术。那你看一下用Unreal开发的,天生就自带Gameworks VR,人家做出来为什么这么快。你自己如果要花时间去写,花时间去研究,这就是一个非常大的工程。所以VALVE给你搭的这一套东西就节省不少的时间。

然后我在这里又讲一下,前向渲染对于我们来说并不是一个非常完整的解决方案。特别是MSAA对于比如说高光的锯齿并不是能够解决的很好。那么我们在Unity里面是不是有别的更好的技术去解决它。我在这里写的前向渲染对于多光源并不是非常有效率,包括刚才说的,可能只能支持16盏光源,再多它的帧率会下降的非常快。即使是支持到16盏光源,它肯定也并不推荐你完全的用满它。再一个是说,比如说,我们很想使用一些特效,比如屏幕空间反射。我们刚才在电影里看到的,机器人在地面的反射很爽或者说很漂亮。但这个东西对于前向技术它就没有办法实现,因为屏幕空间反射需要用到屏幕的几何信息,那怎么办?那我们是不是有一个更好的方法。

QQ图片20170117210620

还真有。大家想一想,我们做电影和做游戏的区别是什么?做电影其实是一个追求质量的过程,做电影我一帧可以渲染1个小时、2个小时。但做游戏,或者说做VR内容开发,我们需要的是效率,一帧最多是十几毫秒。如果你超过20毫秒,那这一帧基本上完蛋。所以说,电影上的一帧,我可以一直算,一直渲染下去,直到它收敛为止。

那么,渲染在图形学里面其实就是一个不停采样的过程。而抗锯齿根本的来源就是,我们一个渲染的图像,它缺少信息,大家如果是工科或理工科出身的,就知道“奈奎斯特采样定理”。我的采样频率要高于我最高频率的两倍,我就能完整地恢复出我需要的信息。在渲染这个领域其实也是一样。打个比方说,我们大家都知道,最简单的抗锯齿的方法是什么?你渲染一张2k的大图,你把它缩小到1k,那这张图肯定锯齿非常少。为什么?因为这相当于我们对1k的图的每一个像素做了四次采样。但是实际上,你真的去渲染一个2k的大图,那么我们VR有2k我可能就要去渲染4k,你这样去抗锯齿显然是不行的。后来,于是就有聪明人说,游戏最大的特点是连续性,那如果我能够找到每帧之间相同的像素,那我就能在时域,也就是说很多帧之间去做个采样。那不就实现了个超采样,也就是所谓的Super Sampling。有的时候大家在数据信号处理的课里面,提到这个Super Sampling。这个能够很好的提高画面的质量,最关键的是这个很便宜,或者说并不是很好,当然它的实现难度是有的。

我给大家看一个具体的例子。这个Demo挺有名的,使用虚幻引擎做的。这个是没用时域抗锯齿的结果,大家看到最大明显的特点是闪。因为,整个画面高光的东西太多了。如果说你不用抗锯齿,画面会非常不稳定。这个地方会特别的闪。

我们加上了时域抗锯齿的结果,是什么?最大的特点就是整个画面非常稳定,这样看起来是不是就有电影级别画质的感觉。画面稳定、像素没有任何瑕疵,包括在高光的地方也不会闪,非常的稳定。这个非常复杂的glossy的地面,我们现在就可以看的非常明显。
我问一下,今天大家主要都是学生,还是硕士研究生,还是什么?大家有过VR开发经验的可以举个手吗?玩过的可能比较多,有过的可能还比较少。如果大家选择开发工具,真的会从Unity中简单易学的工具去入手。

我刚才说的Temporal AA一样的,在asset store上也可以找到一个还不错的实现。也是今年GDC上还会有一个Talk,我不知道大家知不知道limbo这个工作室。大家可以去搜limbo的taa。能够得到非常不错的Temporal AA,也是直接在GitHub下载就可以了。我想跟大家提,就是说大家擅于利用这些包括GitHub、Asset Store这样的插件使我们的开发提升很多的效率。比如说,又跟我刚才说的一样,Unreal的抗锯齿就非常的棒,非常牛逼。Unity就不去做了吗?不可能。如果你想做很牛逼的东西,你必须要擅于利用这些前人已有的资源。

然后,我再讲全局光的问题。全局光问题历来是游戏里比较头痛的问题,特别是在VR里面就会更麻烦。然后,全局光照其实就是说,什么叫全局光照?比如一个灯打到一块黑板上或者地板上,它投下来的影子那是直接光照。但如果它在地板上反射出去的光线照亮了其他物体,那这个就是全局光照。全局光照一般是通过烘焙,也就是离线的方法把全局光照存成某种数据结构,在游戏实时运行时调用去实现的。但在VR里面对于实时的运算是要进行严格的限制,所以我不推荐大家在VR里面使用实时的全局光照技术,比如说提速、mpv这种技术。我建议大家老老实实用标准的光照贴图,也就说烘焙一张贴图然后贴上去。

但是,Unity又是一个非常麻烦的问题,Unity自身所带的enlighten的烘焙,它其实不是很好调出非常好的效果。我想大家可能都看过Unreal的一些作品,比如说Unreal做的室内装修,为什么室内装修企业,包括今天赞助的51VR,为什么他们都会用虚幻引擎去做室内装修呢?一个最大的原因,室内装修对于全局光照的要求非常高,Unity是达不到的。如果你是用Unity做东西,你如果真的用enlighten去调一个非常好的全局光照,难度很大或者说几乎不可能。

QQ图片20170117210519

所以,我推荐大家尽量去使用另外的烘焙工具,比如说vRay,这个大家比较熟悉的。如果说有做美术的,或者说有做建筑设计的应该听说过vRay,这个就是一个比较不错的工具。当然,你把它导进Unity里面是需要耗费一定的工作量,但是这个比你去用它自带的烘焙工具要好一些。我们这边也做过尝试,如果你真的去用比较优秀的烘焙工具的话,Unity做出的室内设计或者室内展示的质量是不会输给Unreal。

这边我想到了一些就是屏幕空间的技术,大家都知道屏幕空间的技术关键就是在于快,缺点就是精度不够。比如Unity自带的SSAO这个就是一个非常好的实现,但在asset store有HBAO或者是别的AO技术,大家都可以试一下。我建议大家能用就用,在你的硬件够的情况下,因为本来你的全局光很矬的情况下,你没有这些AO补偿的话,画面会比较挫。再一个就是屏幕空间反射,屏幕空间反射现在在5.4的beat版里面官方已经有了,其实你们只要在相机上加上imagine facts里面就会有这个。当然实现的屏幕空间发射在Unity 5.4实现可能不是那么完美,但其实它已经是够用的。如果你的场景里有非常多的金属物体,或者说非常多的镜面,使用反射的话会大大增加你视觉上的观感。打个比方说,我是在一个很空旷的金属竞技场里面,甚至说我只要有空间反射的技术我可能不需要GI,我就能给人一种非常好的视觉上的表现力。

说了这么多,我觉得其实就是你优化还是那套方法。大家都知道的,简单说减少drawcall、减少DC、batching。

Unity的batching这个东西是一个老生常谈的话题,在百度上一搜,在谷歌上一搜会有很多这样的。怎么去batching?在场景里怎么去batching?在VR里面,只是对你的要求会更高一些。比方说,我听过一个讲座,如果大家可能玩过《Gunjack》就是在GearVR上实现的游戏。它对drawcall这个东西限制就非常严,它每只眼睛的drawcall不能超过50。所以,不管你是开发HTC或者是开发什么样的应用,drawcall、batching这些东西一定要非常的注意。就是说你不能无限制的堆你所需要的东西,而是说你做一段时间,你可能就要运行一下。你去用Unity的工具去看一下,我现在这个场帧率是多少?我到底在哪里耗的特别快。

QQ图片20170117210508

还有一种比较好的方法就是说,实在不行就按艺术家的方法去画。打个比方说,bloom光晕特效,这个东西大家都知道Unity里面有shader自带,但是这个占的时间。如果你是做移动平台的,你可能知道移动平台后期处理的效果是非常占时间,那怎么办?直接美术画上去,这也是非常行之有效的方法,当然也考验你美术的能力了。

再一个,我推荐就是多去测你游戏的性能。包括professional unity 5.4里 也已经是比较完善的一个东西。那么你多去测性能,你多去了解你游戏的瓶颈,bottleneck在哪里。是我shader太多了还是说我某个特效真的不该用。不要在编辑器里测,最好是打个光。

我最后说,渲染这个东西,就是说有一个自我的评估。当然我知道现在的很多团队是不会专门的去有一个程序员、或者专门有TA技术美术去关注这一块的。但是我想说的就是,希望大家能够去多考虑一下。比如说,你所需要的特效的特点是什么?比方说,如果做的是一个机械的大战,你可能非常需要反射,所以你可能就会去使用一个屏幕空间反射的特效在Unity 5.4 beta版里面会有。再比方说,你做的是一个互动电影,那么你对画面的要求会非常高,那么你的抗锯齿就要做的非常出色,那你只能使用时域的抗锯齿temporal AA,我刚才说的那种方法。就是说,具体的方法,具体问题具体分析。

就是说渲染这个东西,永远不是一成不变的。它不是说我像电影渲染一样,我只要渲染的够真实或者说我只要去模拟每一根光线的运动轨迹,我就得到一个非常完美的图像。关键我们在游戏里面,根据我们的美术风格去做出妥协,根据我们的性能去做出妥协,所以这是一个永远会谈论下去的话题。就是说你很难去说,我某个引擎特别牛逼任何游戏都能做。即使是效果这么好的虚幻引擎,它也很有可能也有做出来帧率非常低的情况。如果你不懂,不懂删减特效的话,你最后很有可能遇上非常大的麻烦。Unity可能就是它的帧率并不是一个很大的问题,但是它的效果同样是个很大的问题。如果你不懂得怎么通过各种各样开发,包括shader的技巧去加特效的话,也可能很难做出非常优秀的作品。所以,我希望大家能够多讨论,有问题就提出,包括最后大家能够建立一些自己的library或者open source library,去提高整个VR社区开发者的质量。

打个比方说,今天我这边有个很好的抗锯齿的实验,我去把它分享出来,大家在Unity上都可以使用。那么大家整个的开发质量就可以提高了。我们AMD也在做非常多的图形学的研究的东西和Demo的东西。所以,我们对质量要求和效率要求肯定非常高的,我们只要有成果,会第一时间的分享出来帮助大家的开发。后面还有导师会讲特效的应用和一些开发的实战,大家也可以更好更深入的去了解。我这个渲染是指南性质的东西,大家可以去更深入的了解怎么去开发一个游戏。

谢谢。

(本文来自VRCORE)

QW

更多精彩内容,关注青亭网微信号(ID:qingtinwang),或者来微博@青亭网与我们互动!转载请注明版权和原文链接!
责任编辑:freeAll
分享到QQ 分享到微信

0 条评论

头像发表我的观点

取消

  • 昵称 *
  • 邮箱 *
  • 网址

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册