看虚幻引擎技术大神分享烧脑干货《克服VR眩晕之帧数:提升UE4内容实时渲染效率》

在10月24日精彩落幕的2015创领发现vrday的活动中,主办方创领发现(uccvr)有幸邀请到了虚幻引擎的原厂技术大牛来现场与各位vr相关的制作人/开发者进行面对面的交流与分享。下面让我们来仔细解读一下该场分享的技术内容。
vr已经成为了当今最火热的一个话题,带上头盔之后,从此进入一个奇妙的世界,在这里你不再是观众,你参与这个世界发生的每一件事件。整个世界从此与众不同。在赛道上飞驰,在战场上纵横。
但是生理机制让我们的大脑在身体并没有移动,而视觉在不断告诉我正在飞速前行的迷惑中产生了晕眩。如何解决因为vr而产生的眩晕,就成为每一位设计师需要面对的问题。
引起vr眩晕有很多原因,比如设计上的,技术上的。渲染的帧数高低必定是其中一个最主要的原因之一。关于ue4里对vr内容的优化方法和思路大部分是和传统的3d游戏优化是一致的,有部分是vr尤其相关的。接下来就以oculus为平台和大家一起分享一下在ue4里常见内容的一些设置和优化的思路和方法。
首先我们来看一个优化过程的实例,先有个大概的了解。打开一个ue4下载的项目,particlecave,vrpreview,带上眼镜就能体验了,对,就这么简单,虽然说这个并不是一个针对vr的项目。
这里做了一些简单的设置:
1.发现摄像机是以预设轨道在飞,而且明显感觉帧率不高,哦,好晕。为了比较方便衡量接下来优化,我做了一些摄像机的设置,让摄像机开始游戏后固定在一个我认为帧数最低的画面。
2.确保帧数没有被限制住,关闭垂直同步,把最高帧数限制上限提高好了,再run一下,固定住了,转转头可以,真的挺卡的。
再接个命令证实一下,最直接和gpu渲染效率有关的就是分辨率。
hmdsp10054fps
帧数立马提高不少,果然是gpu渲染瓶颈!
降低渲染品质
adjustscalabilitytomedium72fps
成功了?还没有哦,这个太暴力了,这个肯定不是最优的优化结果了。因为肯定有些可以进一步做大量的优化,有些和视觉相关比较大的调整可以提高质量。而非粗暴的都调低了,那接下来就得找原因了。
打开gpuprofiling:(ctrl+shift+,)
看下最大的gpu开销在哪里:
basepass:deferreddecals
lighting:reflectionenvironment:
translucency:postprocessing:
从最大开销的几个点入手:
basepass:敲入几个渲染选项命令行:
r.earlyzpass1:增加drawcalls和一部分gpu的消耗,但大大降低basepass的消耗
关闭了一些不需要的pp效果
一套最优pop设置组合:
postprocessingsetting:
scenecolor;
fringeintensity0
grainintensity0
colorgradingintensity0
bloomsetting
lpv0
ambientocclusion0
dofmethodgaussian,其他参数全部0
motionblurall0
aafxaa
ssr0maxroughness0.01
ambientcubemap0
再vrpreview,
嗯,还是75,当然了,dk2上顶格是75,再优化看不出效果
13.39ms75fps
把品质调高成highscalabilityhigh,还是75,哈哈,没问题!
现在算优化完了吧?其实还可以再优化,这时候的优化就是以尽量提升画质但不降低帧数为目标。
看看哪些还可以优化的?当然有!之前的translucency花费好高。
viewmode:shadecomplexity好红,一堆overdraw
decal的花费也很高,statscenerendering,decalsinview
环境反射的花费很高:选中spherereflectioncapture,看一下总共有几个,观察他们影响范围是否重叠严重。
vertexintensity:好密啊。高密度的三角面几乎看上去就像一个实体了,一个三角面的大小在屏幕上的面积小于2*2个像素就会极大的增加开销。
还有particle。
现在基本上已经定位到可执行层面的原因了,一些原因也已经通过可接受的渲染参数调整解决了;另外一些就必须要artist来优化assets本身了。哪些工作最快,质量损失最小,能够换其他更能提升品质的选项。
启示他们并不需要这么多面,assets的优化需要更多的时间。把scaleability有些选项提升到epic,当然他们并不是全部。
一些引起drawcall数量多的原因:
同屏看到的actor太多,如果材质复杂这个因素还会加成。合并actor,尤其是中远处
材质id太多(orsection;meshelements)。重用材质贴图,尽量把同一材质物体合成为一个物体
每个actor上的feature太多。主要是增加投影的属性,增加customdepth的属性
太多灯光投影(这里投影的消费来自于需要计算哪些物体需要被投影)
meshdrawcall往往是个大头,meshid的数量可以在statistics统计可以很方便的查看,从经验判断哪些资源制作不合理。
关于actor设置feature会增加drawcall数的是投影和customdepth,可以通过一些工具来检查这些设置。使用propertymatrix来过滤,检查,并修改。
另外一个经常使用的查找原因的方法排除法:
通过隐藏各种元素,寻找哪个是导致drawcall数量的大头
记得隐藏hud,有的时候hud也是个大头之一。
showflag.slate1
如果是gpu瓶颈,最快速的验证方式就是改变分辨率,降低分辨率可以极大提高帧数。为了抵消畸变纠正而产生的图像模糊,或者分辨率的丢失,在渲染的的buff里往往是实际屏幕尺寸的120-130%,这样增加了图像的锐利度,但降低了渲染的速度。

