上海人物摄像交流群

【新思路】如何让UE4开发的VR项目性能再优化?

只看楼主 收藏 回复
  • - -
楼主



目前VR行业发展迅速,VR性能逐步完善。但目前VR仍然存在一些技术瓶颈。 VR渲染效率和延迟是导致晕动症和人眼疲劳最重要的两个问题。本通过UE4项目开发中的一些流程和技巧来优化VR实时渲染效率。达到提升渲染效率降低延迟,从而降低导致晕动症和人眼疲劳的机率。本文是《使用UE4开发VR项目-性能优化》的第二篇。希望能和您分享一下在UE4 VR项目优化的基本思路方法和技巧。


前篇请参考这里:

__biz=MzA4MDc5OTg5MA==&mid=2650586383&idx=4&sn=40f2a2a9312f1ea10647ceb4a3c9a7e0&scene=21#wechat_redirect


造成晕动症的原因很多,比如设计不合理,硬件技术瓶颈。CPU、GPU上的性能问题、内容优化不合理等等。 下面通过一套优化流程来说明VR性能优化的的思路和方法。


(一)VR优化考虑的问题

(二)VR测试环境准备

(三)找到受到限制的瓶颈

(四)GPU渲染线程分析

(五)CPU逻辑线程分析

(六)可能遇到的问题和优化方法



(一)VR优化考虑的问题


HMD(头显)刷新频率

目前主流的VR设备对帧率的限制都在90FPS/120FPS

DK275 FPS

CV190 FPS

HTCVive 90 FPS

PS4VR 120 FPS



VR双屏渲染

简单的说双屏渲染就是把屏幕所见看成一个Mesh的两个Instance,可节省50%以上效率


Instanced StereoRendering

实例化立体渲染



HMD DistortionMask

HMD镜透变形



VR多分辨率渲染(Multi-Resolution Shading)

人眼只对中间的视距中心的位置较敏感,所以屏幕中间渲染分辨率更高,屏幕周围渲染相对较低。它可以让我们在不影响最终画面显示效果的前提下,提高计算资源的利用率



VR SLI (Nvidia VR优化技术)

这项技术是使用多块显卡协作,开发者可以自由定义显卡处理什么信息。



场景比例

须使 VR 世界中的物体比例与现实世界一致。大小不匹配会引起眩晕或模拟疾病。



渲染品质压力

比如材质复杂度、灯光数量、动态阴影、粒子系统(材质复杂度 +双目粒子面积+ 粒子数量)、贴图尺寸、双屏可见视野、模型面数等等。通过控制物件,特效数量,使用cull distance volume、instance等方式可以控制渲染量达到控制目的。



DRAW CALL数量

比如同屏看到的Actor数量、材质ID数量、每个actor上的feature数量、灯光投影面积过大导致Draw Call偏高,CPU逻辑线程和GPU 渲染线程都会发生问题。



内存占用率

通过限制贴图数量、尺寸、提高模型、材质、贴图的复用率、控制物件、特效数量、及UI相关资源数量,可以达到控制内存的目的。



VR包体大小(VR移动端)

通过提高模型、材质、贴图的复用率,使用压缩限制贴图数量和尺寸,必要时可取消mipmap等方式可以控制包体大小。



卡顿问题

我们首次加载地图的卡顿问题,视地图大小而定,若地图相对小;资源量不大,可用施明的预加载一遍的方式;若地图比较大;资源量也大,则不适用。需考虑修改newRenderPipelineState为异步来解决。另外的针对加载mipmap的卡顿点,也可以通过取消TextureStreaming来解决,取消TextureStreaming后存在显示延迟的问题,这个问题需要修改默认的显示顺序,可按照摄像机距离进行排序显示。


(二)VR测试环境准备


