克服VR眩晕之帧数:提升UE4内容实时渲染效率
VR已经成为了当今最火热的一个话题,带上头盔之后,从此进入一个奇妙的世界,在这里你不再是观众,你参与这个世界发生的每一件事件。整个世界从此与众不同。在赛道上飞驰,在战场上纵横
但是生理机制让我们的大脑在身体并没有移动,而视觉在不断告诉我正在飞速前行的迷惑中产生了晕眩。如何解决因为VR而产生的眩晕,就成为每一位设计师需要面对的问题。
引起VR眩晕有很多原因啦,比如设计上的,技术上的。渲染的帧数高低必定是其中一个最主要的原因之一。关于UE4里对VR内容的优化方法和思路大部分是和传统的3D游戏优化是一致的,有部分是VR尤其相关的。接下来就以oculus为平台和大家一起分享一下在UE4里常见内容的一些设置和优化的思路和方法.
首先我们来看一个优化过程的实例,先有个大概的了解。打开一个UE4下载的项目,particle cave, VR preview,带上眼镜就能体验了,对,就这么简单,虽然说这个并不是一个针对VR的项目。
这里做了一些简单的设置
1、发现摄像机是以预设轨道在飞,而且明显感觉帧率不高,哦,好晕。为了比较方便衡量接下来优化,我做了一些摄像机的设置,让摄像机开始游戏后固定在一个我认为帧数最低的画面。
2、确保帧数没有被限制住,关闭垂直同步,把最高帧数限制上限提高好了,再run一下,固定住了,转转头可以,hmm。。真的挺卡的
再接个命令证实一下,最直接和GPU渲染效率有关的就是分辨率喽
HMD SP 100 54FPS
帧数立马提高不少,果然是GPU渲染瓶颈
降低渲染品质
Adjust scalability to medium 72FPS
成功了? 还没有哦,这个太暴力了
这个肯定不是最优的优化结果了。因为肯定有些可以进一步做大量的优化,有些和视觉相关比较大的调整可以提高质量。而非粗暴的都调低了,那接下来就得找原因了
打开GPUprofiling: (Ctrl+Shift+,)
看下最大的GPU开销在哪里
- Base pass: Deferred Decals
- Lighting: ReflectionEnvironment:
- Translucency: Postprocessing:
从最大开销的几个点入手
BASEPASS: 敲入几个渲染选项命令行:
r.Earlyzpass 1:增加draw calls和一部分GPU的消耗,但大大降低base pass的消耗
关闭了一些不需要的PP效果
一套最优POP设置组合:
- Postprocessing setting:
- Scene color;
- Fringe intensity 0
- Grain intensity 0
- Color grading intensity 0
- Bloom setting
- LPV 0
- Ambient occlusion 0
- DOF Method Gaussian, 其他参数 全部 0
- Motion blur all 0
- AA FXAA
- SSR 0 MAX roughness 0.01
- Ambient cubemap 0
再VR preview,
嗯,还是75,当然了,DK2上顶格是75,再优化看不出效果
13.39ms 75FPS
把品质调高成high Scalability high,还是75,哈哈,没问题!
现在算优化完了吧? 其实还可以再优化,这时候的优化就是以尽量提升画质但不降低帧数为目标。
看看哪些还可以优化的? 当然有 !之前的Translucency花费好高
Viewmode: shade complexity 好红, 一堆overdraw
Decal的花费也很高, Stat scenerendering, decals in view
环境反射的花费很高: 选中sphere reflection capture, 看一下总共有几个,观察他们影响范围是否重叠严重
Vertex intensity: 好密啊。高密度的三角面几乎看上去就像一个实体了, 一个三角面的大小在屏幕上的面积小于2*2个像素就会极大的增加开销
还有Particle 。
现在基本上已经定位到可执行层面的原因了,一些原因也已经通过可接受的渲染参数调整解决了;另外一些就必须要artist来优化Assets本身了。
哪些工作最快,质量损失最小,能够换其他更能提升品质的选项。
启示他们并不需要这么多面,assets的优化需要更多的时间。把scaleability有些选项提升到EPIC,当然他们并不是全部
一些引起DRAW CALL数量多的原因
- 同屏看到的Actor太多,如果材质复杂这个因素还会加成。 合并Actor,尤其是中远处
- 材质ID太多(or Section; Mesh elements)。重用材质贴图,尽量把同一材质物体合成为一个物体
- 每个actor上的feature太多。主要是增加投影的属性,增加custom depth的属性
- 太多灯光投影(这里投影的消费来自于需要计算哪些物体需要被投影)
MESH DRAW CALL往往是个大头,MESH ID 的数量可以在STATISTICS统计可以很方便的查看,从经验判断哪些资源制作不合理
关于ACTOR设置feature会增加DRAW CALL数的是投影和custom depth,可以通过一些工具来检查这些设置。使用property matrix来过滤,检查,并修改
另外一个经常使用的查找原因的方法排除法
通过隐藏各种元素,寻找哪个是导致DRAW CALL数量的大头
记得隐藏HUD,有的时候HUD也是个大头之一
Showflag.slate 1
如果是GPU瓶颈,最快速的验证方式就是改变分辨率,降低分辨率可以极大提高帧数。为了抵消畸变纠正而产生的图像模糊,或者分辨率的丢失,在渲染的的buff里往往是实际屏幕尺寸的120-130%,这样增加了图像的锐利度,但降低了渲染的速度。
HMD SP全称是HMD 的screen percentage, 这个参数就是来修改渲染buff的尺寸的,HMD SP 120是默认值,改成100看看。
如果像刚才例子看到的,帧数有大幅度的提高,那就是GPU负担太大的问题了,如果分辨率的改变对于帧数影响不大,很有可能是因为面太多了。
对这些内容重点做检查,看看有没有超标的现象出现
- 分辨率
- HMD SP
- 投影贴图
- 面数/点数(灯光的多少,阴影的设置,多少物体)
- LOD,关闭shadow,灯光屏幕面积
- 面数密度太高,高到一个三角面小于2*2的像素,这个往往发生在远处物体
- 点处理,点太多
- 点动画的shader太复杂
- tessellation太复杂
- 太多UV,太多SG
- 查看staticmesh editor里点和面数的差别是否大
- 点没有合并等
- view cost(HZB occlusion culling)
- Precumputed visibility volume
- Scene cost GPU particle simulation
- 材质复杂度
- quality switch,sin, pow, cos, divide, Noise很费
- 由于Texture 太多,太大 Texture caching反复的page in and out of 显存
- 遮挡的culling计算
- Precumputed visibility volume
- 延迟灯光
当使用lighting function,IES,接受投影,区域光,复杂shading modes的时候会变得更贵
反射ssr有问题,关掉。 后期, AO,很费
知道哪里有问题了,接下来就可以着手行动了,但之前做个目标规划还是可以事半功倍的。
最小化图像质量妥协,是一种有的放矢的妥协策略。比如高质量的阴影对于高品质的抗锯齿而言对于最终项目实际的表达效果次要。减小阴影品质来换取高品质AA就是一种有的放矢的妥协策略。因此尽量大的减小不是非常关心的渲染品质部分,增加更可见的渲染品质部分。
从容易做起,从开关一些渲染选项,品质参数调整,到直接删东西,优化一个用到几百次的物件,这些都是立竿见影的方式,这样可以做允许的时间计划内完成目标,如果有更多时间和预算可以对相对低性价比的。
目标75帧是必须的,不要说68,70,都不行,必须75,做实际体验中有很大区别。
最常见的问题所在
- 测试环境不合适,灯光没有build
- Actor或者材质ID太多
- 面太多,没有任何的LOD设置
- 灯光使用没有节制: 各种动态投影,灯光类型随意
- 没有合理的设置CULL的条件
- 透明太多
- Postprocess太高级了
这些原因又互相影响,一方面的增加也会增加另外方面的开销
其他一些VR的特有行为
- VR 需要畸变色差纠正
- VR需要双屏
- VR需要更大的渲染分辨率
- VR需要传递传感器信息
比如对于oculus部分是在驱动层级做掉了,比如如何纠正畸变,如何双屏,如何传递传感器信息。
对于传感器信息和视频匹配的准确性,以及渲染的屏幕覆盖率,在UE4里是可以根据需要来修改的,除了这些,其他就和以往的优化思路一致了。
创建测试环境。找原因
- Testing in a stable enviroment
- run Standalone game
- use pause or slomo 0.001 to prevent random numbers
- Measuring few times
- 确保帧数不封顶
- s.Vsync 0
- s.MaxFPS
- 了解瓶颈
- GPU瓶颈
- profileGPU(ctol+shift+,)
- 分辨率
- HMD SP
- 投影贴图
- 面数/点数(灯光的多少,阴影的设置,多少物体)
- LOD,关闭shadow,灯光屏幕面积
- 面数密度太高,高到一个三角面小于2*2的像素,这个往往发生在远处物体
- 点处理,点太多
- 点动画的shader太复杂
- tessellation太复杂
- 太多UV,太多SG
- 查看staticmesh editor里点和面数的差别是否大
- 点没有合并等
- view cost(HZB occlusion culling)
- Precumputed visibility volume
- Scene cost GPU particle simulation
- 材质复杂度
- quality switch,sin, pow, cos, divide, Noise很费
- 遮挡的culling计算
- Precumputed visibility volume
- 延迟灯光
- 当使用lighting function,IES,接受投影,区域光,复杂shading modes的时候会变得更贵
- 反射ssr有问题,关掉,后期AO,很费
- cup瓶颈,CUP GAME瓶颈
- stat game
- AI复杂度
- BP
- raycast
- 物理
- 内存分配
- CUP RENDER瓶颈
- stat scenerendering
- 材质ID太多
- 重用材质贴图,尽量把同一材质物体合成为一个物体
- actor太多,如果材质复杂这个因素还会加成
- 合物体,尤其是中远处
- 每个actor上的feature太多,比如增加投影的属性,增加custom depth的属性
- 太多灯光投影(这里投影的消费来自于需要计算哪些物体需要被投影)
找到瓶颈的方法
- stat unit
- disable一些stuff,然后看效率上的区别
- 一些可调的show flag
- 开关屏幕反射
- 开关AO
- 开关AA
- 开关bloom
- 开关延迟灯光
- 开关灯光类型
- 开关动态阴影
- 开关GI
- 开关后期
- 开关环境反射
- 开关折射
- 开关贴画
- 开关半透明
- 开关tessellation
- viemode
- ProfileGPU
- ProfileCPU
- stat game
- stat scenerendering
- Profiler
后期优化首选项:
- Scene color fringe;
- ambient cubemap,
- image based lens flares;
- LPV off;
- Grain intensity,
- DOF off,
- ssr off,
- or roughness 0.01;
- Motion blur off
最后选择的参数需要应用到DEVICE PROFILES里或者BP里
减小 shader的 instruction的数量
减少Texture sample的数量:把经常使用到同一个物体上的Pattern合在一张贴图上;去掉对质量影响很小的贴图,比如Specular,AO在实际情况中平衡来使用
使用quality switch,sin, pow, cos, divide, Noise,多向量的计算总是大于单向量的计算
UE4里由于使用了延迟灯光,所以灯光的优化比前向渲染方便的多。最快速最有效的方法:使用静态光源。
如果使用的事动态光减小 Lighting cull,半径,衰减,Z INTERSSECTION, cone大小角度。总之尽量减少重叠
投影的开销最大往往不是来自于pixel shader,而是来自于被投影的mesh面数太多,还会被灯光数量,投影物体数量放大
关闭投影的灯光;减小范围或张角;减面,加LOD
r.Shadow.MaxResolution
创造性作假:
- 三角面:
- 远处mattinpaiting
- 投影面片,画在贴图上
一个作品的优化不是一朝一夕的事情,需要确定目标配置:确定最低配置,配置范围小,这样的优化才更有针对性,并且学会在开阔的视野在设计时需要巧妙的避免不必要的内容,学会如何制定Budget:质量优先驱动;快速原型制作;分析制定
对内容制作者前期的培训花费是值得的,完成这些工作之后,一个高品质的VR作品就会诞生。