NO IMAGE

DrawCalls:

   DrawCall是CPU呼叫底層圖形介面。比如有上千個物體,每一個的渲染都需要去呼叫一次底層介面,而每一次的呼叫CPU都需要做很多工作,那麼CPU必然不堪重負。但是對於GPU來說,圖形處理的工作量是一樣的。所以對DrawCall的優化,主要就是為了儘量解放CPU在呼叫圖形介面上的開銷。所以針對drawcall我們主要的思路就是每個物體儘量減少渲染次數,多個物體最好一起渲染。所以,按照這個思路就有了以下幾個方案:

  1. 使用Draw Call Batching,也就是描繪呼叫批處理。Unity在執行時可以將一些物體進行合併,從而用一個描繪呼叫來渲染他們。具體下面會介紹。
  2. 通過把紋理打包成圖集來儘量減少材質的使用。
  3. 儘量少的使用反光啦,陰影啦之類的,因為那會使物體多次渲染。

Draw Call Batching

首先我們要先理解為何2個沒有使用相同材質的物體即使使用批處理,也無法實現Draw Call數量的下降和效能上的提升。

因為被“批處理”的2個物體的網格模型需要使用相同材質的目的,在於其紋理是相同的,這樣才可以實現同時渲染的目的。因而保證材質相同,是為了保證被渲染的紋理相同。

因此,為了將2個紋理不同的材質合二為一,我們就需要進行上面列出的第二步,將紋理打包成圖集。具體到合二為一這種情況,就是將2個紋理合成一個紋理。這樣我們就可以只用一個材質來代替之前的2個材質了。

而Draw Call Batching本身,也還會細分為2種。

Static Batching 靜態批處理

看名字,猜使用的情景。

靜態?那就是不動的咯。還有呢?額,聽上去狀態也不會改變,沒有“生命”,比如山山石石,樓房校舍啥的。那和什麼比較類似呢?嗯,聰明的各位一定覺得和場景的屬性很像吧!所以我們的場景似乎就可以採用這種方式來減少draw call了。

那麼寫個定義:只要這些物體不移動,並且擁有相同的材質,靜態批處理就允許引擎對任意大小的幾何物體進行批處理操作來降低描繪呼叫。

那要如何使用靜態批來減少Draw Call呢?你只需要明確指出哪些物體是靜止的,並且在遊戲中永遠不會移動、旋轉和縮放。想完成這一步,你只需要在檢測器(Inspector)中將Static核取方塊打勾即可

那我們總結一下動態批處理的約束,各位也許也能從中找到為何動態批處理在自己的專案中不起作用的原因:

  1. 批處理動態物體需要在每個頂點上進行一定的開銷,所以動態批處理僅支援小於900頂點的網格物體。
  2. 如果你的著色器使用頂點位置,法線和UV值三種屬性,那麼你只能批處理300頂點以下的物體;如果你的著色器需要使用頂點位置,法線,UV0,UV1和切向量,那你只能批處理180頂點以下的物體。
  3. 不要使用縮放。分別擁有縮放大小(1,1,1) 和(2,2,2)的兩個物體將不會進行批處理。
  4. 統一縮放的物體不會與非統一縮放的物體進行批處理。
  5. 使用縮放尺度(1,1,1) 和 (1,2,1)的兩個物體將不會進行批處理,但是使用縮放尺度(1,2,1) 和(1,3,1)的兩個物體將可以進行批處理。
  6. 使用不同材質的例項化物體(instance)將會導致批處理失敗。
  7. 擁有lightmap的物體含有額外(隱藏)的材質屬性,比如:lightmap的偏移和縮放係數等。所以,擁有lightmap的物體將不會進行批處理(除非他們指向lightmap的同一部分)。
  8. 多通道的shader會妨礙批處理操作。比如,幾乎unity中所有的著色器在前向渲染中都支援多個光源,併為它們有效地開闢多個通道。
  9. 預設體的例項會自動地使用相同的網格模型和材質。

所以,儘量使用靜態的批處理。