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

1. Use less texture data

這條優化技巧非常直接,減少texture的數據量,減少分辨率或者降低位數,雖然可能會降低渲染質量。但是通常使用16-bit textures並不會明顯的感覺到渲染效果下降。

MipMap技術可以有效減少VRAM和Texture Cache之間來回傳遞的texture數據量。值得一提的是Scene視圖中有Mipmaps Shading Mode,可以爲哪些texture用mipmap技術比較合適提供信息。

2. Test different GPU Texture Compression formats

Unity中有很多種texture的壓縮方式, 比如DXT, PVRTC, ETC, and ASTC,每個平臺有各自支持的類型。Unity默認會選擇綜合起來最合適的壓縮格式,但是我們也可以手動更改成其他格式,比如改成壓縮度更高的,會節約空間或者提高性能。

如果我們想自己擼一套壓縮方法,不到迫不得已儘量別這麼做,因爲需要自己處理多種平臺。

可以查看Texture壓縮的相關文檔https://docs.unity3d.com/Manual/class-TextureImporterOverride.html

3. Minimize texture swapping

儘量減少texture數量是最直接的,但是可能在渲染效果上無法接受。兩個小方法:

1.多個功能儘可能使用同一張貼圖,但是使用不同的material和shader屬性,比如超級馬里奧中雲朵和灌木叢就長的一樣。要注意的是這種方法並不能Draw Call,但是可以降低Memory BandWidth的開銷。

2.如果多個貼圖經常一起同時使用,考慮打成圖集Atlas,這樣可以避免在一幀中不斷的分別拉取各個texture。

4. VRAM limits

大多數textures從CPU傳輸到GPU中是發生在初始化的時候,但是也會發生在當需要渲染場景中未存在的texture時。這個加載處理過程是異步的,因此我們會看到一個空的texture直到整個texture爲渲染準備好,我們應該避免頻繁實時的加載texture。

4.1Preload textures with hidden GameObjects

加載過程中blank texture會十分影響遊戲體驗,因此應該想辦法讓texture在真正需要使用前就從硬盤中加載到內存中然後再加載到顯存中。

一種比較取巧的方法是在場景中放一個物體,在其上引用texture,並將物體隱藏。運行時當玩家面向這個物體時,即使該物體是隱藏的,其上的texture也將從內存傳輸到緩存中。將這個物體擺放的位置放在玩家真正需要這張texture渲染之前,比如某個房間內所需的texture可以將隱藏的物體放在去往這個房間的路上。

我們也可以通過代碼控制material的texture來完成類似的功能:GetComponent<Renderer>().material.texture = textureToPreload;

4.2 Avoid texture thrashing

有少數時候,VRAM可能會被佔滿,此時如果有texture需要傳入,必須要先清理一部分texture。這個過程開銷非常非常的大,應該無論如何都要避免。

對於PS4,XBOX這類平臺,不存在這種問題,因爲他們的CPU和GPU共享內存,這種設計是因爲這些平臺不存在多個應用同時運行的需求,同一時刻只是有一款遊戲在運行。

根據不同的目標平臺,texture要採用合適的文件大小和質量,避免超過平臺的VRAM上限。

5. Lighting optimization

5.1 Use real-time Shadows responsibly

之前已經介紹過,Shadows很容易成爲Draw Calls 和 Fill Rate的殺手。要仔細設置Shadow的參數,來達到渲染質量和性能的平衡。Soft Shadows開銷比較昂貴, Hard Shadows 開銷小一些,No Shadows當然沒有開銷。Shadow Resolution, Shadow Projection, Shadow Distance, and Shadow Cascades等參數也非常重要,也會影響Shadow的效果和性能。

Shadow Distance是控制實時陰影渲染的距離,因爲對於攝像機遠處的部分有沒有陰影其實意義不大。這個distance參數就是控制我們可視的陰影範圍。

