Unity GearVR游戏性能优化1

你已经决定使用Unity开发一款VR游戏,并且以Samsung GearVR作为你的目标平台。想要在这个设备上运行起来其实很容易,但是问题是,帧率实在是太低了。你的十字准星像粘住了一样,在视野的边上还会闪烁黑边,相机的移动看起来好像摄影师被踢了一样糟糕。你已经知道维持一个稳定的帧率有多重要,现在终于知道为什么了——在移动VR应用中,低于60FPS的时候不仅仅是看起来糟糕,更重要的是体验超烂。你的高端PC动辄跑到1000FPS,听起来好像搭载了个喷气机引擎,但实际上但风扇转起来的时候没有明显提升(不太理解原作者这句话的意思)。你所需要的是一个优化方法,以便让你的作品跑在移动芯片上。

GearVR环境与高效VR游戏的特点这并不是关于GearVR的一个包罗万象的性能优化介绍,这仅仅是个快速开始。在这一篇博客中,我们将讨论GearVR硬件,以及一个设计良好的移动VR程序的特点。接下来的一篇博客将介绍你已经构建好的程序怎样做性能优化。这篇博客基于Unity做优化,因为它看起来在GearVR开发者中间比较流行。但是,这里提到的概念可以应用于任何游戏引擎。

了解你的硬件在你动手找到性能瓶颈以前,应该先思考一下手机的性能特点。一般来说,移动图形管线基于一个非常快的CPU,一个非常快的GPU,它们通过一个非常慢的总线或者内存控制器连接,以及具有诸多限制的OpenGL ES驱动。GearVR运行在Samsung Note 4和Samsung Galaxy S6(估计这篇博客写的时候是这样的)。这两个产品先实际上代表了许多不同的硬件配置:

Note4有两种不同的芯片组。在南美和欧洲出售的设备基于高通骁龙Snapdragon处理器(骁龙805),而在韩国和亚洲其他地方出售的则是三星Exynos猎户座处理器(猎户座5433)。骁龙处理器有四个核心,而猎户座有八个核心。这些设备分别搭载了两种不同的GPU:高通Adreno420图形处理器和Mali-T760。

Note4可以进一步按操作系统划分。大多数设备多运行这Android 4.4.4 (KitKat),但是Android 5 (Lollipop) 已经可以获取更新了。使用Exynos猎户座处理器的Note4设备全都运行在Android 5上面。

Galaxy S6设备都基于同样的芯片组:三星猎户座处理器Exynos 7420 (搭载Mali-T760M8 GPU)。S6还存在另一个版本,Galaxy S6 Edge,但是从内部来说,它和S6是一样的。

所有的Galaxy S6都是Android 5系统。

如果这看起来比较乱的话,不要着急:尽管设备之间的硬件配置各部相同,这些设备的性能测试方法非常类似(只有一个例外,参见下面“陷阱”一节)。如果你能够使他们在一台设备上运行加快,那么在其他设备上也会加快。

对大多数移动芯片组来说,3D图形性能在这些设备有相当可靠的特点。下面列举一些使得GearVR工程变慢的原因(按严重程度排序):

场景必须依赖渲染器(例如阴影和反射)(消耗CPU/GPU)

绑定VBOs来发射draw call(消耗CPU/驱动)

透明,多通道shader,逐像素光照,其他填充大量像素的效果(消耗GPU/IO)

大型纹理加载,传送以及其他形式的内存拷贝(消耗IO/内存控制)

蒙皮动画(消耗CPU)

Unity垃圾回收限制(消耗CPU)

另一方面,这些设备具有相对较大的内存,可以塞进去大量的多边形。注意,Note4和S6都是2560x1440的显示屏,默认情况下,为了节省填充率我们渲染两个1024x1024的纹理。

了解VR环境由于VR渲染每帧都要渲染两次,每次渲染一只眼睛的图像,非常消耗硬件性能。在Unity 4.6.4p3和5.0.1p1版本中,这意味着每个draw call都要发送两次,每个mesh绘制两次,每个纹理绑定两次。还有一个比较小的开销,就是把最终的帧图像输出,包括扭曲和TimeWarp(大约2毫秒)。将来肯定还会有进一步优化的,但是目前我们卡在整个帧渲染两次。这意味着,渲染管线中一些开销最大部分的消耗是一般的游戏的两倍。

考虑到这些,下面是GearVR应用的一些合理目标:

每帧50-100次draw call

每帧50k-10k个多边形

纹理越少越好(可以使用大纹理)

脚本执行时间1-3毫秒(Unity Update())

请记住,这些并不是死限制,而是一些经验法则。

这帧画面中有3万个多边形和40个draw call

还要注意,Oclus Mobile SDK引入了一个API,可以调节CPU和GPU的使用来控制手机发热和电池消耗(示例用法查看OVRModeParams.cs)。这些方法允许你选择CPU或者GPU哪个对你的场景更重要。举例来说,如果你需要更多的draw call提交,把CPU调高(GPU调低)可能改进整体帧率。如果你忽略了设置这些值,你的程序会被严重的限制住,所以花点时间来实验是值得的。

