談談VR遊戲的性能優化

VR遊戲相對傳統遊戲,個人認爲主要有三個方面的不同:玩法設計,輸入方式,性能壓力。今天就來談一下VR遊戲中的性能優化。

爲什麼VR遊戲的性能壓力很大?

  • 主要有三個因素的影響:高幀率,高分辨率,畫兩遍,影響權重由高到低。
  • 高幀率:DK2爲75,最新的CV1是90;HTC Vive爲90;PS4 VR爲120。對比PC遊戲的60以及主機遊戲的30,壓力可想而知!
    • 需要說明的是鑑於幀率這麼高,每一幀即便2ms的提升意義也巨大。即便以75爲例,每幀時間爲13.33ms,2ms佔比15%!
  • 高分辨率:DK2爲1920 * 1080,最新的CV1爲2160 * 1200;HTC Vive爲2160 * 1200;PS4 VR爲1920 * 1080
    • 除了賬面分辨率之外,實際渲染時爲抵消透鏡畸變帶來的分辨率損失需要超採樣,具體:DK2爲135%,CV1和HTC Vive都爲140%
      這裏寫圖片描述
  • 即使以DK2的數據:1920 * 1080 @75Hz來說,每秒的像素處理量爲283 millions, 這個數據4倍於一般的主機遊戲!更別忘了,最新硬件的這個數據提升至457 millions
  • 畫兩遍
    • 方法一:依次畫兩遍場景
      這裏寫圖片描述
      , SetTexture,SetTransforms,SetViewport,切換RenderState,DrawCall等均翻倍
    • 方法二:依次畫兩遍物體
      這裏寫圖片描述
      ,相比較方法一有節省,但DrawCall依舊翻倍

關於像素處理部分

通過上面的數據可以看到其實VR遊戲性能壓力主要集中在像素處理方面,那麼如下和像素處理相關的部分就要特別注意:

  • 光影計算方案的選擇:空間換時間尤爲重要,light map、靜態AO,環境反射貼圖等能上就上,dynamic shadow在任何時候能省則省。
  • 後期處理:不用的效果統統幹掉。如DOF、Motion Blur、Lens Flare等本就不適合VR遊戲;SSR、SSAO等儘量用前面說的靜態方案來替代;
    AA也可以不用,因爲已經有Super Sampling了
  • 特別注意OverDraw的問題:典型的如範圍巨大的透明面片特效省着點用,不要動不動疊加個7、8層。
  • Shader複雜度問題:UE4的viewmode裏面有一個是專門查看shader複雜度的。一般來說,出現粉色和白色的情況說明shader太複雜了,需要修正。
  • early z culling:
    • 原理:
      這裏寫圖片描述
    • 延遲渲染已經成爲各大引擎的標配,很多人覺得對於延遲渲染來講,early z culling沒有存在的必要,畢竟生成GBuffer之後相當於已經做了像素級別的culling,而且多了一個pass提前寫深度往往得不償失;但early z culling針對延遲渲染的受益部分主要在GBuffer的生成階段,傳統遊戲這部分相對於lighting計算階段開銷不大,所以往往被忽略掉,但VR遊戲中受制於超大的像素處理量,這部分的優化提升在我們遊戲中經過測試是相當明顯的。當然,世事無絕對,這裏僅作下提醒,實際要根據自己的遊戲場景做下詳盡的測試。

關於畫兩遍

批次翻倍加上面數翻倍因此VR遊戲中優化批次和麪數較傳統遊戲的意義更大。

  • 靜態場景的批次優化:針對UE4,我們專門做了擴展工具來合併場景中相同物體的批次,而不需要美術對已經做好的場景進行返工。
    絕大多數情況下,這事總是程序開發效率對美術製作效率的妥協,程序逃不掉的:)
    這裏寫圖片描述
  • 動態批次優化:多用instance的思想合併數量巨多但因個頭小而往往被忽視的物體,典型的如FPS遊戲中的子彈。
    • 其實優化中很多這樣的情況,比如不起眼的string對性能和內存造成的巨大的壓力(當然如string相關的如此底層的優化,現代成熟引擎已經都做好了)
  • 面數:對UE4而言,其消耗體現在生成GBuffer的Base pass階段,要善用統計工具去定時定性得分析遊戲場景;
  • 另外關於面數除了美術提供的靜態場景和角色之外一定要關注下自動生成的東西,如tessellation;工具可能也會統計不到。
    • 舉例:UE4中Ribbon特效的tessellation默認步長爲15uu,而我們遊戲中的Ribbon特效可達30000uu,如果不改變默認值,一條拖尾
      可生成4000面,同屏50條拖尾就令絕大部分GPU歇菜了
    • 特定遊戲中特例化的問題防不勝防,應善用不同工具從多種角度分析。

