【Unity優化】DrawCall與Batch

1、渲染一幀步驟

0-一、剔除:攝像機視錐體剔除、代碼刪除/隱藏Meshhtml

0-二、從硬盤HDD中加載紋理、Mesh到內存RAM,再將須要渲染的加載到VRAM[1]。編程

一、設置全局 Render State(Unity中對應SetpassCall),包含:頂點/片元着色器、紋理、材質、光照、透明度等性能

二、CPU發送一個DrawCall給GPU,指向VRAM中的一個Mesh(不包括材質,這是上一步的工做)。優化

三、GPU根據當前 Render State,以及CPU指向的頂點數據,經過代碼生成像素並顯示到屏幕。動畫

若是後續Mesh使用相同的 Render State,那麼重複二、3步驟;不然須要執行一次1步驟。htm

步驟3稱爲管線Pipeline。管線中從開始到結束,比較關鍵的模塊有:頂點着色器、光柵化、片元着色器。頂點和片元着色器是可編程的,即常說的Shader。blog

[1] RAM、VRAM分別存儲什麼:https://www.reddit.com/r/gamedev/comments/camqq0/whats_stored_in_ram_and_vram/接口

https://forums.unrealengine.com/development-discussion/rendering/1651940-i-want-to-learn-more-about-how-vram-is-used-and-texture-object-optimizations遊戲

(1)VRAM:GPU內存僅存儲當前幀(DC)須要的資源,好比:紋理、mesh、shader、framebuffer、constant buffer、以及其餘渲染場景所需的通用數據。處理完當前的DC後,就會清除數據,準備下次DC。圖片

(2)RAM:RAM包含可執行代碼、音頻、遊戲數據。通常不包含紋理、mesh這些已經在VRAM中的資源(CPU從HDD中讀到RAM,傳給VRAM,而後從RAM中清除。然而若是須要在CPU中檢測碰撞,mesh信息就須要保留)。

(3)RAM、VRAM:動畫、物體變換通常同時存在。一般在CPU中每幀更新,而後複製到VRAM中渲染。

2、優化概述

Render State、DrawCall屬於CPU的工做,都比較耗時。優化方向:下降它們的執行次數。

減小 Render State:減小材質的種類

減小 DrawCall:不一樣的Mesh儘可能使用同一個材質;對同種材質的Mesh作合批處理;使用GPU Instancing

其餘優化:避免OverDraw(避免使用透明,錯誤示範:爲了實現四角陰影,使用一張全屏圖片)

3、優化細節

合批分爲動態、靜態。

【靜態合批】:將相同材質的Mesh合併成一個大Mesh。

優勢:下降DC,且只須要執行一次,能夠是不一樣Mesh;

缺點:佔用內存,不能部分剔除。

適合:靜態大Mesh。

【動態合批】:實時地將相同材質的Mesh合併成一個大Mesh。

優勢:下降DC,能夠是不一樣Mesh,能夠部分剔除。

缺點:每幀都要執行,消耗CPU,且佔用內存。若是該步驟消耗的CPU,大於下降DC所帶來的的提高,則反而影響性能。限制較多(非負縮放、沒有光照貼圖或使用相同的光照貼圖位置、material單pass、不能接受實時陰影)

適用:動態的大量小Mesh。

【GPU Instancing】CPU只發送一次Mesh給GPU,GPU本身去複製實例化。爲了讓Mesh有不一樣的狀態,甚至播放動畫,CPU須要同時提供一份額外數據(好比變換矩陣)。

優勢:解放CPU。

缺點:須要是相同的Mesh,對平臺和API有要求(Windows要求DirectX11以上、OpenGL Core 4.1+/ES 3.0+)

適用:大量相同的Mesh,好比植被

4、容易出錯的地方

一、修改Render.material致使不能動態合批:

(1)Unity提供了兩個獲取Material的方法接口,分別是material及sharedMaterial。當對物體的material進行任何修改時,Unity會對Render裏Materials列表第一個預設的Material進行實例化,並將返回實例。Unity這麼作的目的是不影響其餘物體,而僅僅修改這個實例。

(2)若是調用sharedMaterial,Unity就不會幫咱們實例化,直接返回本來的材質球。可是會讓全部使用該sharedMaterial的模型響應相同的修改。若是這不是你想要的,能夠建立兩個材質球,根據不一樣的狀況替換材質。

Ref: [**記一次Dynamic Batching不生效的爬坑實例分析Unity]**

二、動態合併的限制是單個模型900頂點:

Unity文檔中所說的動態合併的頂點限制是900,指的是單個模型,而不是合批的模型總和。合批的模型總和上限是65535[1]。同理,若是Shader使用了頂點座標、法線、單個UV,那麼限制是300個頂點;若是使用了頂點座標、法線、UV0、UV1和切線,則限制是180個頂點。這兩個限制針對的也是單個模型。

[1] https://forum.unity.com/threads/unity-5-3-static-batching-not-batch-draw-calls.372625/

相關文章
相關標籤/搜索