VR画面渲染性能是这样提升的

转自:https://blog.csdn.net/mryu9958/article/details/78212349/

 

本文您将了解到:

1,VR渲染面临什么问题?

2,如何做好VR的渲染?

3,怎样提升VR渲染的性能?

渲染对于VR内容的开发来说,是非常重要的议题。

但在现在的VR内容开发中,却还没有成熟的解决方案,特别是针对Unity开发者。

近期,VR价值论在VRCORE公开课上找到一份VR渲染指南。

包括渲染方面的基础知识,以及在Unity里面如何去优化渲染的效率。

废话不多说,直接上干货吧,内容较多,建议收藏。

VR画面渲染性能是这样提升的_第1张图片

 

研究生开始,我一直研究图形学和渲染。

渲染对于游戏开发、以及现在VR内容的开发来说是非常重要的议题。

打个比方,你做房地产展示类的应用,那么渲染就很重要,房屋内的光照,日夜之间的切换,这些都需要渲染,做的好的话,将成为让你的应用脱颖而出的杀手锏。

不过,渲染虽然重要,在现在的VR内容开发中,却还没有成熟的解决方案,特别是针对Unity开发者。

大家都知道,虽然虚幻引擎效果比较好,可以做出电影级别的画质,但很大部分的开发者还是使用Unity开发,包括我自己。

Unity的效果不太完美,不过我们不能因为它渲染效果不好,就去做一个不完美的东西。这样不行,因为你的产品最终是要跟别的引擎做的东西去竞争。

所以,我今天来讲的就是渲染方面的基础知识,和在Unity里面怎么去优化它的效率,一些指南性的东西。

这样主要是为了大家在之后使用Unity开发的时候能够有一个全局上的了解和判断。

比如说,为什么我的游戏运行的这么慢?

为什么我的帧率这么低?

或者为什么我想要的画面和游戏运行出来的画面差的这么多呢?

到底是我的全局光照出了问题还是说我的抗锯齿有问题?

在开始之前,我想先给大家看一个Unity做的电影。(视频见文末视频1。)

它和传统电影制作流程不一样,完全是在引擎里实时运行的。

这个也是Unity做出来的效果,质量很高,接下来,我们会逐步去分析它。

可以看到的是,首先,这个机器人的材质非常的真实。金属的高光、地板上的反射。

反射在我们生活中很常见,但在游戏引擎里是比较难实现的技术,不管是实时的还是烘培的反射。

但它使用一些特殊的技术去实现反射的技能。这个过道光很自然,你在使用Unity开发的时候,打一个普通的面光源或者点光源,很难做到这么自然的光照。

这是因为它在这里面使用了全局光照的技术,或者叫做间接光照。

影片主题其实就是说机器人是人类的造物,或者说人类成为了上帝,这是我自己的理解。

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

假如你有一块这么好的显卡,你怎么做出一个非常牛逼的画质呢?

怎么理解渲染?

性能

有两点要求需要满足。

• 在某个固定的平台上必须要达到一定的帧率。

就是说,看起来至少每秒得能够有75帧,其实必须要达到90帧才不会晕眩。

• 必须要满足游戏设计艺术家的要求。

这并不是说特效堆的越多越好,或者说做出来的渲染越真实越好,并不是这样。

比如说,你的游戏可能是水墨风格,可能是美术风格。你用现有的技术把它做的非常漂亮,这是一个很好的渲染系统所必须拥有的特性。

我们想到的现在比较优秀的作品,比如说《使命召唤》或者《战地》。为什么它们能够在PS4上跑出这么优秀的效果?

除了美术过硬之外,他们也使过非常多的光照、贴图、建模上的技术去实现效果。

当然,在VR里面,这些渲染实现会更加的难。

因为大家都知道,VR是两只眼睛,通过左右眼的视差去产生立体感。

首先,至少要渲染两个runnertarget,也就是说两幅图像;

其次,平常我们使用的PS4或PC上的分辨率1080p已经非常高了,现在渲染的分辨率要2k(HTC的分辨率是2k,Oculus的分辨率也是2k以上),两只眼睛,同时帧率还不能说只达到60FPS,而必须达到75FPS或者90FPS。

