前言
CPU準(zhǔn)備數(shù)據(jù)并通知GPU渲染的過(guò)程就是一次DrawCall,如果這個(gè)過(guò)程出現(xiàn)的次數(shù)太多,就會(huì)影響CPU的執(zhí)行效率,就會(huì)出現(xiàn)卡頓汗捡。
當(dāng)然沟涨,影響CPU的不僅僅只有DrawCall,還有物理組件虐秦、GC(垃圾對(duì)象太多,造成GC負(fù)擔(dān)断凶,影響CPU的執(zhí)行效率)、代碼質(zhì)量巫俺。
Draw Call Batching
在屏幕上繪制一個(gè)物體认烁,U3D引擎必須向繪圖API(openGL或者D3D)發(fā)起一次DrawCall。
這些DrawCall往往是昂貴的,當(dāng)繪圖API為每個(gè)DrawCall做一些重要的事情却嗡,引起GPU的性能消耗較高舶沛。
這些消耗大部分是因?yàn)镈rawCall結(jié)束的狀態(tài)切換引起的(比如,從一個(gè)材質(zhì)切換到另一個(gè)材質(zhì))窗价,因?yàn)檫@會(huì)引發(fā)昂貴顯卡驅(qū)動(dòng)的驗(yàn)證和變換步驟如庭。
Unity使用多種技術(shù)來(lái)解決這個(gè)問(wèn)題:
靜態(tài)Batching:把靜態(tài)的物體合并成一個(gè)大meshes,然后用更快的方法渲染他們撼港。
動(dòng)態(tài)Batching:對(duì)于足夠小的meshes坪它,在CPU上變換他們的頂點(diǎn),將一些相似的組合到一起帝牡,在一次中繪制往毡。
內(nèi)建的Baching相對(duì)于手動(dòng)合并物體到一起有幾個(gè)好處(值得注意的是,這些對(duì)象仍可以被單獨(dú)銷毀)否灾。
但是他也有它的缺點(diǎn)(靜態(tài)Batching會(huì)導(dǎo)致內(nèi)存和存儲(chǔ)的開(kāi)銷卖擅,動(dòng)態(tài)Batching會(huì)導(dǎo)致CPU開(kāi)銷)。
Material Setup For Batching(合并材質(zhì))
只有共享同一個(gè)材質(zhì)的物體才能被Batched在一起墨技。如果惩阶,你想達(dá)到一個(gè)好的batching,你需要竟可能多的在不同物體中共享材質(zhì)扣汪。
如果你有兩個(gè)同樣的材質(zhì)但是他們的textures不同断楷,你可以合并這些textures到一個(gè)大texture - 這個(gè)過(guò)程經(jīng)常被叫做texture atlasing。
一旦textures在同一個(gè)圖集中崭别,你就可以使用一個(gè)材質(zhì)來(lái)代替了冬筒。
如果你需要在腳本中訪問(wèn)共享了的材質(zhì),有一個(gè)很重的點(diǎn)需要注意:修改Renderer.material屬性會(huì)創(chuàng)建一個(gè)當(dāng)前材質(zhì)的副本茅主。
所以舞痰,作為替換方案,你應(yīng)該使用Rednerer.sharedMaterial以保證材質(zhì)被共享诀姚。
當(dāng)渲染陰影投射的時(shí)候响牛,即使他們的材質(zhì)是不同的,也經(jīng)常被batched到一起赫段。
只要材質(zhì)中的數(shù)值在shadow pass是相同的呀打,即使陰影投射有不同的材質(zhì),他們也可以使用動(dòng)態(tài)batching糯笙。
舉個(gè)例子贬丛,許多箱可以使用具有不同的texture的材質(zhì),但對(duì)于陰影投射渲染 texture是不相關(guān) - 在這種情況下给涕,他們可以被batched到在一起豺憔。
Dynamic Batching(動(dòng)態(tài)批處理)
Unity可以自動(dòng)batch移動(dòng)物體到相同的draw call额获,如果它們具有相同的材質(zhì)和滿足其它標(biāo)準(zhǔn)。動(dòng)態(tài)Batching是自動(dòng)完成的焕阿,不需要你做額外的事情咪啡。
Batching 動(dòng)態(tài)的物體每個(gè)頂點(diǎn)會(huì)有某些開(kāi)銷,所以batching只適用于頂點(diǎn)數(shù)小于900的meshes暮屡。如果你得shader使用了頂點(diǎn)位置撤摸,法線和單獨(dú)的UV,那么你可以batch 300 個(gè)頂點(diǎn);如果你得shader使用了頂點(diǎn)位置褒纲,法線准夷,UV0,UV1莺掠,和正切衫嵌,只能batch 180個(gè)頂點(diǎn)。
這個(gè)限制的數(shù)量將來(lái)有可能會(huì)變化彻秆。
其它限制
- 如果物體包含鏡像變換楔绞,他們將不會(huì)被batched,例如唇兑,object A 的scale 為 +1 object B 的scale 為-1酒朵,就不能batched到一起。
- 使用不同材質(zhì)的實(shí)例扎附,即使他們實(shí)質(zhì)上是相同的蔫耽,也會(huì)導(dǎo)致兩個(gè)物體不能被batched到一起。陰影投射除外留夜。
- 具有光照貼圖的對(duì)象有額外的渲染參數(shù):光照索引和 偏移/放縮 的光照匙铡。所以一般動(dòng)態(tài)lightmapped對(duì)象應(yīng)指向完全相同的光照貼圖位置然后再進(jìn)行batch。
- 多通道的shader將不會(huì)被batching幾乎所有的Unity shader都支持前置渲染幾個(gè)燈光碍粥,有效的為他們做更多的通道鳖眼。“額外的逐像素的燈光”的draw call 將不會(huì)被batched嚼摩。
- 傳統(tǒng)的延遲渲(逐通道光照)染通道禁用了動(dòng)態(tài)batching钦讳,因?yàn)樗仨毨L制兩次。
由于它的工作原理是變換所有的物體的頂點(diǎn)到CPU的世界坐標(biāo)中低斋,所以它僅僅在它的工作(變換到cpu的世界坐標(biāo))比做一次“draw call”小的時(shí)候才能起到好的作用。
究竟一個(gè)DrawCall有多昂貴取決于諸多因素匪凡,主要是所用的繪圖API膊畴。例如,在控制臺(tái)或當(dāng)前流 行的APIs例如Apple Metal DrawCall的開(kāi)銷一般比較低病游,所以一般動(dòng)態(tài)batching不會(huì)達(dá)到好的效果唇跨。
Static Batching(靜態(tài)批處理)
靜態(tài)batching允許引擎減少draw call適用于任何大小的幾何對(duì)象(假設(shè)沒(méi)有移動(dòng)和共享材質(zhì))稠通。大部分情況下他比動(dòng)態(tài)batching更高效 ,但是它會(huì)占用更多的內(nèi)存买猖。
為了使靜態(tài)batching更好的獲益改橘,你需要明確的指定游戲中某些物體是靜態(tài)的而且不會(huì)移動(dòng),旋轉(zhuǎn)或者縮放玉控。這樣做飞主,你可以在Inspector界面中的“Static”選項(xiàng)(chekbox)標(biāo)記物體為static:
使用靜態(tài)batching將需要額外的內(nèi)存來(lái)存儲(chǔ)合并后的幾何信息。如果幾個(gè)物體在靜態(tài)batching之前共享同一個(gè)幾何圖元高诺,那么這個(gè)幾何圖元將會(huì)為每個(gè)物體復(fù)制一份碌识,無(wú)論在Editor中還是runtime中都是如此。這不是一個(gè)好方法 - 有時(shí)候?yàn)榱吮3指〉膬?nèi)存占用量虱而,你必須犧牲渲染性能為了避免一些物體的靜態(tài)batching筏餐。例如,在一個(gè)稠密的森林中牡拇,標(biāo)記樹木為static會(huì)產(chǎn)生嚴(yán)重的內(nèi)存影響魁瞪。
在內(nèi)部,靜態(tài)batching的原理是變換這些靜態(tài)物體到世界控件然后為他們建立一個(gè)很大頂點(diǎn)+索引 緩沖區(qū)惠呼。然后所有顯示的物體都放到一個(gè)batch导俘,一系列“便宜的”draw call就完成了,這期間幾乎沒(méi)有狀態(tài)切換(state change)罢杉。所以 從技術(shù)上來(lái)講 這并沒(méi)有節(jié)省“3D API draw call”趟畏,但是他節(jié)省了他們之間的狀態(tài)切換(狀態(tài)切換才是罪魁禍?zhǔn)祝?/p>
Other Batching Related Tips
目前,只有網(wǎng)格渲染才被batched滩租。像 skinned meshes赋秀,cloth,拖尾渲染器(Trail Renderer)和其他類型的渲染組件是不被batched的律想。
半透明shader為了做透明度的工作猎莲,經(jīng)常需要物體以從后到前的順序進(jìn)行渲染。
Unity首先會(huì)對(duì)物體進(jìn)行排序技即,然后試著batch他們 - 因?yàn)檫@個(gè)順序是嚴(yán)格限制的著洼,這就意味著 相對(duì)于不透明物體來(lái)說(shuō),會(huì)有很少的batching產(chǎn)生而叼。
相對(duì)調(diào)用draw call來(lái)說(shuō)身笤,手動(dòng)合并比較近的物體可能是一個(gè)非常不錯(cuò)的選擇。
例如葵陵,許多抽屜的靜態(tài)柜子合并成一個(gè)mesh經(jīng)常是有道理的液荸,無(wú)論是在3D建模軟件中還是使用Mesh.CombineMeshaes.