Unity GearVR游戲性能優(yōu)化1

你已經決定使用Unity開發(fā)一款VR游戲,并且以Samsung GearVR作為你的目標平臺。想要在這個設備上運行起來其實很容易,但是問題是,幀率實在是太低了。你的十字準星像粘住了一樣,在視野的邊上還會閃爍黑邊,相機的移動看起來好像攝影師被踢了一樣糟糕。你已經知道維持一個穩(wěn)定的幀率有多重要,現在終于知道為什么了——在移動VR應用中,低于60FPS的時候不僅僅是看起來糟糕,更重要的是體驗超爛。你的高端PC動輒跑到1000FPS,聽起來好像搭載了個噴氣機引擎,但實際上但風扇轉起來的時候沒有明顯提升(不太理解原作者這句話的意思)。你所需要的是一個優(yōu)化方法,以便讓你的作品跑在移動芯片上。

GearVR環(huán)境與高效VR游戲的特點

這并不是關于GearVR的一個包羅萬象的性能優(yōu)化介紹,這僅僅是個快速開始。在這一篇博客中,我們將討論GearVR硬件,以及一個設計良好的移動VR程序的特點。接下來的一篇博客將介紹你已經構建好的程序怎樣做性能優(yōu)化。這篇博客基于Unity做優(yōu)化,因為它看起來在GearVR開發(fā)者中間比較流行。但是,這里提到的概念可以應用于任何游戲引擎。

了解你的硬件

在你動手找到性能瓶頸以前,應該先思考一下手機的性能特點。一般來說,移動圖形管線基于一個非常快的CPU,一個非??斓腉PU,它們通過一個非常慢的總線或者內存控制器連接,以及具有諸多限制的OpenGL ES驅動。GearVR運行在Samsung Note 4和Samsung Galaxy S6(估計這篇博客寫的時候是這樣的)。這兩個產品先實際上代表了許多不同的硬件配置:

  • Note4有兩種不同的芯片組。在南美和歐洲出售的設備基于高通驍龍Snapdragon處理器(驍龍805),而在韓國和亞洲其他地方出售的則是三星Exynos獵戶座處理器(獵戶座5433)。驍龍?zhí)幚砥饔兴膫€核心,而獵戶座有八個核心。這些設備分別搭載了兩種不同的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系統。

如果這看起來比較亂的話,不要著急:盡管設備之間的硬件配置各部相同,這些設備的性能測試方法非常類似(只有一個例外,參見下面“陷阱”一節(jié))。如果你能夠使他們在一臺設備上運行加快,那么在其他設備上也會加快。

對大多數移動芯片組來說,3D圖形性能在這些設備有相當可靠的特點。下面列舉一些使得GearVR工程變慢的原因(按嚴重程度排序):

  • 場景必須依賴渲染器(例如陰影和反射)(消耗CPU/GPU)
  • 綁定VBOs來發(fā)射draw call(消耗CPU/驅動)
  • 透明,多通道shader,逐像素光照,其他填充大量像素的效果(消耗GPU/IO)
  • 大型紋理加載,傳送以及其他形式的內存拷貝(消耗IO/內存控制)
  • 蒙皮動畫(消耗CPU)
  • Unity垃圾回收限制(消耗CPU)

另一方面,這些設備具有相對較大的內存,可以塞進去大量的多邊形。注意,Note4和S6都是2560x1440的顯示屏,默認情況下,為了節(jié)省填充率我們渲染兩個1024x1024的紋理。

了解VR環(huán)境

由于VR渲染每幀都要渲染兩次,每次渲染一只眼睛的圖像,非常消耗硬件性能。在Unity 4.6.4p3和5.0.1p1版本中,這意味著每個draw call都要發(fā)送兩次,每個mesh繪制兩次,每個紋理綁定兩次。還有一個比較小的開銷,就是把最終的幀圖像輸出,包括扭曲和TimeWarp(大約2毫秒)。將來肯定還會有進一步優(yōu)化的,但是目前我們卡在整個幀渲染兩次。這意味著,渲染管線中一些開銷最大部分的消耗是一般的游戲的兩倍。

考慮到這些,下面是GearVR應用的一些合理目標:

  • 每幀50-100次draw call
  • 每幀50k-10k個多邊形
  • 紋理越少越好(可以使用大紋理)
  • 腳本執(zhí)行時間1-3毫秒(Unity Update())

請記住,這些并不是死限制,而是一些經驗法則。