最后,GearVR具有Oculus的异步TimeWarp技术。当你的游戏开始减慢的时候,TimeWarp基于最近的头部位置信息,提供了中间帧。它通过扭曲前一帧来匹配最近的头部位置,在掉帧的时候可以帮助你平稳过度,所以没有借口跑不到60帧。当你摇头的时候,如果你在视场边缘看到了黑色闪烁的条块,这意味着你的游戏运行的太慢了,就算TimeWarp也没有足够的帧图像来填充空白了。

面向性能的设计开发一个高性能程序的最佳方法就是预先设计好。对于GearVR应用来说,这通常意味着围绕移动设备GPU的特点来设计。

设置在开始之前,确保你的Unity工程设置为最佳性能。特别的,一定要确保设置下面的选项:

Static batching

Dynamic batching

GPU skinning

Multithreaded Rendering

Default Orientation to Landscape Left

Batching既然知道了draw call通常是GearVR程序最耗费性能的部分,那么第一步就是要把场景所需draw call尽可能少。一个draw call是一条发送给GPU使其绘制一个mesh或者一部分mesh的指令。这个操作代价最高的部分实际上是mesh本身的选择。每次游戏决定绘制一个新mesh时,这个mesh在被发送到GPU之前必须被驱动处理过。Shader必须要绑定,可能发生格式转换等等;每次一个新mesh选定之后,驱动都要使用CPU进行工作。所以当draw call发送时,最严重的开销是这个选择的过程。

然而,这也意味着,一旦一个mesh(或者更加具体的,顶点缓冲对象VBO)选择之后,我们可以花费一次选择的成本,然后对它渲染多次。只要没有新mesh(或者shader,或者纹理)被选择,这个状态会被驱动缓存下来,然后draw call的发送就快多了。为了利用这一点来提升性能,我们实际上可以把多个mesh打包成一个大的顶点数组,然后使用同一个VBO渲染它们。我们花费了一次整体mesh的选择成本,然后从包含在这个对象内部的mesh中,发送尽可能多的draw call。这个技巧叫做batching,比每个mesh都创建一个VBO的方法快的多,这也是我们进行draw call优化的基础。

包含在一个VBO中的所有mesh,为了能正确的batching,必须有相同的材质设置:相同的纹理、相同的shader,相同的shader参数。为了利用unity中的batching,实际上你需要更进一步:只有对象具有相同的材质对象指针,他们才能给正确batching。最后,下面是一些经验法则:

大纹理/纹理图集:尽可能少的使用纹理,尽可能多的把模型映射到仅有的几张大纹理上。

纹理图集

Static标志:在Unity Inspector中把从不移动物体标记成Static。

材质访问:访问Renderer.material的时候要小心。这将会复制一份材质并返回,这会把该对象排除在batching之外(因为它的材质指针不再相同了)。请使用Renderer.sharedMaterial。

确保batching打开了:在Player Settings中,确保Static Batching以及Dynamic Batching都打开了。

Unity 提供了两种方法来把mesh打包在一起: Static Batching以及Dynamic Batching。

Static Batching当你把一个mesh标记为static,你就是在告诉Unity这个对象不会移动,动画,或者缩放。Unity使用这个信息,在构建的时候自动的把共享材质的mesh打包成一个大型的mesh。有些情况下,这是一个非常重要的优化;出来打包mesh减少draw call,Unity还把变换信息记录在每个mesh的顶点位置中,所以它们就不需要在运行时变换。场景中标记为static的部分越多越好。请记住为了进行批处理该过程需要mesh具有同样的材质。

注意,因为static batching在构建时产生新的大型mesh,这会增加程序最终二进制文件的大小。这通常对GearVR开发者来说不是问题,但是如果你的游戏有好多个独立场景,并且每个场景有很多的静态mesh,加起来就会很大。另一个选项是使用StaticBatchingUtility.Combine在运行时来生成打包的纹理,而不会使你的程序体积膨胀(需要花费一次性的CPU使用和一些内存)。最后,请确保你正在使用的Unity版本支持static batching。

Dynamic BatchingUnity同样可以打包没有标记为静态的mesh,只要他们符合共享材质的需求。如果你打开了Dynamic Batching选项,这个过程几乎可以自动生成。每帧计算要打包的mesh的时候会有一些开销,但是从性能的角度来看,通常会有一个明显的提升。

其他batching问题要注意的是,有一些方法会破坏打包。渲染阴影和其他多通道shader需要一个状态转换,使得对象不能正确的打包。多通道shader也会使得mesh被提交多次,在GearVR上应该引起注意。逐像素的光照有同样的效果:在Unity4中使用默认的Diffuse着色器,投射到mesh上的每个光源都会使得mesh提交一次。这会使得draw call很快增长并超过多边形数量限制。如果你需要逐像素的光照,可以尝试把Quality Setting窗口中同时光源的数量设置成1。最接近的光源会以逐像素方式进行渲染,附近的光照将会使用球谐方法进行计算。要更好的话,删除所有像素光照,使用光照探测器。还要注意的是,batching通常对蒙皮的mesh不起作用。透明物体必须以一定的顺序进行渲染,因此batch效果不太好。

