1. DrawCall是啥?其實就是對底層圖形程式(比如:OpenGL ES)接口的調用,以在螢幕上畫出東西。是以,是誰去調用這些接口呢?CPU。比如有上千個物體,每一個的渲染都需要去調用一次底層接口,而每一次的調用CPU都需要做很多工作,那麼CPU必然不堪重負。但是對于GPU來說,圖形處理的工作量是一樣的。是以對DrawCall的優化,主要就是為了盡量解放CPU在調用圖形接口上的開銷。是以針對drawcall我們主要的思路就是每個物體盡量減少渲染次數,多個物體最好一起渲染。
2. 優化方式
(1)Draw Call Batching
采用批處理方式,Unity在運作時可以将一些物體進行合并,進而用一個描繪調用來渲染他們。
- 靜态批處理:物體不移動,并且擁有相同的材質,靜态批處理就允許引擎對任意大小的幾何物體進行批處理操作來降低描繪調用。例如:在一個3D場景中,有Cube、Capsule、Cylinder、Sphere這個4個GameObject,注意之間不要有遮擋,另外還有Camera和Direction Light,它的處理前後的統計資料如下:
- 動态批處理
在這裡使用時,遇到了坑,很多資料都沒有提及到,在預設情況下,Unity是沒有打開的,需要在Player Settings中進行設定的:
用了一個不錯的例子來看,
for(int i = 0; i < 500; i++)
{
GameObject cube;
cube = GameObject.Instantiate(prefab) as GameObject;
}
動态批處理的結果是非常明顯的(塔防遊戲中估計能提高不少效率)
DrawCall的動态批處理存在着很多限制,是以預設是關閉的
a. 需要在每個頂點上進行一定的開銷,是以動态批處理僅支援小于900頂點的網格物體;
b.着色器使用頂點位置,法線和UV值三種屬性,那麼你隻能批處理300頂點以下的物體;如果你的着色器需要使用頂點位置,法線,UV0,UV1和切向量,那你隻能批處理180頂點以下的物體(這個地方不懂);
c.不要使用縮放。分别擁有縮放大小(1,1,1) 和(2,2,2)的兩個物體将不會進行批處理
d.統一縮放的物體不會與非統一縮放的物體進行批處理
e.用縮放尺度(1,1,1) 和 (1,2,1)的兩個物體将不會進行批處理,但是使用縮放尺度(1,2,1) 和(1,3,1)的兩個物體将可以進行批處理
f.使用不同材質的執行個體化物體(instance)将會導緻批處理失敗;
g.擁有lightmap的物體含有額外(隐藏)的材質屬性,比如:lightmap的偏移和縮放系數等。是以,擁有lightmap的物體将不會進行批處理(除非他們指向lightmap的同一部分)。(什麼是lightmap)
h.多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的着色器在前向渲染中都支援多個光源,并為它們有效地開辟多個通道。
i. 預設體的執行個體會自動地使用相同的網格模型和材質。
3. 打包圖集
每個材質/紋理的渲染一定是會産生DrawCall的,這個DrawCall隻能通過打包圖集來進行優化,例如在2D遊戲中使用了2張圖檔,它的資料為:
在Unity中,Window->2D->Sprite Packer,先轉到Editor Settins中進行設定:
這次的結果,明顯減少了一次Draw Batch: