克服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作品就會誕生。