目前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逻辑线程分析
(六)可能遇到的问题和优化方法
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项目参考请参考《基于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渲染线程问题大多数可能性是像素着色器(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也很耗费资源。
引起Draw Call 数量增多的原因
过多灯光投影(检查投影计算来自哪些物体被投影)
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有奖翻译大赛
友情链接