好消息是,你可以在编辑器中测试和调试batching。Unity Profiler和Game窗口中的Stats面板都可以告诉你发送了多少次draw call以及batching节省了多少资源。如果你的几何体使用很少数量的纹理,那你就不用实例化材质、标记static对象,你的场景也会很高效。

Transparency, Alpha Test, and Overdraw如上所述,移动设备的芯片通常是“fill-bound”,意味着填充像素的花销是一帧中最昂贵的部分。降低填充花销的关键是每个屏幕上的像素都只渲染一次。多通道的shader,逐像素光照效果(例如Unity默认的specular着色器),还有透明物体都需要把它们涉及到的像素渲染多次。类似这些像素太多的话,将会充满总线。

做为一个最佳实践,尝试把Quality Settings中的Pixel Light Count限制到1.如果你使用了多余一个的逐像素光源,确保你知道他们要作用于那个几何体,以及渲染该几何体多次的代价。类似的,让透明物体尽量小点。因为主要的开销是渲染像素,所以物体占据的像素越小,帧渲染完成的越快。注意像烟雾这样的透明特效,可能占据比你想象中更多的像素。

还要注意的是,在移动设备上绝对不要使用alpha测试着色器,例如Unity的cutout着色器。Alpha测试的操作(还要clip(),或者像素着色器中显式的discard操作)强制一些普通的移动设备GPU取消了硬件填充优化,使得渲染非常慢。Discard像元的操作会导致大量难看的走样(aliasing),尽量使用不透明物体。

Performance Throttling在你测试场景性能之前,你需要确保你设置了CPU和GPU的限制。因为VR游戏的性能达到了移动设备的界限,你必须在CPU和GPU之间设置一个权重。如果你的游戏偏重CPU,为了让CPU满速运行,你可以调低GPU。如果偏重GPU可以做相反的操作。如果你的游戏已经很流畅了,可以把两者都调低,这样能够节省电量,延长用户在线时间。更多的信息请查看Mobile SDK documentation中的“Power Management”部分。

重要的是,在你开始任何类型的性能测试之前都要设置CPU和GPU限制。如果这些值初始化失败的话,程序将会在默认设置非常低的环境中运行。因为大多数GearVR应用一般都会偏重CPU,所以通常会把CPU调整的高于GPU。OVRModeParams.cs中有一个关于怎样初始化节流设置的例子,你可以复制粘贴到游戏启动脚本中。

Gotchas陷阱在考虑性能优化的时候,你还应该记住下面这些技巧:

有一个特殊的设备比其他都要慢,具体来说就是基于骁龙的Note 4运行Android 5的系统,图形驱动在draw call方面似乎有一个倒退。对于draw call已经达到限制的游戏,会发现这个问题非常严重(draw call时间增加了20%),会导致正常的渲染管线停滞并且整体帧率下降。我们正和三星和高通努力解决这个问题。运行Android4.4系统的骁龙处理器的Note 4设备,还有Exynos处理器的Note 4和S6设备,都不受此影响。

尽管对CPU和GPU进行节流很大程度上减轻了手机的发热,对重量级的应用来说,在长时间运行的时候导致设备过热仍然是可能的。这种情况发生时,手机会警告用户,然后降低处理器的频率,会导致VR应用无法使用。如果你正在做性能测试和解决发热问题,请让手机先休息五分钟再继续。

Unity 4免费版不支持static batching和Unity Profiler。Unity 5的个人版已经有了。

S6不支持各向异性纹理过滤。

到此结束。下一篇,我们将讨论怎样调试真实的性能问题。

联系方式:0755-81699111

课程网址: http://www.vrkuo.com/course/vr.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • 你已经决定使用Unity开发一款VR游戏,并且以Samsung GearVR作为你的目标平台。想要在这个设备上运行...
    浪尖儿阅读 1,277评论 0 5
  • 原文地址 http://www.fx114.net/qa-75-172454.aspx 使用Profiler工具...
    IongX阅读 5,822评论 1 11
  • 转载http://wetest.qq.com/lab/view/315.html 移动平台硬件架构 移动平台无论是...
    李嘉的博客阅读 1,677评论 0 4
  • 早上6点03分起床,7点30送大儿子陈燃上学。8点到南方国际店参加早会,已经有一个月未参加早会了。发现早会又回到了...
    31c47a10aded阅读 134评论 0 0
  • 射线:3D世界中一个点向一个方向发射的一天无终点的线,在发射轨迹中鱼其他物体发生碰撞时,他将停止发射。注意:这条线...
    IT白鸽阅读 437评论 0 0