hmdsp全称是hmd的screenpercentage,这个参数就是来修改渲染buff的尺寸的,hmdsp120是默认值,改成100看看。

如果像刚才例子看到的,帧数有大幅度的提高,那就是gpu负担太大的问题了,如果分辨率的改变对于帧数影响不大,很有可能是因为面太多了。
对这些内容重点做检查,看看有没有超标的现象出现:
分辨率
hmdsp
投影贴图
面数/点数(灯光的多少,阴影的设置,多少物体)
lod,关闭shadow,灯光屏幕面积
面数密度太高,高到一个三角面小于2*2的像素,这个往往发生在远处物体
点处理,点太多
点动画的shader太复杂
tessellation太复杂
太多uv,太多sg
查看staticmesheditor里点和面数的差别是否大
点没有合并等
viewcost(hzbocclusionculling)
precumputedvisibilityvolume
scenecostgpuparticlesimulation
材质复杂度
qualityswitch,sin,pow,cos,pide,noise很费
由于texture太多,太大texturecaching反复的pageinandoutof显存
遮挡的culling计算
precumputedvisibilityvolume
延迟灯光
当使用lightingfunction,ies,接受投影,区域光,复杂shadingmodes的时候会变得更贵。
反射ssr有问题,关掉。后期,ao,很费。
知道哪里有问题了,接下来就可以着手行动了,但之前做个目标规划还是可以事半功倍的。最小化图像质量妥协,是一种有的放矢的妥协策略。比如高质量的阴影对于高品质的抗锯齿而言对于最终项目实际的表达效果次要。减小阴影品质来换取高品质aa就是一种有的放矢的妥协策略。因此尽量大的减小不是非常关心的渲染品质部分,增加更可见的渲染品质部分。

