Unity 繪圖性能優化 - Draw Call Batching


Unity 繪圖性能優化 - Draw Call Batching

 

Unity官方鏈接:http://docs.unity3d.com/Manual/DrawCallBatching.html

轉載請注明本文鏈接:http://www.cnblogs.com/fly-100/p/5422734.html

Draw Call Batching

在屏幕上繪制一個物體,U3D引擎必須向繪圖API(openGL或者D3D)發起一次DrawCall。這些DrawCall往往是昂貴的,當繪圖API為每個DrawCall做一些重要的事情,引起GPU的性能消耗較高。
這些消耗大部分是因為DrawCall結束的狀態切換引起的(比如,從一個材質切換到另一個材質),因為這會引發昂貴顯卡驅動的驗證和變換步驟。

Unity使用多種技術來解決這個問題:

  • 靜態Batching:把靜態的物體合並成一個大meshes,然后用更快的方法渲染他們。
  • 動態Batching:對於足夠小的meshesh,變換他們的頂點在CPU上,將一些相似的組合到一起,在一個go中繪制。

內建的Baching相對於手動合並物體到一起有幾個好處(值得注意的是,這些對象仍可以被單獨銷毀)。
但是他也有它的缺點(靜態Batching會導致內存和存儲的開銷,動態Batching會導致CPU開銷)。

 

Material Setup For Batching

只有共享同一個材質的物體才能被Batched在一起。如果,你想達到一個好的batching,你需要竟可能多的在不同物體中共享材質。

如果你有兩個同樣的材質但是他們的textures不同,你可以合並這些textures到一個大texture - 這個過程經常被叫做texture atlasing。一旦textures在同一個圖集中,你就可以使用一個材質來代替了。 

如果你需要在腳本中訪問共享了的材質,有一個很重的點需要注意:修改Renderer.material屬性會創建一個當前材質的副本。所以,作為替換方案,你應該使用Rednerer.sharedMaterial以保證材質被共享。

當渲染陰影投射的時候,即使他們的材質是不同的,也經常被batched到一起。只要材質中的數值在shadow pass是相同的,即使陰影投射有不同的材質,他們也可以使用動態batching。舉個例子,許多箱可以使用具有不同的texture的材質,但對於陰影投射渲染 texture是不相關 - 在這種情況下,他們可以被batched到在一起。

 

Dynamic Batching

Unity可以自動batch移動物體到相同的draw call,如果它們具有相同的材質和滿足其它標准。動態Batching是自動完成的,不需要你做額外的事情。

  • Batching 動態的物體每個頂點會有某些開銷,所以batching只適用於定點數小於900的meshes。
    • 如果你得shader使用了頂點位置,法線和單獨的UV,那么你可以batch 300 個頂點;如果你得shader使用了頂點位置,法線,UV0,UV1,和正切,只能batch 180個頂點。
    • 這個限制的數量將來有可能會變化。
  • 如果物體包含鏡像變換,他們將不會被batched,例如,object A 的scale 為 +1 object B 的scale 為-1,就不能batched到一起。
  • 使用不同材質的實例,即使他們實質上是相同的,也會導致兩個物體不能被batched到一起。陰影投射除外。
  • 具有光照貼圖的對象有額外的渲染參數:光照索引和 偏移/放縮 的光照。所以一般動態lightmapped對象應指向完全相同的光照貼圖位置然后再進行batch。
  • 多通道的shader將不會被batching
    • 幾乎所有的Unity shader都支持前置渲染幾個燈光,有效的為他們做更多的通道。“額外的逐像素的燈光”的draw call 將不會被batched。
    • 傳統的延遲渲(逐通道光照)染通道禁用了動態batching,因為它必須繪制兩次。

由於它的工作原理是變換所有的物體的頂點到CPU的世界坐標中,所以它僅僅在它的工作(變換到cpu的世界坐標)比做一次“draw call”小的時候才能起到好的作用。究竟一個DrawCall有多昂貴取決於諸多因素,主要是所用的繪圖API。例如,在控制台或當前流 
行的APIs 例如Apple Metal DrawCall的開銷一般比較低,所以一般動態batching不會達到好的效果。

 

Static Batching

靜態batching允許引擎減少draw call適用於任何大小的幾何(假設沒有移動和共享材質)。大部分情況下他比動態batching更高效 ,但是它會占用更多的內存。

為了使靜態batching更好的獲益,你需要明確的指定游戲中某些物體是靜態的而且不會移動,旋轉或者縮放。這樣做,你可以在Inspector界面中的“Static”選項(chekbox)標記物體為static:


 

使用靜態batching將需要額外的內存來存儲合並后的幾何信息。如果幾個物體在靜態batching之前共享同一個幾何圖元,那么這個幾何圖元將會為每個物體復制一份,無論在Editor中還是runtime中都是如此。這不是一個好方法 - 有時候為了保持更小的內存占用量,你必須犧牲渲染性能為了避免一些物體的靜態batching。例如,在一個稠密的森林中,標記樹木為static會產生嚴重的內存影響。

在內部,靜態batching的原理是變換這些靜態物體到世界控件然后為他們建立一個很大頂點+索引 緩沖區。然后所有顯示的物體都放到一個batch,一系列“便宜的”draw call就完成了,這期間幾乎沒有狀態切換(state change)。所以 從技術上來講 這並沒有節省“3D API draw call”,但是他節省了他們之間的狀態切換(狀態切換才是罪魁禍首)。

 

Other Batching Related Tips

目前,只有網格渲染才被batched。像 skinned meshes,cloth,拖尾渲染器(Trail Renderer)和其他類型的渲染組件是不被batched的。半透明shader為了做透明度的工作,經常需要物體以從后到前的順序進行渲染。Unity首先會對物體進行排序,然后試着batch他們 - 因為這個順序是嚴格限制的,這就意味着 相對於不透明物體來說,會有很少的batching產生。相對調用draw call來說,手動合並比較近的物體可能是一個非常不錯的選擇。例如,許多抽屜的靜態櫃子合並成一個mesh經常是有道理的,無論是在3D建模軟件中還是使用Mesh.CombineMeshaes.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM