1. 程式人生 > >Unity__靜態合批與動態合批

Unity__靜態合批與動態合批

draw call是openGL的描繪次數(directX沒怎麼研究,但原理應該差不多)
一個簡單的openGL的繪圖次序是:設定顏色→繪圖方式→頂點座標→繪製→結束。
每幀都會重複以上的步驟。這就是一次draw call

如果有兩個model,那麼需要  
設定顏色→繪圖方式→頂點座標A→繪製→結束。
設定顏色→繪圖方式→頂點座標B→繪製→結束。
兩次draw calls;
也就是說在openGl繪製前,如果色彩通道(color filter),繪圖方式(shader),頂點座標(model)不同的情況下draw calls就會增加。

對openGl來說繪製引數(狀態值)的變更要比繪製大量的頂點更耗費cpu。



所謂高速繪圖就是,在儘量不改變openGl狀態值的情況下,用一次draw call完成所有繪製。
比如上面的例子:
設定顏色→繪圖方式→頂點座標A+頂點座標B→繪製→結束。
就要更加有效率。

個人估計unity3d的dynamic batch,static batch都是通過一定的方法使不同的object的頂點座標能夠結合成一個整體,達到減少draw calls的效果。
但是有一定的要求限制,比如material要相同,mesh要相同並在300個面以內等等,這些都是為了保證openGl的狀態值不改變。

 

Unity在 Player Setting 裡的兩個功能選項 Static Batching 與 Dynamic Batching。功能描述如下:

  1. Static Batching 是將標明為 Static 的靜態物件,如果在使用相同材質球的條件下,Unity 會自動幫你把這兩個物件合併成一個 Batch,送往 GPU 來處理。這功能對效能上非常的有幫助,所以是需要付費才有的。
  2. Dynamic Batching 是在物件小於300面的條件下(不論物件是否為靜態或動態),在使用相同材質球下,Unity就會自動幫你合合併成一個 Batch 送往 GPU 來處理。

 

在螢幕上渲染物體,引擎需要發出一個繪製呼叫來訪問圖形API(iOS系統中為OpenGL ES)。每個繪製呼叫需要進行大量的工作來訪問圖形API,從而導致了CPU方面顯著的效能開銷。

 

Unity在執行時可以將一些物體進行合併,從而用一個繪製呼叫來渲染他們。這一操作,我們稱之為“批處理”。一般來說,Unity批處理的物體越多,你就會得到越好的渲染效能。

 

Unity中內建的批處理機制所達到的效果要明顯強於使用幾何建模工具(或使用Standard Assets包中的CombineChildren指令碼)的批處理效果。這是因為,Unity引擎的批處理操作是在物體的可視裁剪操作之後進行的。Unity先對每個物體進行裁剪,然後再進行批處理,這樣可以使渲染的幾何總量在批處理前後保持不變。但是,使用幾何建模工具來拼合物體,會妨礙引擎對其進行有效的裁剪操作,從而導致引擎需要渲染更多的幾何面片。

 

材質

只有擁有相同材質的物體才可以進行批處理。因此,如果你想要得到良好的批處理效果,你需要在程式中儘可能地複用材質和物體。

如果你的兩個材質僅僅是紋理不同,那麼你可以通過 紋理拼合 操作來將這兩張紋理拼合成一張大的紋理。一旦紋理拼合在一起,你就可以使用這個單一材質來替代之前的兩個材質了。

如果你需要通過指令碼來訪問複用材質屬性,那麼值得注意的是改變Renderer.material將會造成一份材質的拷貝。因此,你應該使用Renderer.sharedMaterial來保證材質的共享狀態。

 

動態批處理

如果動態物體共用著相同的材質,那麼Unity會自動對這些物體進行批處理。

動態批處理操作是自動完成的,並不需要你進行額外的操作。

 

Tips:

1、 批處理動態物體需要在每個頂點上進行一定的開銷,所以動態批處理僅支援小於900頂點的網格物體。

2、 如果你的著色器使用頂點位置,法線和UV值三種屬性,那麼你只能批處理300頂點以下的物體;如果你的著色器需要使用頂點位置,法線,UV0,UV1和切向量,那你只能批處理180頂點以下的物體。

3、請注意:屬性數量的限制可能會在將來進行改變。

4、 不要使用縮放尺度(scale)。分別擁有縮放尺度(1,1,1)和(2,2,2)的兩個物體將不會進行批處理。

5、 統一縮放尺度的物體不會與非統一縮放尺度的物體進行批處理

使用縮放尺度(1,1,1)和 (1,2,1)的兩個物體將不會進行批處理,但是使用縮放尺度(1,2,1)和(1,3,1)的兩個物體將可以進行批處理。

6、 使用不同材質的例項化物體(instance)將會導致批處理失敗。

7、擁有lightmap的物體含有額外(隱藏)的材質屬性,比如:lightmap的偏移和縮放係數等。所以,擁有lightmap的物體將不會進行批處理(除非他們指向lightmap的同一部分)。

8、 多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的著色器在前向渲染中都支援多個光源,併為它們有效地開闢多個通道。

9、預設體的例項會自動地使用相同的網格模型和材質。

 

靜態批處理

相對而言,靜態批處理操作允許引擎對任意大小的幾何物體進行批處理操作來降低繪製呼叫(只要這些物體不移動,並且擁有相同的材質)。因此,靜態批處理比動態批處理更加有效,你應該儘量低使用它,因為它需要更少的CPU開銷。

為了更好地使用靜態批處理,你需要明確指出哪些物體是靜止的,並且在遊戲中永遠不會移動、旋轉和縮放。想完成這一步,你只需要在檢測器(Inspector)中將Static複選框打勾即可,如下圖所示:
 

 
 

使用靜態批處理操作需要額外的記憶體開銷來儲存合併後的幾何資料。在靜態批處理之前,如果一些物體共用了同樣的幾何資料,那麼引擎會在編輯以及執行狀態對每個物體建立一個幾何資料的備份。這並不總是一個好的想法,因為有時候,你將不得不犧牲一點渲染效能來防止一些物體的靜態批處理,從而保持較少的記憶體開銷。比如,將濃密森裡中樹設為Static,會導致嚴重的記憶體開銷。

 

靜態批處理目前只支援Unity iOS Advanced。