詳解CocosCreator優(yōu)化之DrawCall
前言
在游戲開發(fā)中,DrawCall 作為一個非常重要的性能指標(biāo),直接影響游戲的整體性能表現(xiàn)。
無論是 Cocos Creator、Unity、Unreal 還是其他游戲引擎,只要說到游戲性能優(yōu)化,DrawCall 都是絕對少不了的一項。
本文將會介紹什么是 DrawCall,為什么要減少 DrawCall 以及在 Cocos Creator 項目中如何減少 DrawCall 來提升游戲性能。
什么是 DrawCall
DrawCall就是CPU調(diào)用圖形庫(比如DirectX或OpenGL)的圖形繪制接口,來命令GPU進(jìn)行渲染的操作。
DrawCall 是如何影響性能的呢?
先舉個栗子:
http形式從服務(wù)器拉取1024個大小1kb的文件和單個大小為1M的文件,哪個耗時更短?
答:肯定是拉取單個1M的更快。
原因就是每個請求之前,http 都需要做許多的準(zhǔn)備工作來保證文件能夠正常傳輸。而正是這些額外工作,造成了很多時間和性能開銷。
而每一次繪制CPU都要調(diào)用DrawCall,而在調(diào)動DrawCall前,CPU還要進(jìn)行很多準(zhǔn)備工作:檢測渲染狀態(tài)、提交渲染所需要的數(shù)據(jù)、提交渲染所需要的狀態(tài)。
而GPU本身具有很強大的計算能力,可以很快就處理完渲染任務(wù)。一般來說,繪制 100 個三角形和繪制 1000 個三角形所消耗的時間沒差多少。
但是,當(dāng) DrawCall 過多,CPU就會很多額外開銷用于準(zhǔn)備工作,CPU本身負(fù)載,而這時GPU可能閑置了。
**也就是說,正是因為每次渲染前,CPU 都需要做一系列準(zhǔn)備工作,而 CPU 的每一次內(nèi)存顯存讀寫、數(shù)據(jù)處理和渲染狀態(tài)切換都會帶來一定的性能和時間消耗,積少成多,而 GPU 大部分時間都在摸魚。
所以才造成了我們認(rèn)知中的,DrawCall 數(shù)量過多導(dǎo)致了卡頓 **
如何減少 DrawCall
如上所說,我們可以通過一次多給 CPU 分配點工作,讓一次渲染的內(nèi)容多一些,減少分配次數(shù),來達(dá)到我們的目的。
話是這么說,可是我們應(yīng)該怎么實際操作呢?往下看
針對圖片資源
靜態(tài)合圖
就是講碎圖整合成一張大圖,即我們常說的 打圖集。
但是圖集也不是隨便打的,并不是一張大圖容納越多的碎圖越好。這里面也是有一定的門道的。
盡量將處于同一界面(UI)下的相鄰且渲染狀態(tài)相同的碎圖打包成圖集
對于Creator來說,在游戲運行時引擎是按照節(jié)點層級順序從上往下由淺到深進(jìn)行渲染的,理論上 每渲染一張圖像(文本最終也是圖像)都需要一次 DrawCall。
渲染狀態(tài)是指:紋理狀態(tài)(預(yù)乘、循環(huán)模式和過濾模式)或 Material(材質(zhì))、Blend(混合模式)等等,所以使用自定義 Shader 也會打斷合批
所以 相鄰且渲染狀態(tài)相同 是關(guān)鍵點。
tip: 不建議任何圖片資源的尺寸超過2048*2048,否則可能會出現(xiàn)加載相關(guān)的問題。
下面介紹2種打圖集的方式
自動圖集資源(Auto Atlas)
利用 Cocos Creator 內(nèi)置的自動圖集資源來將碎圖打包成圖集。
在項目構(gòu)建時,編輯器會將所有自動圖集資源所在文件夾下的所有符合要求的圖像分別根據(jù)配置打包成一個或多個圖集。
自動圖集資源使用起來很靈活,編輯器在打包圖集時會自動遞歸子目錄,若子目錄下也有自動圖集資源(即 .pac 文件)則會跳過該目錄,所以我們可以對同一目錄下的不同部分的碎圖配置不同的參數(shù)。
關(guān)于自動圖集的幾點建議
合理控制圖集最大尺寸,避免單個圖像加載時間過長。尺寸太大的圖像沒有必要打進(jìn)圖集(如背景圖)。善用九宮格(Sliced)可以節(jié)省很多空間(這一點需要美術(shù)大佬配合)。間距保持默認(rèn)的 2 并保持勾選擴(kuò)邊選項,避免圖像裁剪錯誤和出現(xiàn)黑邊的情況。勾選不包含未被引用資源選項,自動排除沒有用到的圖像以節(jié)省空間(該選項預(yù)覽時無效)。開發(fā)時預(yù)覽圖集,根據(jù)結(jié)果進(jìn)行調(diào)整,以達(dá)到最好的優(yōu)化效果。
TexturePacker
使用 TexturePacker 打包圖集時需要注意配置「形狀填充(Shape Padding,對應(yīng) Auto Atlas 中的間距)」,避免某張圖像出現(xiàn)相鄰圖像的像素的情況。
對比一下
Auto Atlas
- Cocos Creator 內(nèi)置,方便
- 功能不多但是該有的都有
- 項目構(gòu)建時才生成圖集,開發(fā)時任意修改無壓力
- 圖集尺寸在生成時自適應(yīng),節(jié)省空間
- 支持自動紋理壓縮
TexturePacker
- 第三方軟件需自行安裝,不夠方便
- 收費功能很多很專業(yè)但是基本用不著,免費功能也夠用
- 先生成圖集再使用,更換圖像又要重新生成圖集
- 尺寸固定需要自己設(shè)置
- 不支持自動紋理壓縮 動態(tài)合圖
Creator 官方說明:
Cocos Creator 提供了在項目構(gòu)建時的靜態(tài)合圖方法 —— 「自動合圖」(Auto Atlas)。但是當(dāng)項目日益壯大的時候貼圖會變得非常多,很難將貼圖打包到一張大貼圖中,這時靜態(tài)合圖就比較難以滿足降低 DrawCall 的需求。
所以 Cocos Creator 在 v2.0 中加入了 「動態(tài)合圖」(Dynamic Atlas)的功能,它能在項目運行時動態(tài)的將貼圖合并到一張大貼圖中。當(dāng)渲染一張貼圖的時候,動態(tài)合圖系統(tǒng)會自動檢測這張貼圖是否已經(jīng)被合并到了圖集(圖片集合)中,如果沒有,并且此貼圖又符合動態(tài)合圖的條件,就會將此貼圖合并到圖集中。
動態(tài)合圖官方文檔:
https://docs.cocos.com/creator/manual/zh/advanced-topics/dynamic-atlas.html
動態(tài)圖集有2個限制:
- 動態(tài)圖集尺寸最大是 2048 * 2048
- 碎圖的尺寸默認(rèn)不能超過 512,可通過 API 進(jìn)行修改:
cc.dynamicAtlasManager.maxFrameSize = 512
tips: 啟用動態(tài)合圖會增大內(nèi)存消耗,不同平臺占用內(nèi)存不一致。小游戲和原生平臺默認(rèn)禁止動態(tài)合圖??梢酝ㄟ^ api 自行開啟:cc.macro.CLEANUP_IMAGE_CACHE = false; cc.dynamicAtlasManager.enabled = true;
還需要保證紋理的 Premulyiply Alpha(預(yù)乘)、Wrap Mode(循環(huán)模式) 和 Filter Mode(過濾模式) 等信息與動態(tài)圖集一致才能夠動態(tài)合批。
另外,靜態(tài)圖集也能參與動態(tài)合圖,只要滿足動態(tài)合圖的要求即可。
tip1: 自動圖集資源(Auto Atlas)需要在其屬性檢查器面板中開啟 Texture 欄下的 Packable 選項,該選項默認(rèn)是禁用的。
tip2: 精靈(Sprite)也是需要開啟 Packable 選項才能動態(tài)合圖。該選項默認(rèn)是開啟的。
tip3: 如果要使用了 shader ,那么需要禁用該精靈的 Packable 選項。
針對 Label
位圖字體(BMFont)
在 Creator 中使用系統(tǒng)字體或 TTF 字體的 Label 會打斷渲染合批,特別是 Label 和 Sprite 層疊交錯的情況,每一個 Label 都會打斷合批增加一個 DrawCall。
因此建議使用 BMFont 來代替 TTF 或系統(tǒng)字體,并且將 BMFont 與 UI 碎圖打包到同一圖集中(或「開啟動態(tài)合圖」),可以免除大部分文本導(dǎo)致的 DrawCall增加。
文本緩存模式(Cache Mode)
Creator 2.0.9 版本在 Label 組件上增加了 Cache Mode 選項,來解決系統(tǒng)字體和 TTF 字體帶來的性能問題。
CacheMode有三種選項:
- NONE(默認(rèn)) 每一個 Label 都會生成為一張單獨的位圖,且不會參與動態(tài)合圖,所以每一個 Label 都會打斷渲染合批
- BITMAP 開啟 BITMAP 模式后,文本同樣會生成為一張位圖,但是只要符合動態(tài)合圖要求就可以參與動態(tài)合圖,和周圍的精靈合并 DrawCall 。一定要注意 BITMAP 模式只適用于不頻繁更改的文本,否則內(nèi)存會爆炸。
- CHAR 開啟 CHAR 模式后,引擎會將該 Label 中出現(xiàn)的所有字符緩存到一張全局共享的位圖中,相當(dāng)于是生成了一個 BMFont 。適用于文本頻繁更改的情況,對性能和內(nèi)存最友好。tip: 該模式 只能用于字體樣式和字號固定,并且不會頻繁出現(xiàn)巨量未使用過的字符 的 Label。因為共享位圖的最大尺寸為 2048*2048,占滿了之后就沒辦法再渲染新的字符,需要切換場景才會清除共享位圖。
總結(jié):對于大量頻繁更改的文本,使用 CHAR 模式帶來的性能提升是非常明顯的。
同時 CHAR 模式的局限也很明顯,一般用于場景中出現(xiàn)大量數(shù)字文本,類似于經(jīng)驗值增加、血量減少之類的特效的情況
必經(jīng)之路–調(diào)整UI層級順序
原則:
分離圖像節(jié)點和文本節(jié)點文本使用 BMFont 或 Cache Mode 選項,盡量出現(xiàn)避免文本打斷渲染合批的情況FBI WARNING: 一個 Mask 組件及其控制的渲染節(jié)點,需要至少三次 Draw call。第一次開啟模板測試并調(diào)用一次 Draw call,刷新模板緩沖。第二次繪制對需要通過模板測試的區(qū)域進(jìn)行設(shè)置。第三次再進(jìn)行實際的子節(jié)點內(nèi)容繪制,繪制結(jié)束再關(guān)閉模板測試。因此 使用 Mask 組件就無法與其他相鄰節(jié)點進(jìn)行批次處理 ,但是 Mask 組件內(nèi)部的連續(xù)節(jié)點在滿足合并規(guī)則的情況下還是會進(jìn)行合批。
總結(jié)
改變渲染狀態(tài)會打斷渲染合批,例如改變紋理狀態(tài)(預(yù)乘、循環(huán)模式和過濾模式)或改變 Material(材質(zhì))、Blend(混合模式)等等,所以使用自定義 Shader 也會打斷合批。圖集默認(rèn)不參與動態(tài)合圖,手動開啟自動圖集資源的 Packable 選項后如果最終圖集符合動態(tài)合圖要求也可以參與動態(tài)合圖。紋理開啟 Packable 選項參與動態(tài)合圖后無法使用自定義 Shader,因為動態(tài)合圖會修改原始貼圖的 UV 坐標(biāo)。使用 Cache Mode 的 BITMAP 模式需要注意內(nèi)存情況,CHAR 模式需要注意文本內(nèi)容不宜過多。在 ***Cocos Creator 2.0.7 之前的版本***中,改變節(jié)點的顏色或透明度、Sprite 組件使用九宮格(Sliced)都會打斷渲染合批
以上就是詳解CocosCreator優(yōu)化之DrawCall的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator優(yōu)化DrawCall的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
前端實現(xiàn)讀取word文件并將其原樣式展示的幾種方案
在前端直接讀取并原樣展示W(wǎng)ord文檔是一個相對復(fù)雜的任務(wù),因為Word文檔的格式(如.doc或.docx)與Web技術(shù)棧使用的格式(HTML、CSS)不兼容,這篇文章主要給大家介紹了關(guān)于前端實現(xiàn)讀取word文件并將其原樣式展示的幾種方案,需要的朋友可以參考下2024-08-08JS實現(xiàn)的仿東京商城菜單、仿Win右鍵菜單及仿淘寶TAB特效合集
這篇文章主要介紹了JS實現(xiàn)的仿東京商城菜單、仿Win右鍵菜單及仿淘寶TAB特效合集,以實例形式較為詳細(xì)的分析了JavaScript實現(xiàn)動態(tài)添加下拉菜單及響應(yīng)鼠標(biāo)事件生成菜單等實現(xiàn)技巧,需要的朋友可以參考下2015-09-09express+mockjs實現(xiàn)模擬后臺數(shù)據(jù)發(fā)送功能
這篇文章主要介紹了express+mockjs實現(xiàn)模擬后臺數(shù)據(jù)發(fā)送功能,需要的朋友可以參考下2018-01-01javascript加載xml 并解析各節(jié)點的值(實現(xiàn)方法)
下面小編就為大家?guī)硪黄猨avascript加載xml 并解析各節(jié)點的值(實現(xiàn)方法)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10