Shadow Resolution 和 Shadow Cascades參數如果設置的很高會加大Memory Bandwidth 和 Fill Rate的開銷(因爲ShadowMap)。更高的陰影質量開銷自然會更大,對於ShadowMap,會有鋸齒的問題,離攝像機近處的物體陰影效果會比較差。Shadow Cascades就是爲了解決這個問題,根據和攝像機距離使用不同質量的ShadowMap。

關於級聯陰影的作用可以參考這個官方文章:https://docs.unity3d.com/Manual/shadow-cascades.html

SoftShadow和HardShadow相比,除了Shader更復雜以外沒有任何其他開銷,所以對於Fill Rate有餘地的項目可以享受SoftShadow帶來的快感。

5.2 Use Culling Masks

Light上的Mask屬性可以通過Layer層級來限制那些物體受到該Light影響。這對於降低光照的開銷很有效,但是物理系統的優化也經常用到layer mask,一個物體只能屬於一個Layer,所以要注意Light光照優化用到mask和物理系統優化用到mask是否有衝突,衝突的話要根據需求抉擇,通常mask是以物理系統的優化爲先。

5.3 Use baked Lightmaps

烘焙光照和陰影與實時渲染光照和陰影比起來性能提高非常大,缺點是需要額外的存儲空間和內存開銷以及Memory Bandwidth的消耗。除非遊戲中光照渲染用很簡單的頂點光或者只有一個方向光,否則我們都應該或多或少的去使用烘焙光照和陰影來提高性能。

有一些參數會對Lightmapping影響比較大,比如resolution分辨率, compression壓縮以及是否開啓Pre-computed
Realtime GI等,當然場景中有多少個物體需要渲染也會影響很大。 static屬性標誌爲Lightmap Static的會參與Lightmapper的繪製,需要繪製的物體越多,就需要生成更多的LightMaps,所以儘量使用增量式加載,減少每幀需要處理的物體數量。加載場景中的Lightmap可能會造成內存瞬間開銷很大,當舊場景卸載後應該立刻釋放掉對應的LightMap。

6. Optimizing rendering performance for mobile devices

手機設備發展日新月異,所以下邊列出的一些優化方法是針對目前設備的,隨着硬件發展可能也會出現不適用,開發時每個優化方法都應該根據當前需求進行對應測試。

6.1 Avoid Alpha Testing

移動端GPU和PC端GPU還有比較大的差距,對於Alpha Testing開銷會很嚴重,在大多數情況下,用Alpha Blending而不要用Alpha Testing。

6.2 Minimize Draw Calls

移動端的瓶頸經常是Draw Call而不是Fill Rate。應該在項目開發時儘早就使用合併mesh,合批和圖集等技術來減少Draw Call,Deferred Rendering也是很不錯的技術,因爲它和其他移動端需要考慮的問題也比較搭,比如避免使用transparency等,但是Deferred Rendering並不是所有硬件都支持。

6.3 Minimize Material count

這條跟Batching和Atlasing一起使用風味更佳,可以有效減少Draw Call,節約顯存VRAM 和 Memory Bandwidth。

6.4 Minimize texture size

OpenGL ES1.1 只能最大支持1024x1024

OpenGLES 2.0 能支持2048x2048

OpenGLES 3.0 能支持4096 x 4096  

儘量減少texture的大小,對於不同目標平臺使用合適的大小,如果texture過大超過了限制,在加載時也會被CPU降低縮小,這會浪費寶貴的加載時間以及有可能導致渲染效果出現問題,因爲這個過程我們並不可控。

6.5 Make textures square and power-of-two

2次方的正方形貼圖可以被GPU壓縮,從而提高性能。

6.6 Use the lowest possible precision formats in Shaders

這條其實之前在Shader優化部分已經說過了,儘可能的降低Shader中數據的精度。

7.Summary

Dynamic Graphics這章就結束了,作者說了:這章內容信息很多,需要慢慢消化,也是Unity中最複雜的部分,你要是都弄懂就牛逼了

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