在这种情况下,你必须要牺牲掉一些效果。甚至说,你要牺牲掉很多效果去达到基本的性能要求。

在这个情况下,优化就显得非常重要。

锯齿

还有一个比较重要的因素,就是我们在VR里,眼睛离屏幕非常近。

同时,我们的眼睛一直在运动的。

那么,我们平常在用电脑玩游戏或者手机玩游戏的时候,一些比较不明显的画质上的差异它就会体现出来,特别明显的就是锯齿。

玩游戏比较多的人知道有个名词叫“狗牙”。比如说一个非常细的多边形,我看上去会有一段一段一段的“狗牙”,或者说一块金属反射的高光,我在玩的时候它会不停的闪烁,就会让人感觉画面很不稳定。

而在VR里面这种情况更加的严重,也就是我们通常说的抗锯齿会变得更加的重要。

怎样解决性能上的问题?

我先讲一下,怎么解决这些性能上的问题。

减小渲染图像

首先,一个比较自然的想法就是把要渲染的图像变得小一些。

那么怎么变的小一些呢?

一个很明显的优化思想就是,渲染并不是说两幅图都是2k的图片,并不是要把这2k全部渲染出来,因为现在的头显是有FOV的,它在边缘是有畸变的。

也就是说我们完全是可以只渲染中心一部分的图片,而并不是把整个图渲染出来。

用一个遮挡的Mesh去把不需要的像素点剔除掉,对你真正的体验来说不会有任何影响。

举一个例子,Valve公司做的《The Lab》的Demo。

在这里面就讲到,用一个圆形的Mesh去保留所需要的像素。边缘那些黑的在VR头显里面,或者说在HTC Vive或Oculus里面不需要这些像素。它测算出来的结果是,通过这个能够把17%的像素去剔除掉。这是一个比较自然的想法。

VR画面渲染性能是这样提升的_第2张图片

 

注视点渲染技术

还有一个类似的想法,像素的着色或者说像素的渲染,是GPU里面损耗最大的部分,那我们能不能把这些像素不要再去扔掉呢?

其实最简单的思想是,人在看东西的时候是有一个焦点的。

打个比方说,我现在看到的这块屏幕,我的眼睛会集中在这块屏幕上。我不可能太多的关注周围的窗帘、包括这块广告板。

那是不是说,我们可以把更多的GPU的效率提供在这块板(焦点)上而不是我们同样的渲染整个视场中的,包括这边和这边的物体。

这就是一个非常简单或者说非常直白的叫做Foveated Rendering,就是注视点渲染技术。

传统的渲染流水线中,我们会把三维空间的物体投影到屏幕上,然后每个像素都一个一个地按部就班的去着色。

实际上在VR里面,它还真不是这样。因为在VR里面我们有注视点,可能说我们只看中间的那一小部分,而并不是说我们对整个的画面中的像素都是一视同仁的。所以说,有一个非常简单的实现技术,固定的注视点渲染,它并不是说我们需要实现眼球跟踪那么复杂的技术。

比方说,我在看的时候,我的眼球会往这边看或者往那边看。

我们做一个最基本的假设,就是说我的眼球总是看着最前方,然后我们通过一个算法把周围像素着色的密度去降低,那就可以提高很多的效率。

这里说的GameWorks VR,也就是英伟达推出的关于VR渲染的技术里面,也用了同样的思想,就是Multi-resolutionshading。

这个思想其实是一样的,它就是说我也假设我的视点永远是在画面最中心,然后我把画面分成大概9个区域,分别按不同的着色密度去渲染。

我看过官方的数据,这个Multi-resolutionshading能够提高15%或者20%的着色效率。

还有一个比较浪费的就是,在VR里面你要渲染两遍,左眼和右眼。

其实很多东西是不需要渲染两遍的。

最基本的就是说,和灯光有关的东西,你根本不需要渲染两遍。

• 比如说Shadow map,也就是阴影。

因为,阴影是跟灯光有关的,和摄像机的位置无关。你的两只眼睛不管距离多大或者是差异性有多大,它都是一样的。

• 还有一个比较值得研究的就是,比如说漫反射。

高光我们可能在两个眼睛里面会有很大的区别,但是漫反射其实区别比较小。

