降低游戲的Drawcall,是渲染優化很重要的手段,接下來從以下4個方面來分析如何降低DrawCall:
降低Drawcall的意義是什么?如何查看游戲的Drawcall;Drawcall合批的常用的技術手段原理與優缺點;組織項目讓Drawcall最小需要注意的點;摘抄官方關于Drawcall合批的一些規定搞清楚這些,Drawcall的優化基本上就能很好的掌握好。
降低Drawcall的意義是什么?如何查看游戲的Drawcall
游戲引擎遍歷游戲場景中的所有的物體,然后得到一個物體的渲染順序,然后按照順序提交給GPU來繪制游戲畫面出來。每次渲染時,CPU把每次繪制要使用的數據傳遞給GPU,然后向GPU下達繪制DrawCall指令,GPU接收到指令以后”開機”繪制游戲物體出來。假設我們有100個物體需要渲染,如果分100次提交給GPU,每次GPU渲染一個,完成后再渲染下一個,這樣CPU就要向GPU傳送數據100次,同時下達100次的渲染命令。如果是這樣,CPU提交數據給GPU,下達指令會有額外的開銷,GPU每次可以處理很多個面,但是由于每次只送進來一個物體,導致GPU的處理能力沒有發揮出來。假設把100個物體一次提交給GPU一起繪制,CPU不用反反復復的給GPU下達指令,重復傳送數據,GPU一次開機把100個物體一次處理好,發揮最大的性能。把N個物體合并到一起來提交給GPU,GPU一次繪制,這個過程我們叫做合批。CPU給GPU下達一次渲染指令叫Drawcall。提交繪制一個游戲場景,場景中的物體分幾次提交給GPU進行繪制我們叫做批次數目(Batches),又叫Drawcall次數。如果100個物體分100次提交給GPU,Drawcall/批次數目(Batches)為100,100個物體分2次提交給GPU,Drawcall/批次數目(Batches)為2。
如何查看游戲運行時Drawcall的數目,如下圖所示:
總結一下降低Drawcall次數的意義:
a:避免CPU反復多次的提交數據給GPU而產生的開銷;
b:每次提交盡可能多的物體,能最大限度發揮GPU的性能,提升GPU的吞吐量;
Drawcall合批的常用的技術手段原理與優缺點
盡可能的讓我們的游戲場景的物體能最少的批次完成渲染,一次渲染盡可能多的物體,降低Drawcall能提升渲染的性能。Unity游戲開發中有哪些常用的技術能將物體合批,降低Drawcall呢?
首先物體能合批的首要條件就是提交繪制的物體一定要是”同一個材質”,只有這些物體才有合批的可能。假設我們提交給GPU渲染的物體排列如下:A1A2A3A4A5A6B1B2B3B4B5B6其中A1,…A6表示這6個物體使用同一個材質A,B1,…B6標識6個物體使用同一個材質B。
靜態合批:
游戲引擎會將"能夠合批“(同一個材質球)的"靜態物體"(所以你要標記為靜態不可移動物體)預先合并好成一個新的整體的網格,提交給GPU渲染。
靜態合批處理的局限性(缺點)
a:要求物體是靜態不可移動的;
b:預先計算好合并整體網格,合并后的內存開銷增加;
c:N個物體使用同一個網格,把所有的網格合并到一起,合并后會有N個網格的數據導致內存暴漲,這時候要關閉靜態的合批。例如森林有1000棵樹,采用靜態合批后做成一個1000個樹合在一起的網格,合并后的網格占用的內存空間就會很大,所以這種情況下一般關閉靜態合批。
動態合批:
游戲引擎將"能夠動態合批"的(同一個材質球)物體的每個頂點,根據世界變換矩陣,用CPU來計算合批物體的每個頂點對應的世界空間的坐標,然后就把計算后的物體的頂點(世界空間下的頂點)與單位矩陣一起提交給GPU,GPU一起把他們渲染出來出來。
由上可知,動態合批是一個雙刃劍,雖然可以獲得合批提升的渲染性能,但同時CPU計算出頂點的世界坐標會產生額外的運算開銷,使用動態的合批的時候,我們要關注一下,付出+得到是不是成比例。
動態合批是引擎會自動處理的,所以引擎會對能夠動態合批的物體,會有一些條件的限制,引擎和系統給的合批的限制是頂點數目不應過多;
最后總結一下動態合批的缺點:CPU的開銷和drawcall減少得到性能提升之間來做平衡;
GPUInstancing合批:
同一個網格對象的N個實例的繪制可以采用GPUInstancing合批。它的本質就是提交一次網格物體給GPU,GPU繪制出這個物體的N個實例到不同的地方(位置,旋轉,縮放)。如1000個小兵采用GPUInstancing合批,提交一個小兵的網格對象給GPU,GPU根據1000個小兵的位置來繪制出來我們1000個實例。
1000個實例,可以在同一個批次進行完成(1000個實例<GPU每次處理的極限),如果1000個兵一起合批超過了顯卡的極限就分多批如:800兵一批,200兵一批;
GPUInstacing合批是非常好的一種方式,它的缺點就是有些老的顯卡不支持。
組織項目讓Drawcall更小需要注意的點
合理的安排物體,注意不要打亂物體的合批。3D物體的渲染順序是引擎自動計算出來的,盡可能的在3D場景里面讓物體使用同一個材質,盡可能的在同一個渲染隊列里面使用同一個材質,盡可能的在3D場景里面使用同一個種shader,不要根據物體渲染的需順序來回切換shader(SetPassCall開銷很大)。2DUI物體盡可能的安排同一個圖集的物體在一起,如任務系統UI,盡量的讓任務系統這些UI物體在一個圖集里,這樣可以合批渲染;
將多個物體的紋理合并到一起,如游戲地圖上的障礙物,可以將這些障礙物與地圖的紋理合并到一起,這樣地圖和障礙物可以由合批的可能。
最后美術把能合批的物體生成到一個fbx模型里面,這樣從美術的層次來減少渲染批次。
今天的分享就到這里了,關注我們可以獲得更詳細的官方給出的合批的一些規定,幫助大家優化Drawcall。