从容易做起,从开关一些渲染选项,品质参数调整,到直接删东西,优化一个用到几百次的物件,这些都是立竿见影的方式,这样可以做允许的时间计划内完成目标,如果有更多时间和预算可以对相对低性价比的。目标75帧是必须的,不要说68,70,都不行,必须75,做实际体验中有很大区别。
最常见的问题所在:
测试环境不合适,灯光没有build
actor或者材质id太多
面太多,没有任何的lod设置
灯光使用没有节制:各种动态投影,灯光类型随意
没有合理的设置cull的条件
透明太多
postprocess太高级了
这些原因又互相影响,一方面的增加也会增加另外方面的开销:
其他一些vr的特有行为:
vr需要畸变色差纠正
vr需要双屏
vr需要更大的渲染分辨率
vr需要传递传感器信息
比如对于oculus部分是在驱动层级做掉了,比如如何纠正畸变,如何双屏,如何传递传感器信息。对于传感器信息和视频匹配的准确性,以及渲染的屏幕覆盖率,在ue4里是可以根据需要来修改的,除了这些,其他就和以往的优化思路一致了。
创建测试环境,找原因:
testinginastableenviroment
runstandalonegame
usepauseorslomo0.001topreventrandomnumbers
measuringfewtimes
确保帧数不封顶
s.vsync0
s.maxfps
了解瓶颈
gpu瓶颈
profilegpu(ctol+shift+,)
分辨率
hmdsp
投影贴图
面数/点数(灯光的多少,阴影的设置,多少物体)
lod,关闭shadow,灯光屏幕面积
面数密度太高,高到一个三角面小于2*2的像素,这个往往发生在远处物体
点处理,点太多
点动画的shader太复杂
tessellation太复杂
太多uv,太多sg
查看staticmesheditor里点和面数的差别是否大
点没有合并等
viewcost(hzbocclusionculling)
precumputedvisibilityvolume
scenecostgpuparticlesimulation
材质复杂度
qualityswitch,sin,pow,cos,pide,noise很费
遮挡的culling计算
precumputedvisibilityvolume
延迟灯光
当使用lightingfunction,ies,接受投影,区域光,复杂shadingmodes的时候会变得更贵
反射ssr有问题,关掉,后期ao,很费
cup瓶颈,cupgame瓶颈
statgame
ai复杂度
bp
raycast
物理
内存分配
cuprender瓶颈
statscenerendering
材质id太多
重用材质贴图,尽量把同一材质物体合成为一个物体
actor太多,如果材质复杂这个因素还会加成
合物体,尤其是中远处
每个actor上的feature太多,比如增加投影的属性,增加customdepth的属性
太多灯光投影(这里投影的消费来自于需要计算哪些物体需要被投影)

找到瓶颈的方法:
statunit
disable一些stuff,然后看效率上的区别
一些可调的showflag
开关屏幕反射
开关ao
开关aa
开关bloom
开关延迟灯光
开关灯光类型
开关动态阴影
开关gi
开关后期
开关环境反射
开关折射
开关贴画
开关半透明
开关tessellation
viemode
profilegpu
profilecpu
statgame
statscenerendering
profiler
后期优化首选项:
scenecolorfringe;
ambientcubemap,
imagebasedlensflares;
lpvoff;
grainintensity,
dofoff,
ssroff,
orroughness0.01;
motionbluroff
最后选择的参数需要应用到deviceprofiles里或者bp里:
减小shader的instruction的数量:
减少texturesample的数量:把经常使用到同一个物体上的pattern合在一张贴图上;去掉对质量影响很小的贴图,比如specular,ao在实际情况中平衡来使用qualityswitch,sin,pow,cos,pide,noise,多向量的计算总是大于单向量的计算。
ue4里由于使用了延迟灯光,所以灯光的优化比前向渲染方便的多。最快速最有效的方法:使用静态光源。如果使用的是动态光减小lightingcull,半径,衰减,zinterssection,cone大小角度。总之尽量减少重叠。
投影的开销最大往往不是来自于pixelshader,而是来自于被投影的mesh面数太多,还会被灯光数量,投影物体数量放大。
关闭投影的灯光;减小范围或张角;减面,加lod
r.shadow.maxresolution
创造性作假:
三角面:
远处mattinpaiting
投影面片,画在贴图上
一个作品的优化不是一朝一夕的事情,需要确定目标配置:确定最低配置,配置范围小,这样的优化才更有针对性,并且学会在开阔的视野在设计时需要巧妙的避免不必要的内容,学会如何制定budget:质量优先驱动;快速原型制作;分析制定。
对内容制作者前期的培训花费是值得的,完成这些工作之后,一个高品质的vr作品就会诞生。
2015创领发现vr/ar行业大赛,举办的宗旨是为了更好的寻找和发现优秀的vr/ar制作人/开发者,我们将围绕着与开发相关的任何需求,打造国内最专业的vr/ar社区与孵化平台。大家可以登录www.uccreate.com官方网站进行提前报名,不限于demo或者成品,大赛截止时间安排在于明年3月,感兴趣的伙伴们可以抓紧啦!