一、渲染一幀步驟
0-1、剔除:攝像機視錐體剔除、代碼刪除/隱藏Mesh
0-2、從硬盤HDD中加載紋理、Mesh到內存RAM,再將需要渲染的加載到VRAM[1]。
1、設置全局 Render State(Unity中對應SetpassCall),包含:頂點/片元着色器、紋理、材質、光照、透明度等
2、CPU發送一個DrawCall給GPU,指向VRAM中的一個Mesh(不包括材質,這是上一步的工作)。
3、GPU根據當前 Render State,以及CPU指向的頂點數據,通過代碼生成像素並顯示到屏幕。
如果后續Mesh使用相同的 Render State,那么重復2、3步驟;否則需要執行一次1步驟。
步驟3稱為管線Pipeline。管線中從開始到結束,比較關鍵的模塊有:頂點着色器、光柵化、片元着色器。頂點和片元着色器是可編程的,即常說的Shader。
[1] RAM、VRAM分別存儲什么:https://www.reddit.com/r/gamedev/comments/camqq0/whats_stored_in_ram_and_vram/
(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中渲染。
二、優化概述
Render State、DrawCall屬於CPU的工作,都比較耗時。優化方向:降低它們的執行次數。
減少 Render State:減少材質的種類
減少 DrawCall:不同的Mesh盡量使用同一個材質;對同種材質的Mesh做合批處理;使用GPU Instancing
其他優化:避免OverDraw(避免使用透明,錯誤示范:為了實現四角陰影,使用一張全屏圖片)
三、優化細節
合批分為動態、靜態。
【靜態合批】:將相同材質的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,比如植被
四、容易出錯的地方
1、修改Render.material導致不能動態合批:
(1)Unity提供了兩個獲取Material的方法接口,分別是material及sharedMaterial。當對物體的material進行任何修改時,Unity會對Render里Materials列表第一個預設的Material進行實例化,並將返回實例。Unity這么做的目的是不影響其他物體,而僅僅修改這個實例。
(2)如果調用sharedMaterial,Unity就不會幫我們實例化,直接返回原本的材質球。但是會讓所有使用該sharedMaterial的模型響應相同的修改。如果這不是你想要的,可以創建兩個材質球,根據不同的情況替換材質。
Ref: [**記一次Dynamic Batching不生效的爬坑實例分析Unity]**
2、動態合並的限制是單個模型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/