這幀畫面中有3萬個多邊形和40個draw call

還要注意,Oclus Mobile SDK引入了一個API,可以調節(jié)CPU和GPU的使用來控制手機發(fā)熱和電池消耗(示例用法查看OVRModeParams.cs)。這些方法允許你選擇CPU或者GPU哪個對你的場景更重要。舉例來說,如果你需要更多的draw call提交,把CPU調高(GPU調低)可能改進整體幀率。如果你忽略了設置這些值,你的程序會被嚴重的限制住,所以花點時間來實驗是值得的。

最后,GearVR具有Oculus的異步TimeWarp技術。當你的游戲開始減慢的時候,TimeWarp基于最近的頭部位置信息,提供了中間幀。它通過扭曲前一幀來匹配最近的頭部位置,在掉幀的時候可以幫助你平穩(wěn)過度,所以沒有借口跑不到60幀。當你搖頭的時候,如果你在視場邊緣看到了黑色閃爍的條塊,這意味著你的游戲運行的太慢了,就算TimeWarp也沒有足夠的幀圖像來填充空白了。

面向性能的設計

開發(fā)一個高性能程序的最佳方法就是預先設計好。對于GearVR應用來說,這通常意味著圍繞移動設備GPU的特點來設計。

設置

在開始之前,確保你的Unity工程設置為最佳性能。特別的,一定要確保設置下面的選項:

  • Static batching
  • Dynamic batching
  • GPU skinning
  • Multithreaded Rendering
  • Default Orientation to Landscape Left

Batching

既然知道了draw call通常是GearVR程序最耗費性能的部分,那么第一步就是要把場景所需draw call盡可能少。一個draw call是一條發(fā)送給GPU使其繪制一個mesh或者一部分mesh的指令。這個操作代價最高的部分實際上是mesh本身的選擇。每次游戲決定繪制一個新mesh時,這個mesh在被發(fā)送到GPU之前必須被驅動處理過。Shader必須要綁定,可能發(fā)生格式轉換等等;每次一個新mesh選定之后,驅動都要使用CPU進行工作。所以當draw call發(fā)送時,最嚴重的開銷是這個選擇的過程。

然而,這也意味著,一旦一個mesh(或者更加具體的,頂點緩沖對象VBO)選擇之后,我們可以花費一次選擇的成本,然后對它渲染多次。只要沒有新mesh(或者shader,或者紋理)被選擇,這個狀態(tài)會被驅動緩存下來,然后draw call的發(fā)送就快多了。為了利用這一點來提升性能,我們實際上可以把多個mesh打包成一個大的頂點數組,然后使用同一個VBO渲染它們。我們花費了一次整體mesh的選擇成本,然后從包含在這個對象內部的mesh中,發(fā)送盡可能多的draw call。這個技巧叫做batching,比每個mesh都創(chuàng)建一個VBO的方法快的多,這也是我們進行draw call優(yōu)化的基礎。

包含在一個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。有些情況下,這是一個非常重要的優(yōu)化;出來打包mesh減少draw call,Unity還把變換信息記錄在每個mesh的頂點位置中,所以它們就不需要在運行時變換。場景中標記為static的部分越多越好。請記住為了進行批處理該過程需要mesh具有同樣的材質。

注意,因為static batching在構建時產生新的大型mesh,這會增加程序最終二進制文件的大小。這通常對GearVR開發(fā)者來說不是問題,但是如果你的游戲有好多個獨立場景,并且每個場景有很多的靜態(tài)mesh,加起來就會很大。另一個選項是使用 StaticBatchingUtility.Combine 在運行時來生成打包的紋理,而不會使你的程序體積膨脹(需要花費一次性的CPU使用和一些內存)。

最后,請確保你正在使用的Unity版本支持static batching。

Dynamic Batching

Unity同樣可以打包沒有標記為靜態(tài)的mesh,只要他們符合共享材質的需求。如果你打開了Dynamic Batching選項,這個過程幾乎可以自動生成。每幀計算要打包的mesh的時候會有一些開銷,但是從性能的角度來看,通常會有一個明顯的提升。

其他batching問題