其他

當然,前面講的都是針對VR遊戲的特點來重點強調的,其他的優化方法同樣使用,根據之前的經驗做下總結,包括但不限於:

  • 對錶現效果妥協,如很多手機平臺的遊戲角色連normal都沒有。。還有貼圖精度,模型精度等
  • 對製作流程 、製作效率的妥協。如開發無盡之劍XboxOne版時發現,UI直接調用d3d API畫的。。
  • 開發效率的妥協。 注意shader中的數據類型,頂點的數據格式等,能用16位浮點就不要用32位的浮點
  • 遊戲類型具體分析,比如如果確定場景中物件都必須渲染則把Ocullusion Culling關掉,因此這種情況下不需要預計算遮擋剔除關係!
  • 特別注意下CPU、GPU的同步點,線程之間的同步點(多發生在競爭統一資源上,如主線程和第三方庫的線程用同一個內存分配器)
  • 善用第三方庫站在巨人肩膀,比如小內存多,分配頻繁自己又懶得寫內存庫的話,乾脆用tcmalloc、nedmalloc等
  • 多用LOD,不只是貼圖mipmap、模型LOD等這種,還有邏輯層面的LOD,如特效分層LOD
  • 不同Actor、不同Component、不同系統設置不同的更新頻率
  • 多線程加速、SIMD加速
  • 很track的做法:避免使用基於win32 API的高級函數,例如memeset,因爲這個是單字節填充;可用匯編進行優化,效率提升明顯(當然成熟引擎不需要操心這點)

其他方案

除了這些,業界還有些全新的優化方案,這裏也做下介紹。

  • 多/雙顯卡渲染:
    • DX12支持顯卡混搭,可把render task綁定到任意GPU上
    • Nvidia的SLI和ATI的CrossFire可應付非DX12的情況,叫法不同但原理相同:一塊顯卡渲染左眼,另一塊顯卡渲染右眼:
      這裏寫圖片描述
      要求兩塊顯卡必須型號一致,實測效果很不錯
  • StencilMesh的思想,同樣是culling,不過在另外的層面上。UE4中的實現叫做HMD Distortion Mask,實際也是節省掉周圍四角區域的像素計算。
    這裏寫圖片描述
    這裏寫圖片描述
  • Instanced stereo Rendering:
    • 核心思想:一次提交繪製雙份幾何體,draw call不需要翻倍了
    • UE4的4.11 preview版本已經放出了第一個版本的實現
  • Multi-Resolution
    • 人眼對中心區域像素更敏感,所以保持中心區域分辨率並降低邊緣區域分辨率。整體分辨率降低的同時儘可能抵消對效果的影響。
      這種方法可以節省25%~50%的像素處理量
      這裏寫圖片描述

補充和總結

其實真正做優化之前,有兩點怎麼強調都不爲過:

  • 穩定測試環境。包括關閉PC上其他3D程序,關閉垂直同步,保證每次採樣點以及採樣上下文完全一致,不要以編輯器模式啓動等等。
  • 量化觀測數據。同一遊戲,在完全穩定的測試環境下,前後兩次測試的性能觀測數據有有些許浮動都是很正常的,因此直覺不可靠!直覺不可靠!
    直覺不可靠!重要的事情說三遍!不要想當然的認爲:”這個沒影響“,”那個沒關係“,”這次有提升“,”感覺沒作用“等等。捕獲如下精確的數據加以分析纔是靠譜的做法。
    這裏寫圖片描述
    另外,優化是一個長期迭代進行的過程,中間過程做好記錄;遇到和美術PK的情況,也要做到儘量用數據說話。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章