VR项目参考请参考《基于UE4的VR项目基础环境配置和Motion Controller控制配置》的VR项目基础环境配置(http://gad.qq.com/article/detail/7167914)

创建测试环境

暂停游戏

跑单独游戏

进行多次测试

确保帧数不封顶 关闭垂直同步



(三)找到受到限制的瓶颈


目前的VR内容来看,CPU逻辑线程上出问题的比例很小。如果CPU逻辑线程出现了问题。一定是实现和设计上出现了问题。或者是代码写的有问题。大多数的问题出现在GPU渲染线程上。找到瓶颈的方法,第一步判断是CPU逻辑线程问题还是GPU渲染线程问题。第二步使用控制台Stat fps来看FPS,如果FPS已经满足就没必要进一步优化。如果不满足,接下来使用Stat Unit命令查看更详细数据来帮我们判断瓶颈所在。



HMD SP 100

SP是屏幕比例,输出分辨率是固定的。但Render Buffer可以调整。默认120% 调整成100% 时候 画面会变糊,测试VR性能过程中,根据不同关卡、摄像机位置、来调整不同的值。在渲染压力很大,不能进行进一步优化的情况下,让画面变糊,让帧数有提升后,即可进一步优化。判断是Pixel Shader瓶颈,还是Vertex Shader瓶颈,只要调整HMD SP 会有帧数提升的时候,即可确认是GPU渲染线程瓶颈。这个命令在优化压力很大的情况下是最有效果的调整。



Stat FPS

显示FPS数据,查看当前帧数



Stat unit

这里面有三个有用的数据,GAME:游戏逻辑线程这一帧所耗费的时间。DROW:GPU渲染线程所耗费的时间。Gpu:GPU耗费的时间。


可以查看几个模块每一帧耗费的毫秒数。如果Game这里毫秒数最高,首先查是否限制帧数上限。如果Game和Frame一样,那么可能不是游戏主线程瓶颈。很可能是限帧的原因。

调整渲染质量Scale Ability设置

关闭一些stuff,然后看效率上的区别

一些可调的show flag(屏蔽渲染查找问题)

开/关屏幕反射

开/关AO

开/关AA

开/关bloom

开/关延迟灯光

开/关灯光类型

开/关动态阴影

开/关GI

开/关后期

开/关环境反射

开/关折射

开/关贴花

开/关半透明

开/关tessellation


(四)GPU渲染线程分析


如果遇到GPU瓶颈最快的验证方法是改变分辨率 降低分辨率可以极大提高帧数


如果帧数有大幅度提高 即是GPU瓶颈。如果影响不大,可能是面数太多。


一般GPU渲染线程问题大多数可能性是像素着色器(Pixel Shader)


ProfileGPU 命令可快速确定多个通道的 GPU 消耗

快捷键:Ctrl+Shift+,

r.ProfileGPU.ShowUI 对 UI 进行抑制

建议不要在编辑器里运行,开关编辑器也是有渲染开销的。渲染数据会产生误差。最好建立单独游戏(Standalone)运行环境



几个值得注意的数据项:

Base Pass

Deferred Decals

Lighting

SSR(环境反射)

Translucency(半透明)

Postprocessing(后期处理效果)

Particle(粒子)

**当Base Pass很高,可以使用命令行打开Early Z Pass 可以降低 Base Pass 但同时会少量增加DRAW CALL**

检查影响GPU效率的内容查看有无超标现象

比如分辨率、HMD SP、投影贴图大小



ViewMode检查

当三角面密度太高(高到三角面小于2*2像素 往往发生在远处物体上) 很容易出现问题。

分别查看三角面、顶点、灯光数量、阴影设置、Actor数量

LOD 关闭Shadew 、灯光屏幕面积

顶点太多

点动画的Shader处理过于复杂

Tessellation 过于复杂

多重UV、过多的SG

查看Staticmesh Editor里点和面数的差别是否大

点没有合并、场景GPU粒子模拟数量过多



材质复杂度

Quality、Switch、Sin、 Pow、 Cos、Divide、Noise 这些节点很耗费资源


减少材质Shader的指令的数量。减少Texture Sample的数量:把经常使用到同一个物体上的图案合在一张贴图上;去掉对质量影响很小的贴图,比如Specular、AO等。尽量使用QualitySwitch,Sin, Pow, Cos, Divide, Noise节点。多向量的计算量总是大于单向量的计算量。

遮挡的culling计算

使用预算可见性剔除遮挡的对象。



延迟灯光

当使用lightingfunction、IE、接受投影、区域光、复杂shadingmodes的时候会变得更昂贵。反射SSR如果有问题,请关掉它。另外后期AO也很耗费资源。


(五)CPU逻辑线程分析


引起Draw Call 数量增多的原因

1
同屏Actor过多、材质复杂性过于复杂。 (合并Actor、降低材质复杂度)
2
材质ID太多、重用材质贴图(把同一材质合并成一个物体)
3
每个Actor上的Feature 太多(主要增加投影属性 增加Custom depth属性)
4

过多灯光投影(检查投影计算来自哪些物体被投影)



Mesh Draw call 可以检查静态模型统计器来解决问题

Actor 设置 Feature 会增加DrawCall数量的是 custom depth

通过检查工具来设置Showflag 使用Property matrix 来过滤

使用排除法,隐藏各种元素 查找Draw Call 数量过多的因素

隐藏HUD (HUD占用很多性能,Showflag.slate 1)

还可以使用移动设备上的CMS增强阴影(4.12)

Rerdring>Mobile>Combined>StaticandCSM shadrring

接收物体选项:ReceicvCombined Static CSM shadows from stationary lights


UE4里由于使用了延迟灯光,所以灯光的优化比前向渲染方便的多。最快速最有效的方法:使用静态光源。如果使用的是动态光源,要减小Lighting Cull、半径、衰减、 Cone大小角度等等。总之尽量减少重叠。


投影的开销最大不是来自于PixelShader,而是来自于被投影的Mesh面数太多,还会被灯光数量,投影物体数量放大。关闭投影的灯光;减小范围或张角;减面,加LOD


可以使用r.Shadow.MaxResolution 命令用来查看阴影分辨率数据。


Stat Game

Stat Scenerendering

命令可以显示

DrawCall数量 (计算公式:Mesh数量 * Mesh ID * 投影灯光数量)

Particle粒子

复杂的UI 

Decal 贴花

静态Mesh

动态Mesh 

查看影响最大的部分 ,再次使用Show Flag 开关渲染特性来查看这些特性对DRAW CALL和帧数的影响



DrawCall优化:

打开Statistics统计面板,按使用次数排序Actor。查找使用次数最多的MESH 的ID ,如果ID是负数,那么就可以做优化。


例:如果有60个MESH 资源 其中有一半使用同一资源,那么就需要考虑需要用Merge Actors(融合Actor)来降低ID数量。优先减少使用频率最高的Mesh ID。这个操作可以减少这60个MESH中50%以上的DrawCall.(优化模这步骤建议放在最后才去考虑)


Staionary灯光和动态灯光要尽量的少,并且能不投影的尽量不要投影。并且减少光源间Overlaid(覆盖)


控制台:r.VisualizeOccludedPrimitives 1

命令主要用来判断场景中哪些遮挡掉的物体是被渲染的。

绿色的框就是没有绘制的对象.,如果有Actor在遮挡后面但是并没有被绿色的框画出来,这时候引擎认为这个Actor是可见的,造成消耗。这种情况一般是边界(Bounds)设置太大,一些非Root Motion的动画要注意。当Actor从A点移动到B点,边界会自动变大。就可能出现Actor 在遮挡物体后,但引擎仍然认为Actor是可见的并将它绘制出来。



粒子优化:

StatParticle


把占屏幕面积较大的,靠视点较近的,半透明较多的,材质复杂的,边界盒较大的,粒子数量多的进行集中优化。离视点较远的,可以使用LOD减少粒子绘制。当GPU进行立体渲染(Stereo Rendering)的时候,当视点越近,视差看到位移的位置就越远。离视点近的粒子很容易出错。引擎里的粒子大多数都是面向摄像机的一个片。当引擎进行立体渲染的时候,粒子片总是朝向左边摄像机。这时候右眼摄像机就出现了视差错误。离视点越近的粒子,立体化渲染时错误越明显。为了避免这种错误,可以把粒子做成实体模型。



后期优化:

下面是一组后期优化组合:

Post processingsetting

Scene color

Fringe intensity 0

Grain intensity 0

Color gradingintersity 0

Bloom setting

LPV 0

Ambient occlusion 0

DOF Method Gaussian0

Motion blur all 0

AA FXAA

SSR 0 Max roughness0.01

Ambient cubemap 0



Profiler

最后可以使用Profiler将数据捕获到磁盘上进行分析。


(六)可能遇到的问题和优化方法


最常见问题的原因包括:

测试环境不合适,比如灯光没构建。

双目渲染Actor太多,多材质ID

模型面数太多并且没有使用LOD,没有合理使用剔除

灯光类型使用没有规划,大面积动态投射阴影

大面积使用透明

HMD(头显)刷新频率



使用的灯光类型

构建 VR 项目时使用静态光照 和 光照图。如需使用动态光照,应尽量减少动态灯光的数量。如场景为室外,须将定向光照设为动态而非静态,然后开启级联阴影贴图(CSM)并尽量进行简单设置,即可生成阴影。



VR & VFX

在 VR 项目中多数情况下,需要使用静态网格体替代 2D 粒子模拟 VFX(如爆炸或烟雾拖尾)。近场特效或离摄像机非常近的特效在 VR 项目中效果上佳,但特效须由静态网格体粒子组成。



VR 和透明度

在 3D 图形渲染中,透明度的开销非常之大,因为每帧都需对其进行整体再次求值,以确保未发生变化。正因为再次求值的存在,VR 项目中透明度的渲染开销极大,大于其带来的效果增益。然而,使用 DitherTemporalAA 材质函数可解决解决这一难点。此材质函数将使材质拥有外观上的透明度,并避免常见透明度问题(如自我排序)。



多边形减面

在 VR 游戏中,玩家观察的自由度更高,执行减面操作可能导致玩家看到不应该看到的物体,因此不能进行此操作。



阴影投影

去掉大部分动态着色器(DynamicShader),

用BP控制角色脚步离地面远近来缩放脚下阴影片面大小。

Reflection Capture  减少 尽量不要重叠

关掉场景SSR  用材质模拟SSR效果

打开SM联级动态阴影



创造性作假:

三角面:

远处mattinpaiting

投影面片,渲染在贴图上


使用PrecomputedVisibilityVolume(预遮挡计算)

遮挡较多的地方可以大幅度提高渲染效率



使用CullDistanceVolume(裁剪体积)

根据Mesh在屏幕上所占像素尺寸裁剪模型



内存分配

CUP RENDER瓶颈

stat scenerendering

材质ID太多

重用材质贴图,尽量把同一材质物体合成为一个物体

actor太多,如果材质复杂这个因素还会加成

合物体,尤其是中远处

每个actor上的feature太多,比如增加投影的属性,增加custom depth的属性

太多灯光投影(这里投影的消费来自于需要计算哪些物体需要被投影)

除了以上的优化手段,有更多规范需要在制做之前进行测试并制定规范。


比如目标硬件是什么?美术在制做原型的时候就去设置一些美术标准,根据标准来做,后期再做比较统一的优化,这样效率可能会比较高一点。在做了基本的性能优化和分析后,接下来更进一步的就要进行美术迭代资源了做LOD,做剔除,调整渲染参数,优化材质指令。等等VR既需要表现好的的效果,又要更高的流畅度,同时VR本身的开销又很高,所以对优化的要求就更大。本文粗略的整理了开VR项目中对于VR性能优化的一些思路流程和技巧。希望本文的分享能对您VR项目的优化有一点点的帮助。


(后一篇文章将把文中流程整理成简表供大家参考)


点击一下
立即阅读相关好文章


》谈贪婪设计



这么做设计才好玩


核心设计分析

......

近期热文

【VR项目开发系列】使用UE4开发VR项目_性能优化(一)_常用工具

“你好,这里有一场翻译大赛等你参加” ——腾讯GAD VR/AR有奖翻译大赛



举报 | 1楼 回复

友情链接