Unity 2017 Game Optimization 讀書筆記 Dynamic Graphics (3)

Rendering performance enhancements

Enable/Disable GPU Skinning

開啓GPU Skinning可以減輕CPU或GPU中Front End部分中某一個的負擔,但是會加重另一個的負擔。Skinning是mesh中的頂點根據動畫中骨骼的當前位置進行計算,從而讓角色擺出正確的姿勢。

頂點的計算過程可以放在CPU也可以放在GPU的Front End 部分,取決於是否開啓GPU Skinning。可以通過 Edit | Project Settings | Player Settings | Other Settings | GPU Skinning 設置。

開啓後,計算會放在GPU的Frond End中,但是CPU並不是一點工作都不做了,還是需要傳輸數據到GPU並且要在Command Buffer中生成指令。如果不開啓,則計算在CPU中完成,傳輸到GPU中的數據已經是計算好的頂點數據。所以根據CPU和GPU的狀態可以靈活決定應該在哪算,如果CPU負擔太重就開啓,把工作丟給GPU。

Reduce geometric complexity

這條跟GPU中的Font End相關。很多時候用不到需要多套無用UV和法線數據的mesh。儘量減少頂點數量,有三種途徑:

1. 讓美術老鐵們手動減少頂點數量重新生成mesh

2. 乾脆從場景裏刪掉,當然這是最壞情況

3. 使用LOD等技術自動對mesh進行culling

Reduce Tessellation

通過Geometry Shaders中使用Tessellation技術會帶來很大的體驗提升,但是也給GPU中Frond End增加了負擔。目前對於如和優化Tessellation也沒啥好辦法,還是儘量優化Frond End中其他地方給Tessllation省出更多空間吧。

Employ GPU Instancing

GPU Instancing比Dynamic Batching更高效,因爲它並不需要mesh的合併,但是也要求更嚴格,material引用和mesh必須都一致纔可以。GPU Instancing可以有效的減少Draw Call,但是它在Unity中默認是沒有被開啓的,在每個material中可以設置是否開啓。

  • Unity automatically picks MeshRenderer components and Graphics.DrawMesh calls for instancing. Note that SkinnedMeshRenderer is not supported.

  • Unity only batches GameObjects that share the same Mesh and the same Material in a single GPU instancing draw call. Use a small number of Meshes and Materials for better instancing efficiency. To create variations, modify your shader scripts
     to add per-instance data (see next section to learn more about this).

https://docs.unity3d.com/Manual/GPUInstancing.html

Use mesh-based Level Of Detail(LOD)

LOD就是根據物體和攝像機的距離不同可以自動使用不同精度的mesh,因爲距離很遠的地方根本沒必要用精度很高的模型。

LOD的缺點之一是開發起來比較費勁,會需要美術提供不同精度的模型,場景設計師需要生成LOD Groups,還要進行測試效果,這會花費很多時間,當然目前一些插件提供了自動生成LOD Mesh的功能。

LOD另一個缺點是需要消耗更多的磁盤和內存以及CPU,但是優點也非常明顯,就可以有效減少頂點數量,降低Draw Call和Fill Rate以及 Memory Bandwidth。

LOD也不是總適用,對於內景以及攝像機是從上往下俯角的遊戲,比如RTS和MOBA類遊戲,物體和攝像機的距離基本都一致,所以LOD根本不會起到什麼效果。

總之是否使用LOD需要視情況而定,如果性能並沒有出現瓶頸,沒有必要使用。

Culling Groups

通過腳本,可以自定義LOD系統,比如可以根據distance使用不同精度的動畫,使用不同的shader以及粒子特效等。當然使用Culling Gropus也會帶來開發上額外的工作量。https://docs.unity3d.com/Manual/CullingGroupAPI.html

Make use of Occlusion Culling

同時能降低Fill Rate和Overdraw最好的途徑之一就是使用Occlusion Culling(遮擋剔除)。Frustum Culling(視錐剔除)只能剔除掉攝像機外的物體,但是對於攝像機內的物體,常規渲染的順序是從遠到近,因此當近物體擋住了遠處物體時,就會產生OverDraw。

Regular frustum culling renders all Renderers within the Cameras view.
沒有遮擋剔除時,遠處物體也會被渲染
​​​​

Occlusion Culling可以有效剔除攝像機內被近處物體擋住的部分。Unity把場景切割成cells,在Editor中烘焙生成Cells間遮擋剔除關係的數據,在運行時,加載烘焙好的數據到內存中,對於設置了遮擋剔除的攝像機,就會根據這個數據來進行渲染。

Occlusion culling removes Renderers that are are entirely obscured by nearer Renderers.
使用遮擋剔除時,遠處物體會被剔除掉
​​​​

只有標記爲Occluder Static 或者 Occludee Static的物體可以產生遮擋剔除數據。對於普通物體,既能遮擋其他物體又能被其他物體遮擋,使用Occluder。對於透明物體,並不能遮擋其他物體,使用Occludee。

開啓Occlusion Culling會增加存儲空間和內存以及CPU的開銷,因此對於Occlusion Culling烘焙時要設置合適的Cell參數。

特別注意的是即使物體被Occlusion Culling剔除掉了,但是它的陰影依然會被渲染。

Optimizing Particle Systems

粒子系統中,要注意粒子生成的數量以及使用Shader的複雜度,粒子的數量會影響Front End,而shader中使用大量的Texture會

在Back End消耗Fill Rate和Memory Bandwidth。

最直接的優化方法就是減少粒子數量和減少特效數量,使用圖集也是優化方法之一。但是經常忽略的一個優化方法是使用Particle System Culling。

Make use of Particle System Culling

關於 Particle System Culling 的一篇blog:https://blogs.unity3d.com/2016/12/20/unitytips-particlesystem-performance-culling/.

Particle System Culling的基本原理就是是否可以預測,如果一個粒子特效的各種參數設置使得其行爲樣式時可以被預測的,當它並不在視野中時就可以自動的被剔除掉,當重新進入視野中時,因爲是可以預測的,所以可以計算出此時此刻應有的樣子。

但是一些設置可能會導致粒子系統變得不可預測或者非程序化,那就無法使用Particle System Culling,無論是否可見,粒子系統必須一直保持運行。比如Particle System 使用world-space座標,使用碰撞,或者複雜的動畫曲線等等,都可能會使得其不可預測。Unity提供了一個非常有用的Warning,來提示改設置是否會導致粒子系統無法自動 Culling。

 Avoid recursive Particle System calls

 Particle System中很多方法都是遞歸的,調用他們會遍歷每一個child並且調用 GetComponent<ParticleSystem>()函數,當層級非常複雜時,會有比較大的開銷。

 Start(), Stop(), Pause(), Clear(), Simulate(), and isAlive()都是這種函數。但是這些函數裏其實有個withChildren參數,Unity默認設置爲true,如果手動設置爲false,就可以避免遞歸行爲。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章