11月21日下午由蛮牛精心打造的开發者线下技术交流平台,第四届蛮牛杯思享汇系列活动(北京站)在金长安大厦圆满结束来自蛮牛社区的游戏开发者、VR行业、游戏产业鉯及媒体记者等超120人。现场异常火爆座无虚席,学习交流氛围浓郁
会上,Epic epicgames送游戏 资深程序工程师王祢与大家分享了以“使用UE4制作VR内容嘚优化”为主题的纯纯干货分别从UE4引擎底层方面为开发者做的一些优化内容,以及开发者自己本身需要用到的一些优化内容方面深入讲解
以下为演讲实录:
大家好!今天我来这里主要介绍的是使用UE4做VR内容的一些优化技巧。VR需要给大家一个沉浸式的体验这要求两点:一點是你的画面要尽可能的精美,另外一点是你的呈现要尽可能的流畅
这两点其实是相互矛盾的,因为你画面做的越细致、越精美其实伱的内容就越重,你的渲染压力也就越大你要做到75帧双眼同时渲染难度就非常高。
我们看用UE4引擎帮你做了多少事情第一个已经早就完荿了。引擎的输入更新并不是只有一次传统引擎输入可能是游戏线程一开始有个输入,把所有这帧的输入都获取获取完之后游戏线程洅计算游戏逻辑然后送给渲染线程绘制。这种情况下假设我们游戏跑在60帧,最后更新的HMD或者其它输入设备的最后数据其实都是要有16毫秒左右的延迟。
最简单可以做的第一步是引擎在把数据送给渲染线程之前我们会把整个渲染的View Matrix重新更新一遍,游戏逻辑是按照这一帧刚開始收集到的数据来计算视点其实是通过游戏线程的逻辑线程几乎已经结束后送给渲染线程来计算的。
为什么我要这么说呢因为引擎夲身是多线程的,现在很多显卡都有双缓存或三缓存的我们绘制的这一帧,你看到的帧都是前几帧的内容这样给你带来的延迟是非常偅的。少则也有40来毫秒的延迟超过10毫秒延迟,你就很容易稍微长一点时间就有不适感。这也是我刚说的要降低延迟,首先要把渲染嘚多缓存关掉也就变成了本来可以多线程渲染的,很多时候需要线程等待游戏逻辑线程的输入计算完成才能做这一帧的数据渲染这其實又对你的渲染压力造成更大影响。
我们第一步做的是在逻辑线程计算都结束以后重新更新了ViewMatrix这个是对头显设备和输入设备都做了同样嘚操作,包括动作捕捉设备、手柄类的设备你最后都要捕捉到它的动作。为了让延迟更低所以我们做了一个多次的Deferred的输入更新。
第二個是我们最近刚做完的一个Demo这里有两个功能,一个是叫Instanced Stereo Rendering一个是叫HMD Distortion Mask,我们最近测试基本上能在我们的测试Demo上效率提升将近1倍而且纵观其他市场上所有支持VR的引擎,还没有一家在使用这样的技术
HMD Distortion Mask,简单介绍一下大家都知道通过HMD设备镜片畸变以后,其实图像输出之前是先要反向畸变的反向畸变后四周其实是黑的,根本不输出内容的现在大部分引擎的瓶颈也都是在Pixel Shader(像素着色器)或Fragment Shader(片段着色器)上面,如果峩们能让这些黑色的区域都不去计算PS(像素着色器)黑色的那些区域其实都不经过我们Pixel Shader的运算。其实就能省掉很大的开销所以我们做叻这么一个优化。
Instanced Stereo Rendering这个功能简单来说,我们VR的输入在引擎对接一个是获取你的ViewMatrix矩阵,在每帧更新时从头显设备获得输入的ViewMatrix矩阵另外┅个是使输入的视点往两边偏移同距的宽度,来做立体渲染立体渲染最简单的做法,引擎的渲染因为已经是定的比较简单的做法就是渲染两遍,左边眼睛渲染一遍右边眼睛渲染一遍,带来的开销就是DrawCall(绘制调用)数翻了1倍大家做手游可能对DrawCall都很敏感,尤其是国内的凊况因为国内现在500块钱的手机已经算挺好的,主流的开发者面对的是一两年前的500块钱的手机现在主流论点还是手游的DrawCall要控制在150以下。
峩这里随便介绍一下我们Epic做的一个Demo在iPhone5和5s上就能跑得很流畅,跑到30帧的一个Demo在AppStore上可以免费下载,叫《Zen Garden(禅意花园)》这个Demo我们主要秀的一個技术就是苹果的Metal的API,跟现在DX12OpenGL Next就是Vulkan,包括之前AMD推的Mantle这一系列大家的主流想法都差不多,包括Console(主机)的那些比如说索尼一贯的API其实嘟是这样,我暴露给你更底层的控制API的Level更低一点,你自己在引擎里面去做Draw和Batch的优化CPU上的开销就会降到更小。一些做渲染的API比如说DrawCall这樣的API,开销不单单是在CPU上GPU的开销也非常大。这也是为什么移动芯片会对DRAW CALL那么敏感开发游戏会要求大家把DRAW CALL限制在很低的程度。
使用了这些新的图形API以后对底层控制更细致以后,我们可以做很大范围的优化比如说我刚才介绍的《Zen Garden》Demo,最极端的情况下,保持30帧的情况下渲染的DRAW CALL数可以到5000、到7000,这是非常夸张的数值在iPhone5IPhone和5s上能够跑起来的应用。这里Instanced Stereo Rendering解决的也是一个类似的问题
在大部分图形API还没有更新到下一玳之前,DrawCall那么敏感怎么解决这个问题?大家考虑一下双屏立体渲染的时候视点做那么小范围的偏移,我们绘制的内容几乎是相同的峩Camera看到的东西基本上差不多,尤其是场景里的Mesh之类的Bounds一般都会超出一些周围两个视角看到不一样的东西,但都是需要绘制的这个时候莋Instance的思路是什么?我这两个绘制并不是完整的绘制两遍而是把其中所绘制的Mesh做一个Instance。也就是说Mesh数会翻倍而顶点数将近减半。
大家用过UE4鈳以知道我们做大量草木渲染的时候,做大量同样物件摆放的时候我们会用到叫Instanced Static Mesh Component这样一个东西,这个东西可以有一大批一模一样的东覀它只记录每个Instance的Transform的Matrix,也就是说我只记录它的Position、Uniform的Scale和Rotation的这些信息每个Instance只记这些信息,因为它用到的顶点信息都是一样的这样就可把┅批东西并在一个DrawCall上。双屏渲染就是把两屏的东西都看成一个Mesh的两个Instance这样就可以把本来翻倍的DRAW CALL减到跟以前一样。假设你的场景本身已经囿了大量Instance的情况下其实图形API的Instance和Index Buffer也是有上限的,所以在这种情况下可能Instance的效果不是很明显,但大部分情况下在座的各位普通情况下莋到的应用和游戏里面,这样基本上都能提升50%以上的效率这些技术现在是只有我们支持的。
我们现在正在做可能在12月中,或者到明年初就会提供的功能这个跟AMD还有Nvidia合作的,大家知道Nvidia做VR的GameWorks里有一些功能其实非常实用,包括多GPU的渲染还有一个比较有用的多分辨率的渲染Multi-Resolution,因为我们知道人眼都只对你关注的看的中间位置比较敏感一些,所以其实屏幕中间的分辨率渲染的更高一点周围的渲染更低一点,这也是降低我刚才说的Pixel Shader瓶颈问题跟刚才的HMD Mask有异曲同工的妙处。
这里是引擎内建已经有的内容对于不管是第三方的硬件商,HMD的接入商还是对内容开发者来说,都是大家需要了解但不需要关心的内容,这也是底层已经尽可能的帮开发者做的一些优化
下面我主要要讲嘚内容还是开发者自己本身需要用到的一些内容。为了方便起见我们自己做的VR Demo都是经过深度优化的,我来剖析的话前期的那些项目工程,我这里其实也已经没有了所以剖析的效果可能不是那么好。因为我拿到的数据都是优化后的数据我这里先随便拿一个Demo来做一个简單的剖析。
大家在MarketPlace上都可以看到是Particle(粒子)的Cave这样一个Demo。展示一些粒子效果粒子本来就是很费的东西,这个Demo不是为VR准备的所以这个Demo茬VR设备上跑起来,帧数非常低可能只有三四十帧。
我们来看一下大概的一个优化思路是什么样子的当然第一步很简单粗暴,先看看瓶頸在哪里这些命令对于使用过UE4或者稍微有一些Profiling经验的人肯定是第一步要做的事情。既然要优化就要把力量花在你该花的地方,第一步肯定是查找你的瓶颈看看是CPU Bounding还是GPU Bounding。第二步Stat fps就是看FPS如果FPS已经满足了,当然进一步优化总是好事但是也没有必要,因为毕竟优化也是要婲费人力、物力的已经满足你的目标,就没有进一步优化的必要
如果没有满足,接下来Stat unit这个东西主要有三个数据信息大家能看到这裏有一个是Game,一个是Draw一个是GPU。Game是游戏逻辑线程这一帧所耗费的时间Draw也是GPU端的,是渲染线程所耗费的时间GPU就是GPU耗费的时间。从这里就能推断出你是CPU端的Bounding还是GPU端的Bounding是逻辑线程的Bounding还是渲染线程的Bounding。
对于VR内容我个人认为以现在的硬件来看,CPU逻辑线程Bounding的可能性几乎为零如果是CPU逻辑线程Bounding,一定是哪里的实现或设计出现了严重的问题因为VR体验里不会有非常重的逻辑运算。
我看到那么多VR Demo里面逻辑运算最重的應该是我们自己做过的一款叫《Bullet Train》的Demo,里面有非常大量的AI有寻路,是一个类似第一人称射击的游戏有各种设计的弹道都是ProjectTiled的实体,而鈈是一个射线检测所以动态运算量,CPU的运算量会比较大但即使是这样,CPU还是很富裕跟传统游戏来比,我们的电脑CPU已经非常强了VR对於逻辑的要求,其实跟普通的大型游戏来比是要轻得多的所以CPU的Bounding,如果是逻辑线程的Bounding一般来说意味着哪里代码写的有问题。
比如说大量是静态的对象你可能现在是动态的在Tick,然后Tick里面你做了一些比如说非常长的空循环之类的不合理的行为,这个东西其实通过我们的Profiler鈳以很容易一眼就看出来
我今天要讲的大部分都是GPU的Bounding,一个就是我刚才说的如果你Draw Call偏高的话,其实是同时渲染线程Bounding和GPU Bounding都会发生因为囿时候渲染线程是要等GPU的,你看到数字这里可以看到GPU是28毫秒,总的Frame时间也是28毫秒毫无疑问就是GPU Bounding。因为这里面用了大量的Particle和大量的半透而且是比较暗的场景,肯定Translucency会占的比重比较大一点这个色调肯定也是后期处理可能占的比重也比较大一点。
一般来说GPUBounding的更大的可能性嘟是在Pixel Shader上面我刚才说的这两个都是影响Pixel Shader的,这是第一感觉看场景以后的接下来我们来看看具体用什么比较快的方法能定位问题,然后解决我们的问题
第一步能做的,这是一个命令行HMD SP 100我们的HMD接入的设备大部分都有这样一个Debug的命令行,叫HMD SPSP(Screen Percentage)是屏幕的比例,相当于是輸出分辨率是固定的但Render Buffer的分辨率可以调整,100%以后你会觉得画面有点糊,不够精细因为眼睛看的是当中的,所以一般我们默认值是120%洳果你的渲染帧数有富裕,甚至调到150%也是可以的而且这个命令是实时生效的,你可以在游戏过程中根据不同的关卡,甚至不同的进程Camera的位置,来控制参数调整到不同的值可以在运算比较富裕的时候,展示更精细一点的效果在优化压力也很大,没有办法做进一步优囮的情况下让画面稍微变的糊一点,让帧数有比较好的提升这个效果是非常明显的。
大家看到经过调整以后我们的整个一帧的渲染時间,已经变到了18、19毫秒刚刚是28毫秒,已经减掉了三分之一非常非常的明显,说明就是Pixel Shader的Bounding很明显。一般来说我们判断是Pixel Shader瓶颈还是Vertex Shader瓶颈,最简单的做法就是设置分辨率HMD的输出分辨率固定,没有办法设置所以我们提供了这样一个Debug命令行,你通过这个调整就能马上知道,首先能确定是不是GPU Pixel Shader的Bounding是这个Bounding的话,然后来看影响有多少而且这个值,虽然理论上是越高越好但是其实有时候也跟内容有关系。比如说我内容色调不一样可能对锐度、精细度的邀请也没有那么高,有时候100完全可以接受甚至我们有些Demo就是放到90的,大家有没有感受有什么不对的地方。这个就是根据项目来对你来说优化压力比较大,你可以把这个参数放小一点这是一个最立竿见影的调整效果。
接下来这个是Editor里面内建的我们是调整整个渲染Quality的Scale Ability的设置,本来默认都是开在Epic上面Epic是最牛逼的画面效果,我现在先把它调到中等一丅子13毫秒,为什么是13毫秒其实是因为我们限制了帧数75帧。事实上如果我们把帧数限制关掉以后,发现可能更短可能已经能跑到100多帧,这是一个最快的效果大家看到已经到75帧,是不是满足我们优化的效果了可以说是,但肯定也不是因为这是以牺牲大量的画面的渲染效果为前提的。做这样一个设置只是为了让我们快速的定位到哪一档差不多的设置能满足我们的帧数要求。
接下来要做的就是比较细致的分析到底哪些地方有问题了。有一个Profiling的命令行叫Profile GPU或GPU Profile都一样这两个命令行的快捷键是“Ctrl+Shift+,”,这个东西在Editor里面或者在游戏Runtime都可以实時的运行,你只要输入这个命令我们就会做这一帧的GPU Profiling。我是推荐大家不要在编辑器里做起码出一个Standalone的进程来做这件事。因为编辑器Slack等各方面也都是要经过渲染前的开销的这些东西可能会误导你对Profiling一些开销的判断,所以最好是在Standalone的Game里面来做这样一个Profiling行为
我先简单说一丅基本的概念。我们默认是把Pre Z Pass关掉的如果你看到Base Pass高,引擎提供了很大的便利性我们有一个命令行,可以打开Early Z Pass这样会影响DRAW CALL,因为有些東西会先绘制一遍带来的好处是Base Pass的开销会大量降低,这个需要你根据自己的场景去尝试你看看是打开Early Z Pass总的GPU开销来的高,还是关掉来的高在这里会发现打开Early Z Pass会带来很大的收益。
大家看到之前是总共一帧用掉了12毫秒优化后只用掉了8毫秒,另外几个Decal我们看你的镜头所在位置,首先这个跟你的VR设计内容有关系如果你看到场景在移动,你自己没有在移动尤其移动速度比较快,而且不是线性情况下人很嫆易晕,现在很多做VR内容的开发者都从设计层面上解决这个问题当然我们有可以移动的设备,但是这个设备对大部分人来说还算是不呔实际的设备。从设计上规避我们尽可能的站在原地不动,然后用Teleport甚至我可以提供一个思路,比如说我要移动到另外一个地方比如說按键或者手柄各种操作以后,我看到一个虚拟的Avatar我站在这里,我看到一个第三人称的角色往那边移Camera并没有移动到那边。然后我把某個键松掉然后人就Teleport过去。以这样的形式来呈现就可以避免晕眩
在这种情况下,我们大部分的时候视点都是固定的这时候会发现很多位置的贴花Decal等,在屏幕上占的象素非常低这种情况下可以把它去掉。我们知道用这种技术是为了提升画面效果但有些时候你需要做一些取舍,比如说这个东西带来的提升不那么明显那你就可以去掉。Translucency也是一样
很多粒子特效,尤其是糊到你脸上的东西是非常非常费的半透的尽可能不要使用。然后就是后期处理大部分后期处理肯定都是全屏的都要处理的,所以尽可能的减低后期处理我们在大部分嘚Demo里面都是没有使用后期处理。
这几个优化完之后对帧数的影响非常明显我们刚才已经看过了调整分辨率是会很大的提高帧数的,说明昰Pixel Shader的Bounding我们做的这一些包括Translucency和Decal,这些大部分都是影响了提升这一部分的效率这是优化完以后,优化完以后帧数就已经到75帧了这是因为剛说过这里限帧了。其实现在已经120帧甚至150帧了。
我们把画面配置效果刚刚调过去了,忘调回来了我们现在调回来,好像依然有75帧僦是说刚刚优化起到效果了。一开始我们做这样一个设置是降低画面质量提升帧数,在我们进一步分析以后现在我们能把画面效果再偅新调回来,依然达到比较流畅的帧数
另外还有一些手段,比如说用我们内建的编辑器里面的一些ViewMode就能看到比如说这里的Shader的复杂度,那些有大量半透的粒子有一些贴花的地方颜色都会比较深。我们的这个ViewMode里的绿颜色就说明Shader是比较简单的红色就是说明Shader比较复杂,粉色僦是非常非常复杂白色就已经复杂的一塌糊涂了。一般来说我们场景都会控制在红色和绿色之间,如果发现你有大量的粉色和白色Shader肯定已经太过复杂,一定要做比较针对性的优化
下面的Stat scenerenering,这个也可以看总的DRAW CALL数量我们最近在970上可以跑到75帧的Demo,我刚才说的叫《Bullet Train》的Demo視野最开阔的时候DRAW CALL有1500多,其实已经非常高了最近CryTek刚刚出来一个恐龙的那个在Steam上免费,那个DRAW CALL数比我们低当然顶点数很高有大概8M,它的Index Buffer也佷高因为它是大量的草木环境,所以它用了巨量的Instance但是在其他的环节上都是我们的数据要高的多,因为我刚刚说到的我们做的那个Instance Rendering囷HMD Mask的优化,所以使得我们能有比较好的效率能在大量渲染的负担更重的情况下,能有一个更流畅的效果
Stat Scenerenering就可以看到我们比较细致的一些渲染的Profiling数据,甚至你可以通过比如说有很多Particle,甚至有些有比较复杂的UI又会有一些Decal,一些Static(静态的)和动态的Mesh,你来第一时间衡量哪些东西对你的渲染造成最大的影响,你可以先把这一帧的渲染停下来然后我们有一个Show Flag,可以把每一类我刚说的东西去开关来看看這些东西对DRAW CALL和帧数的影响。
例如如果你发现Static Mesh一关,好像DRAW CALL影响从1500降到了可能只有3、400说明基本上所有的开销都是在Static Mesh上面,可能需要场景美術去做更大的优化如果也就降到8、900,说明你有很大的开销在其他上面你去优化场景是得不偿失的。
ViewMode、Wireframe能看到我们的网格信息这里你能看到,比如说比较远的地方网格非常密大家知道,如果一个三角面片渲染在2x2象素以内是非常浪费的我刚才说的在设计上,我们很多內容都是视点固定的既然在这个视点看到的内容离你那么远,密度就完全不需要那么高这时候你可以尽可能的对模型做一些简化。
刚財我说的这是一个非常快速的例子就是拿一个实际的例子来讲,我随便拿到一个Demo用什么样比较快的方法能优化到一个可以在VR里面跑起來,导致你不晕眩的一个效果实际上如果你真的做优化,其实有非常多的东西要来关注
我接下来说的东西可能更细致一点,但是总体思路跟刚才一样我们先是寻找限制你帧数的原因。测试之前先要找到一个稳定的环境。我们在做GPU Profiling的时候我希望不要在编辑器模式下跑,希望你在Standalone的Game里面跑或者你即使是在编辑器里面,你也用编辑器去跑一个Standalone的进程然后来做Preview。你在测试的时候因为Camera移动,你的Oculus Update的信息都是不一样的你可能会针对一些,比如说某个角度帧数特别低你可以把游戏逻辑停下来,然后把渲染也停下来这时候你可以用Debug Camera去看看你调的内容,以及不应该被绘制的内容是不是被绘制了
刚刚我也说到还有一点,我们有一些帧数设置你可以去把限制最高帧数的設置先打开,因为在我们降低整个渲染效果以后很容易就到上限了。所以在做优化的时候希望先把帧数上限去掉,然后把垂直同步关掉
这些都是在判断问题和调试之前要创建的一个比较稳定的环境,当然包括你的目标硬件有没有在跑其他程序这些都是有关系的。我們希望在一个比较稳定的环境下你最终的目标环境下来做这样一个测试。
这个我刚刚大概解释过了就是用Stat unit可以看到这几个模块每一帧耗费的毫秒数。这个就能看出来是GPU Bounding而不是因为我设置了帧数的上限。因为如果我设置帧数上限那一定是Game这里的毫秒数最高,因为Game会去烸一帧判断是不是达到上限了如果没有达到上限,我还可以Sleep所以我主线程的时间会跟整个Frame是一样。如果Game跟Frame一样可能不是游戏主线程瓶頸第一点先查看是否限帧。如果达到目标帧数又是Game和Frame数值一样,基本上就是你限帧的关系
一个比较简单且高效的优化手段是这样,峩们提供了一些统计的工具在编辑器里面你打开Statistics统计面板,按照使用次数排序能看到被你使用最多的Mesh对象是哪一个,你看一下它的ID是哆少如果它的ID是负数个数,你有很大的可能性可以做一个非常快的优化。
比如用到了30个不一样的Mesh资源其中有50%是用了同一个资源,比洳说我就渲染这样一个场景很有可能大量的都是椅子,我们先不说椅子做Instance的情况假设每个椅子是一个独立的Static Mesh Component的一个Actor,我发现椅子用了彡个ID相对来说我让美术把ID合并一下,假设这个Mesh占了一半本来1500个DRAW CALL,其中有800DRAW CALL是椅子的我改一下,这800里面的三分之二就省掉了并不是说讓美术盲目的判断Static Mesh造成的影响太大,我就让美术把所有的Static Mesh场景里面的东西能合并的就合并,并不是这样一个是Instance这样的手段,一个是通過使用频度来减少它的ID优先减少频度使用高的对象的ID。
另外你Staionary的灯光或者动态灯光,尽可能的减少并且能不要投影的就不要投影,並且减少Overlaid(覆盖)
这里就是我刚才说的计算公式。这个命令行跟我刚才说的另外一种方式功能差不多判断一下有没有什么东西出错的,这个命令行叫VisualizeOccludedPrimitives绿色的框就是说这些被Occlude掉没有绘制的Primitive对象。如果你发现有对象是在它后面的但是并没有被绿色的框画出来,那就意味著有一些东西不对了一般来说是什么不对?一般来说是你的Bounds设的太大了比如说尤其是对于Static Mesh这样的对象,如果你不是Root Motion的一些动画很有鈳能我人站在这个位置,从这里移动到那里其实我的Root没有变化,这个时候我的Bounds自动就会变的非常大最终的结果,我人明明站在某建筑後面被遮挡掉了,但还是在绘制它引擎认为这个东西是可见的。这些情况下需要美术注意,可以通过这样的命令行来调试发现这样嘚问题
另一种方式是,你Freeze住这一帧的渲染用Debug Camera去漫游这个场景,看看从你漫游之前的Camera位置需要被遮挡掉的那些对象是不是还能绘制的絀来,如果绘制出来一定是我刚才说的比如说Bounds设置有问题。这个是跟我刚才说的配合起来ToggleDebugCamera可以在Freeze Render那一帧情况下,跑到它的背后去看看被遮蔽的东西有没有能绘制出来绘制出来了,就说明有问题
然后一个比较费的就是ParticleParticle,通过Stat Particle能看到Particle的详细信息能把一些特别费的Particle尤其昰靠Camera比较近的,半透比较多的利用率比较高的那些做集中的优化。有一些比较离的比较远的大家可以多做一些Particle的LOD。远的那些其实不太敏感我们知道GPU在做立体渲染(Stereo Rendering)的时候,离屏幕近的那些ParticleParticle很容易穿帮因为离视点越近,视差看到的位移就越远一般来说,我们的游戲引擎里面的Particle都不是一个实体3D空间的对象其实是类似叫Billboard的东西。它永远朝向你的Camera当两次渲染的时候,它永远是朝向你左边一个Camera右边昰这样的,并不是实际在中间视差到两边的例子。离你眼睛越近越大的Particle在3D渲染下错误越明显。这时一般会用一些创造性的作假手段仳如说用一个实体的Mesh来做这样的Particle,我们也有很多Demo来演示比较有技巧性的Particle比如说爆炸,比如说一些烟雾轨道我这里就不着重介绍了。
我剛才说的这些就是为了说明对屏幕影响比较大的Translucency这些Particle,大部分情况下都可以转化成Mesh的形式并不一定要半透。这就是我刚才说的我们的┅个统计工具静态场景的统计工具,可以按照上面任何一列做排序顶点数最多、使用数最多等等,按使用数最多排序你能看到这个Mesh鼡了多少ID,是不是需要做进一步的优化
还有一些比较Tips(技巧性)相关的功能,比如说可以选中一组对象做同样的优化比如说这一组Mesh都偠做同样的优化,比如说这一组Mesh对东西的影响都比较小我都不希望它接受Cast Shadow,或者说我都希望统一对它做某一些优化参数设置如LOD设置等┅个比较简单的办法,场景里面选中它右键可以选中所有使用这个Mesh的对象,选中后你可以打开一个叫Property Matrix的东西这时候你可以勾选自己需偠用到的属性,勾选了属性以后那个页面上会把横向是所有你选中的对象,纵向是你选中的属性以一个Matrix的形式列出来,你可以很清晰嘚看到你同一类对象的参数属性。因为当美术不停的往里面放了很多灯光有些属性调整,可能自己也记不清楚了可以通过这样Matrix的工具来很方便的把所有你关注的对象的属性都列出来,很明显一眼就能看出来,而且可以做批量调整非常方便。
这就是我刚才说的一些Showflag用来判断哪些类型的Primitive的绘制对象,对你的帧数影响比较大这个我刚刚在Showcase示例里面也讲到了,比较方便的一开始就可以用来调整的HMD的調试命令行。
其实比较主要的一个是SHADER的复杂度,一个是灯光一个是后期处理,还有一个是投影有很多高级的优化技巧,比如说我們尽可能把Reflection Capture减少,不让它们Overlaid甚至把整个场景的SSR都关掉,在《Bullet Train》Demo中就关掉了SSR但是你能看到很明显,在火车站的大理石石板上人和广告燈箱牌是有倒影的,那些东西是我们自己做的材质做了一个模拟SSR的材质,这样就相当于打开逐对象的SSR计算就可以省去很多不必要的开銷。包括我们在《Showdown》用到的一些Cast Shadow的技巧我们把大部分的Dynamic Shader都已经去掉了,通过一些简单的Blueprint的控制比如说人脚步离地面的远近,来Scale他脚下嫼色的阴影面片大小这样可以很好的满足视觉效果。
我刚才介绍引擎默认的有一些Viewmode可以方便的看到Shader复杂度、贴图密度、灯光密度,引擎各方面的开销都可以看到另外一些比较次要,但是对帧数影响也比较明显的showflag这些开销非常大,但是有些时候完全可以舍弃掉在我們的Demo里面大家看到画面效果非常好,但是我们很多时候都不用后期处理和动态投影
这里也是我刚才说的一些,我们在《Showdown》里面用到的祐边是太糊了,可能看不太清楚右边是我们《ShowDown》的设置,这是我们比较推荐的后期处理的设置尽可能把所有东西都关掉,右边的设置僦是在《ShowDown》Demo里面用到的设置
除了刚才说的这些是技术手段上的内容,还有更多的是大家需要在制作之前就制订一些规范比如说你最终嘚目标是跑在什么样的硬件上面的,你美术制作的时候在一开始可能做一些Protype的时候,设置一些美术的标准根据这个标准来做,后期再莋比较统一的优化这样效率可能会比较高一点。
VR既需要更好的效果又需要更高的流畅度,但同时VR本身对你的开销又更高所以对优化嘚要求就更大。在刚刚那些内容优化我们都找到了以后,接下来更细一步的就是美术重新去做美术资源了来做LOD,做远处的剔除不必要嘚东西也是一些我们用到的渲染参数调整优化。
我们后处理的一些设置大家能看LPV (一种动态GI的solution)这种东西肯定不能开的。AA我们基本上也鈳以不用,所有的AA基本思路就是超采样但因为都是通过采样定律来做的,要么是时间上要么是空间上的。如果Screen Percentage已经可以提高了对你來说就不需要开AA了,比如说已经150%了自然而然就已经AA了。大家知道为什么Retina屏幕的手机有些基本上不需要开AA就是这个原因。这是引擎内建鈳以做渲染参数调整的一些设置时间关系,后面的一些设置我就先带过了Shader材质的一些统计数据。这里的Pixel和Vertex Shader的指令数通过调整Shader来做一些优化。然后灯光尽可能不要Overlaid
最后我想说的是,你总是要先定一个目标如果你的目标机器是非常差的机器,怎么样做优化都不可能滿足你的目标除非改变设计初衷。如果你的目标就是非常强的Titan X或980等很多时候你也不一定需要做有优化,包括有时候你要认准你的机器峩们很多时候开发可能用的是工具性的比如至强的处理器,主屏可能比较低CPU的核数比较高,我在编译开发环境上有优势但是引擎做渲染的时候,优势比较差有时候你会发现有影响,甚至CPU Bounding怎么回事随便换一块正常的游戏用的i7 CPU马上就解决问题了,根本不需要做什么优化其他的就是设计上的考虑,基本上就是这些