要注意的是,有一些方法會破壞打包。渲染陰影和其他多通道shader需要一個狀態(tài)轉換,使得對象不能正確的打包。多通道shader也會使得mesh被提交多次,在GearVR上應該引起注意。逐像素的光照有同樣的效果:在Unity4中使用默認的Diffuse著色器,投射到mesh上的每個光源都會使得mesh提交一次。這會使得draw call很快增長并超過多邊形數量限制。如果你需要逐像素的光照,可以嘗試把Quality Setting窗口中同時光源的數量設置成1。最接近的光源會以逐像素方式進行渲染,附近的光照將會使用球諧方法進行計算。要更好的話,刪除所有像素光照,使用光照探測器。還要注意的是,batching通常對蒙皮的mesh不起作用。透明物體必須以一定的順序進行渲染,因此batch效果不太好。

好消息是,你可以在編輯器中測試和調試batching。Unity Profiler和Game窗口中的Stats面板都可以告訴你發(fā)送了多少次draw call以及batching節(jié)省了多少資源。如果你的幾何體使用很少數量的紋理,那你就不用實例化材質、標記static對象,你的場景也會很高效。

Transparency, Alpha Test, and Overdraw

如上所述,移動設備的芯片通常是“fill-bound”,意味著填充像素的花銷是一幀中最昂貴的部分。降低填充花銷的關鍵是每個屏幕上的像素都只渲染一次。多通道的shader,逐像素光照效果(例如Unity
默認的specular著色器),還有透明物體都需要把它們涉及到的像素渲染多次。類似這些像素太多的話,將會充滿總線。

做為一個最佳實踐,嘗試把Quality Settings中的Pixel Light Count限制到1.如果你使用了多余一個的逐像素光源,確保你知道他們要作用于那個幾何體,以及渲染該幾何體多次的代價。類似的,讓透明物體盡量小點。因為主要的開銷是渲染像素,所以物體占據的像素越小,幀渲染完成的越快。注意像煙霧這樣的透明特效,可能占據比你想象中更多的像素。

還要注意的是,在移動設備上絕對不要使用alpha測試著色器,例如Unity的cutout著色器。Alpha測試的操作(還要clip(),或者像素著色器中顯式的discard操作)強制一些普通的移動設備GPU取消了硬件填充優(yōu)化,使得渲染非常慢。Discard像元的操作會導致大量難看的走樣(aliasing),盡量使用不透明物體。

Performance Throttling

在你測試場景性能之前,你需要確保你設置了CPU和GPU的限制。因為VR游戲的性能達到了移動設備的界限,你必須在CPU和GPU之間設置一個權重。如果你的游戲偏重CPU,為了讓CPU滿速運行,你可以調低GPU。如果偏重GPU可以做相反的操作。如果你的游戲已經很流暢了,可以把兩者都調低,這樣能夠節(jié)省電量,延長用戶在線時間。更多的信息請查看Mobile SDK documentation中的“Power Management”部分。

重要的是,在你開始任何類型的性能測試之前都要設置CPU和GPU限制。如果這些值初始化失敗的話,程序將會在默認設置非常低的環(huán)境中運行。因為大多數GearVR應用一般都會偏重CPU,所以通常會把CPU調整的高于GPU。OVRModeParams.cs中有一個關于怎樣初始化節(jié)流設置的例子,你可以復制粘貼到游戲啟動腳本中。

Gotchas陷阱

在考慮性能優(yōu)化的時候,你還應該記住下面這些技巧:

  • 有一個特殊的設備比其他都要慢,具體來說就是基于驍龍的Note 4運行Android 5的系統,圖形驅動在draw call方面似乎有一個倒退。對于draw call已經達到限制的游戲,會發(fā)現這個問題非常嚴重(draw call時間增加了20%),會導致正常的渲染管線停滯并且整體幀率下降。我們正和三星和高通努力解決這個問題。運行Android4.4系統的驍龍?zhí)幚砥鞯腘ote 4設備,還有Exynos處理器的Note 4和S6設備,都不受此影響。
  • 盡管對CPU和GPU進行節(jié)流很大程度上減輕了手機的發(fā)熱,對重量級的應用來說,在長時間運行的時候導致設備過熱仍然是可能的。這種情況發(fā)生時,手機會警告用戶,然后降低處理器的頻率,會導致VR應用無法使用。如果你正在做性能測試和解決發(fā)熱問題,請讓手機先休息五分鐘再繼續(xù)。
  • Unity 4免費版不支持static batching和Unity Profiler。Unity 5的個人版已經有了。
  • S6不支持各向異性紋理過濾。

到此結束。下一篇,我們將討論怎樣調試真實的性能問題。

原文

https://developer3.oculus.com/blog/squeezing-performance-out-of-your-unity-gear-vr-game/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容