• 再一个就是说,比如说很多的后处理的特效。

比如我们的光晕、HDR高动态范围,这个特效其实都不需要渲染两遍。

所以我推荐,基本上大家在做VR开发的时候能够用Unity 5.4,虽然现在还Beta版,但在5.4里已经开始对这些东西做了一些优化。如果你用5.3的话,可能效率还是要低一些。

怎样解决锯齿上的问题?

然后我再讲的就是刚才说的锯齿问题。

这个东西在VR里面会是一个非常严重的问题。

大家都知道Unity里面摄像机可以设render pass,包括有前向渲染Forward Rendering和延迟渲染Deferred Rendering。

在VR里面我们怎么去选择这个呢?

你在做一个小游戏的时候,可能根本不会care这个东西。

用前向渲染和用后向渲染,显卡都是能够满足目标的。但是,我在这分析的就是说前向渲染,它有一个天生的好处就是能够在硬件上支持MSAA。

我们玩游戏的都会知道一个选项,如果你去把《使命召唤》或者这样游戏里的图形选项打开,它有一项就叫MSAA。

MSAA实际上是显卡里用硬件算法去支持的。

如果你用前向渲染,它天然就自带了一个MSAA的效果,锯齿问题就不是那么严重。

但后向渲染其实就是一个非常尴尬的事情,如果游戏玩的多的可能都知道,现在有抗锯齿的FXAA,其实是基于一个图像分析,这个图像分析在VR里面用处并不是很大,或者说即使加上了对于锯齿的改善并不是很明显。

所以,我向大家推荐Unity里面非常强大的插件,就是VALV的Lab Renderer。

其实这是VALVE的工程师在做The Lab这个Demo的时候,想到的这个事情。

如果你听过他们在GDC上的演讲,就会明白他们也用Unity做开发,那他们为什么不用Unreal呢?

VALVE做的《半条命》、《DOTA2》,是非常高端、特效非常好的游戏。为什么它要用Unity呢?他们工程师就说了一句:“我们发现用Unity的团队,大部分都是小团队,而这样的小团队里面是不可能有一个人去专门研究图形,专门研究画面效果的,所以我们去专门研究这样一个插件叫做 The LabRenderer 的技术。”

目的就是说能够帮助小团队去实现一个还不错的渲染效果。

这个渲染其实特别容易。

它就是最简单的一个 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盏光源,也并不推荐你完全的用满它。

再一个是,比如说,我们很想使用一些特效,比如屏幕空间反射。但这个东西对于前向技术就没有办法实现,因为屏幕空间反射需要用到屏幕的几何信息,那怎么办?那我们是不是有一个更好的方法?

还真有。

大家想一想,我们做电影和做游戏的区别是什么?

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

那么,渲染在图形学里面其实就是一个不停采样的过程。

而抗锯齿根本的来源就是,一个渲染的图像,它缺少信息,大家如果是工科或理工科出身的,就知道 “奈奎斯特采样定理”。

我的采样频率要高于我最高频率的两倍,我就能完整地恢复出我需要的信息。

在渲染这个领域其实也是一样。

打个比方说,我们大家都知道,最简单的抗锯齿的方法是什么?你渲染一张2k的大图,把它缩小到1k,那这张图肯定锯齿非常少。

为什么?因为这相当于我们对1k的图的每一个像素做了四次采样。但是实际上,你真的去渲染一个2k的大图,那么VR有2k我可能就要去渲染4k,你这样去抗锯齿显然是不行的。

后来就有聪明人说,游戏最大的特点是连续性,那如果我能够找到每帧之间相同的像素,那我就能在时域,也就是说很多帧之间去做个采样。

就实现了个超采样,也就是所谓的Super Sampling。

有的时候大家在数据信号处理的课里面,提到这个Super Sampling。这个能够很好的提高画面的质量,最关键的是这个很便宜,或者说并不是很好,当然它的实现难度是有的。

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

我们加上了时域抗锯齿的结果,是什么?

最大的特点就是整个画面非常稳定,这样看起来是不是就有电影级别画质的感觉。画面稳定、像素没有任何瑕疵,包括在高光的地方也不会闪,非常的稳定。

