您好,登錄后才能下訂單哦!
這篇文章主要介紹了Unity性能優化之DrawCall的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Unity(或者說基本所有圖形引擎)生成一幀畫面的處理過程大致可以這樣簡化描述:
1. 引擎首先經過簡單的可見性測試,確定攝像機可以看到的物體
2. 然后把這些物體的頂點(包括本地位置、法線、UV等),索引(頂點如何組成三角形),變換(就是物體的位置、旋轉、縮放、以及攝像機位置等),相關光源,紋理,渲染方式(由材質/Shader決定)等數據準備好
3. 然后通知圖形API——或者就簡單地看作是通知GPU——開始繪制,GPU基于這些數據,經過一系列運算,在屏幕上畫出成千上萬的三角形,最終構成一幅圖像。
在Unity中,每次引擎準備數據并通知GPU的過程稱為一次Draw Call。
這一過程是逐個物體進行的,對于每個物體,不止GPU的渲染,引擎重新設置材質/Shader也是一項非常耗時的操作。
因此每幀的Draw Call次數是一項非常重要的性能指標,對于iOS來說應盡量控制在20次以內,這個值可以在編輯器的Statistic窗口看到。
Unity內置了Draw Call Batching技術,從名字就可以看出,它的主要目標就是在一次Draw Call中批量處理多個物體。
只要物體的變換和材質相同,GPU就可以按完全相同的方式進行處理,即可以把它們放在一個Draw Call中。
Draw Call Batching技術的核心就是在可見性測試之后,檢查所有要繪制的物體的材質,把相同材質的分為一組(一個Batch),然后把它們組合成一個物體(統一變換),這樣就可以在一個Draw Call中處理多個物體了(實際上是組合后的一個物體)。
但Draw Call Batching存在一個缺陷,就是它需要把一個Batch中的所有物體組合到一起,相當于創建了一個與這些物體加起來一樣大的物體。
與此同時就需要分配相應大小的內存。這不僅會消耗更多內存,還需要消耗CPU時間。
特別是對于移動的物體,每一幀都得重新進行組合,
但對于靜止不動的物體來說,只需要進行一次組合,之后就可以一直使用,效率要高得多。
這就需要進行一些權衡,否則得不償失。
Unity提供了Dynamic Batching和Static Batching兩種方式。
Dynamic Batching是完全自動進行的,不需要也無法進行任何干預。
對于頂點數在300以內的可移動物體,只要使用相同的材質,就會組成Batch
Static Batching則需要把靜止的物體標記為Static,然后無論大小,都會組成Batch。
如前文所說,Static Batching顯然比Dynamic Batching要高效得多,于是,Static Batching功能是收費的……
要有效利用Draw Call Batching,有以下注意點:
1. 首先是盡量減少場景中使用的材質數量,即盡量共享材質,對于僅紋理不同的材質可以把紋理組合到一張更大的紋理中(稱為Texture Atlasing)。
2. 然后是把不會移動的物體標記為Static。此外還可以通過CombineChildren腳本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手動把物體組合在一起,但這個腳本會影響可見性測試,因為組合在一起的物體始終會被看作一個物體,從而會增加GPU要處理的幾何體數量,因此要小心使用。
3. 對于復雜的靜態場景,還可以考慮自行設計遮擋剔除算法,減少可見的物體數量同時也可以減少Draw Call。
總之,理解Draw Call和Draw Call Batching原理,根據場景特點設計相應的方案來盡量減少Draw Call次數才是王道,其它方面亦然。
參考資料: http://ravenw.com/blog/2011/10/14/unity-optimization-of-draw-call/#sthash.eWSmEU7K.dpuf
開發游戲時,一定被時時提醒要減少 Draw Call,當然Unity也不例外,打開Game 窗口裡的 Stats,可以看到 Draw Call 與 Batched 的數字。
但到底甚麼是 Draw Call?影響的效能是來自 CPU?還是 GPU?
首先,讓我們定義何為 “Draw Call”:
“一個 Draw Call,等于呼叫一次 DrawIndexedPrimitive (DX) or glDrawElements (OGL),等于一個 Batch”
摸過 DirectX 或 OpenGL 的人來說,對 DrawIndexedPrimitive 與 glDrawElements 這 API 一定不陌生。
當我們準備好資料 (通常為三角面的頂點資料) 要 GPU 劃出來時,一定得調用這個函數。
換句話說,如果在畫面上有一張 “木” 椅子、一張 “鐵” 桌子,那理論上就會有兩個 Draw Call。
有看到特別指出 “木” 與 “鐵” 嗎?這代表兩物件是使用不同材質球或者不同的 Shader。
在 DirectX 或 OpenGL 里,對不同物件指定不同貼圖或不同 Shader 的描述,就會需要呼叫兩次Draw Call。
SetShader( “Diffuse" ); SetTexture( “鐵" ); DrawPrimitive( DeskVertexBuffer ); SetShader( “VertexLight" ); SetTexture( “木" ); DrawPrimitive( ChairVertexBuffer );
每次對 Shader 的更改或者貼圖的更改,基本上就是對 Rendering Pipeline 的設定做修改,所以需要不同的 Draw Call 來完成物件的繪制。
現在了解為什麼 UNITY 官方文件里,老是要你盡量使用同樣材質球,以減少 Draw Call 數量了吧!
在來談到 Batch,其實也是 Draw Call 的另一種稱呼。
你可以理解成每一次的 Draw Call 會產生一個 Batch,而 Batch 里裝的是物件頂點資料。
Batch 由 CPU 通過 “驅動程式” 將頂點資料送往 GPU,GPU接手后將物件畫在畫面上。
由此可知,越多 Draw Call,CPU 就越忙碌。這下更清楚知道 Draw Call 數量所影響的是 CPU 效能而非 GPU。
NVIDIA 在 GDC 曾提出,25K batchs/sec 會吃滿 1GHz 的 CPU,100% 的使用率。所以他們推出了一條公式,來預估游戲中大概可以 Run 多少個 Batch:
舉個例子:如果你的目標是游戲跑30FPS、使用2GHz的CPU、20%的工作量發給Draw Call來使用,那你每秒可以有多少Draw Call呢?
333 Batchs/Frame = 25K * 2 * (0.2/30)
那既然 Batch 是個箱子,里頭裝著物件的頂點資料,再依據我們上面的描述,
那將同樣材質和Shader 的物件,可以合併成一個 Batch 送往 GPU,這樣就是最省事的方法嘍?Yes!就是這樣沒錯!
UNITY 在 Player Setting 里的兩個功能選項 Static Batching 與 Dynamic Batching。功能描述如下:
Static Batching 是將標明為 Static 的靜態物件,如果在使用相同材質球的條件下,UNITY 會自動幫你把這兩個物件合併成一個 Batch,送往 GPU 來處理。
這功能對效能上非常的有幫助,所以是需要付費才有的
Dynamic Batching 是在物件小于300面的條件下(不論物件是否不靜態或動態),在使用相同材質球下,UNITY就會自動幫你合併成一個 Batch 送往 GPU 來處理。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Unity性能優化之DrawCall的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。