我刚才说的 Temporal AA 一样的,在asset store上也可以找到一个还不错的实现。我不知道大家知不知道limbo这个工作室,可以去搜limbo的taa,能够得到非常不错的Temporal AA,也是直接在GitHub下载就可以了。

我想跟大家建议,要擅于利用包括GitHub、Asset Store这样的插件让我们的开发提升效率。

如果你想做很棒的产品,你必须要擅于利用这些前人已有的资源。

怎样解决全局光的问题?

然后,我再讲全局光的问题。

全局光问题历来是游戏里比较头痛的问题,特别是在VR里面更麻烦。

什么叫全局光照?

比如一个灯打到一块黑板上或者地板上,它投下来的影子那是直接光照。但如果它在地板上反射出去的光线照亮了其他物体,那这个就是全局光照。

全局光照一般是通过烘焙,也就是离线的方法把全局光照存成某种数据结构,在游戏实时运行时调用去实现的。

但在VR里面对于实时的运算是要进行严格的限制,所以我不推荐大家在VR里面使用实时的全局光照技术,比如说提速、mpv这种技术。

我建议大家老老实实用标准的光照贴图,也就说烘焙一张贴图然后贴上去。

但是,Unity又是一个非常麻烦的问题,Unity自身所带的enlighten的烘焙,不是很好调出非常好的效果。

我想大家可能都看过Unreal的一些作品,比如说Unreal做的室内装修,为什么室内装修企业,比如说51VR,他们都会用虚幻引擎去做室内装修呢?

一个最大的原因,室内装修对于全局光照的要求非常高,Unity是达不到的。如果你是用Unity做东西,用enlighten去调一个非常好的全局光照,难度很大或者说几乎不可能。

所以,我推荐大家尽量去使用另外的烘焙工具,比如说 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的工具去看一下,我现在这个场帧率是多少?我到底在哪里耗的特别快。

还有一种比较好的方法就是说,实在不行就按艺术家的方法去画。

打个比方说,bloom光晕特效,这个东西大家都知道Unity里面有shader自带,但是这个占的时间。

如果你是做移动平台的,你可能知道移动平台后期处理的效果是非常占时间,那怎么办?直接美术画上去,这也是非常行之有效的方法,当然也考验你美术的能力了。

再一个,我推荐多去测你游戏的性能。包括professional unity 5.4里也已经是比较完善的一个东西。

多去测性能、多去了解你游戏的瓶颈、bottleneck在哪里、是shader太多了还是说我某个特效真的不该用。不要在编辑器里测,最好是打个光。

对于开发者的建议

最后说一下,渲染有一个自我的评估。

当然我知道现在的很多团队是不会专门有一个程序员、或者专门有技术美术去关注这一块的。

但是我想说的就是,希望大家能够去多考虑一下。

比如说,你所需要的特效的特点是什么?

比方说,如果做的是一个机械的大战,你可能非常需要反射,可能就会去使用一个屏幕空间反射的特效在Unity 5.4 beta版里面会有。

再比方说,你做的是一个互动电影,那么对画面的要求会非常高,那么抗锯齿就要做的非常出色,那你只能使用时域的抗锯齿temporal AA,我刚才说的那种方法。

具体问题具体分析,渲染这个东西,永远不是一成不变的。

它不是像电影渲染一样,只要渲染的够真实或者说只要去模拟每一根光线的运动轨迹,就得到一个非常完美的图像。

关键在游戏里面,根据美术风格去做出妥协,根据性能去做出妥协,所以这是一个永远会谈论下去的话题。

你很难去说,我某个引擎特别牛,任何游戏都能做。即使是效果这么好的虚幻引擎,它也很有可能也有做出来帧率非常低的情况。

如果你不懂,不懂删减特效的话,你最后很有可能遇上非常大的麻烦。Unity的帧率并不是一个很大的问题,但是它的效果同样是个很大的问题。

如果你不懂得怎么通过各种各样开发,包括shader的技巧去加特效的话,也可能很难做出非常优秀的作品。

所以,我希望大家能够多讨论,有问题就提出,甚至能够建立一些自己的library或者open source library,去提高整个VR社区开发者的质量。

你可能感兴趣的:(VR相关)