cocoscreator 淺析Label 的三種緩存模式

為了解決系統(tǒng)字經(jīng)常打斷合批的問題耘柱,cocos提供了三種緩存模式:官網(wǎng)文檔

image.png

CacheMode.NONE: 先用網(wǎng)頁canvas渲染文字,然后用Texture2D.initWithElement(canvas)獲取紋理
CacheMode.BITMAP: 跟CacheMode.NONE差不多斜做,區(qū)別就是會(huì)將實(shí)時(shí)獲取到的紋理放到動(dòng)態(tài)合集里,于是就能跟附近的同類型Label或者使用動(dòng)態(tài)圖集的Sprite進(jìn)行合批略水。
CacheMode.CHAR:會(huì)先將label拆成一個(gè)個(gè)單獨(dú)的字徽诲,每一個(gè)字都用以上的方法獲取生成的紋理,放在一個(gè)專門存放此類字符紋理的大圖內(nèi)牡属,然后渲染的時(shí)候使用多個(gè)頂點(diǎn)票堵,按每個(gè)字符一個(gè)矩形渲染。

我們先來看下幾種緩存模式下運(yùn)行時(shí)的區(qū)別
image.png

如上圖逮栅,None模式下悴势,每個(gè)label都占一個(gè)drawcall,即使內(nèi)容相同也不例外措伐,此時(shí)內(nèi)存中三個(gè)label紋理+一個(gè)sprite紋理+FPS label紋理特纤。
Bitmap模式下,三個(gè)Label和Sprite共占一個(gè)drawcall侥加,是因?yàn)槿龔坙abel的紋理和sprite的紋理打到了一個(gè)動(dòng)態(tài)圖集里面捧存。我們可以打印出動(dòng)態(tài)圖集:

let _debugNode = cc.dynamicAtlasManager.showDebug(true);
_debugNode.getComponent(cc.ScrollView).content.children[0].color = cc.Color.RED
_debugNode.scale = 0.5;
image.png

紅色的就是動(dòng)態(tài)圖集,可以注意到即使是一模一樣的Label,在自動(dòng)圖集里也不會(huì)共用貼圖昔穴,有多少個(gè)BITMAP緩存模式的Label镰官,就有多少份字體貼圖,所以如果我們的游戲里有大量相同的label吗货,更加適合用CHAR緩存模式泳唠。

再看CHAR模式,CHAR模式下相當(dāng)于是全局共用一個(gè)2048x2048的位圖字體:cc.Label._shareAtlas宙搬,
我們打印一下該字體的紋理:

let shareLabelTex = cc.Label._shareAtlas.getTexture()
let spr = _debugNode.getComponent(cc.ScrollView).content.children[0].getComponent(cc.Sprite)
spr.spriteFrame.setTexture(shareLabelTex)
image.png

從上圖順便可以看出警检,系統(tǒng)FPS信息Label就是用的CHAR模式。

下面我們跟著Label源碼來看看害淤,幾種模式分別是怎么裝配渲染數(shù)據(jù)的

我們今天討論的范圍是非native環(huán)境下2d系統(tǒng)字扇雕。


image.png

從這段代碼可知,CHAR模式下對(duì)應(yīng)的Assembler是Letter窥摄,NONE模式和BITMAP模式的Assembler都是TTF镶奉。Label組件就是通過這些Assembler將字體數(shù)據(jù)變成紋理數(shù)據(jù)進(jìn)而顯示的,先看看他們是怎么關(guān)聯(lián)的:


image.png

每次系統(tǒng)字相關(guān)設(shè)置發(fā)生變化崭放,組件都會(huì)調(diào)用_applyFontTexture重新初始化紋理數(shù)據(jù)哨苛,非CHAR模式下,是直接創(chuàng)建一個(gè)新的Texture2D紋理币砂,通過canvas初始化(紅框部分)建峭。
而每次諸如Label.string發(fā)生改變后,會(huì)更新渲染數(shù)據(jù)决摧,讓canvas重新繪制字體亿蒸,從而使_ttfTexture得到刷新:
(因?yàn)橛玫搅藈eb端的畫布渲染,所以顯然不能適用于native端掌桩,native端另有適配)

嘗試寫入一份紋理拷貝到自動(dòng)圖集

NONE模式和BITMAP模式的Assembler都是TTF边锁,唯一的區(qū)別就是BITMAP模式下,會(huì)在生成完紋理后波岛,將該紋理拷貝一份到自動(dòng)圖集茅坛,然后使用自動(dòng)圖集里面的內(nèi)容。所以BITMAP的優(yōu)勢(shì)是能與周圍使用自動(dòng)圖集的碎圖一起合批则拷,但同時(shí)也會(huì)加大自動(dòng)圖集的消耗贡蓖。內(nèi)容或字體大小等頻繁變化的不要使用BITMAP模式,因?yàn)槊克⑿乱淮位筒纾蜁?huì)拷貝一次最新紋理到自動(dòng)圖集斥铺。

關(guān)于CHAR模式,就有點(diǎn)繞了宣旱,生成紋理的方式還是一樣仅父,但不是 每個(gè)Label生成一個(gè)紋理,而是每個(gè)先把Label字符串分開浑吟,按每個(gè)字符去生成紋理笙纤,然后嘗試拷貝紋理到共用的LetterAtlas大圖,然后下次再遇到相同參數(shù)的字符组力,就直接取大圖紋理省容。


image.png

上圖中,紅色的就是CHAR LABEL的公共紋理燎字,可以看到腥椒,字體大小不同時(shí),即使內(nèi)容相同候衍,也會(huì)使用不同的紋理內(nèi)容笼蛛。


image.png

所謂相同參數(shù),就是上圖的shareLabelInfo的color蛉鹿、fontSize滨砍、fontFamily、outline妖异、margin惋戏,然后再與字符內(nèi)容相加,得到的hash值他膳,然后維護(hù)一個(gè)_letterDefinitions表响逢,每增加一個(gè)新的letterTexture,就拷貝一份到公共大紋理棕孙,然后保存紋理坐標(biāo)舔亭、寬、高等信息蟀俊,hash為鍵值分歇。


image.png

其實(shí)跟向動(dòng)態(tài)圖集插入紋理差不多,只不過系統(tǒng)字剛好有一些可以比較衡量的參數(shù)欧漱,所以比動(dòng)態(tài)圖集更方便的是可以判斷某個(gè)小的字符紋理有沒有被加到大圖中职抡,有的話就直接取。

然后再一點(diǎn)就是CHAR模式下误甚,頂點(diǎn)數(shù)據(jù)有所不同缚甩,普通的Sprite或者Label,都是一個(gè)矩形窑邦、4個(gè)頂點(diǎn)擅威、兩個(gè)三角形,CHAR模式下冈钦,每個(gè)字符所用的紋理是不連續(xù)的郊丛,可能在大圖中的任意位置,所以必須每個(gè)字符使用一套紋理坐標(biāo),有n個(gè)字符厉熟,就有n x 4個(gè)頂點(diǎn)导盅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揍瑟,隨后出現(xiàn)的幾起案子白翻,更是在濱河造成了極大的恐慌,老刑警劉巖绢片,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滤馍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡底循,警方通過查閱死者的電腦和手機(jī)巢株,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熙涤,“玉大人纯续,你說我怎么就攤上這事∶鹪” “怎么了猬错?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茸歧。 經(jīng)常有香客問我倦炒,道長,這世上最難降的妖魔是什么软瞎? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任逢唤,我火速辦了婚禮,結(jié)果婚禮上涤浇,老公的妹妹穿的比我還像新娘鳖藕。我一直安慰自己,他們只是感情好只锭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布著恩。 她就那樣靜靜地躺著,像睡著了一般蜻展。 火紅的嫁衣襯著肌膚如雪喉誊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天纵顾,我揣著相機(jī)與錄音伍茄,去河邊找鬼。 笑死施逾,一個(gè)胖子當(dāng)著我的面吹牛敷矫,可吹牛的內(nèi)容都是我干的例获。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼曹仗,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼榨汤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起整葡,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎讥脐,沒想到半個(gè)月后遭居,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旬渠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年俱萍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片告丢。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡枪蘑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岖免,到底是詐尸還是另有隱情岳颇,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布颅湘,位于F島的核電站话侧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏闯参。R本人自食惡果不足惜瞻鹏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹿寨。 院中可真熱鬧新博,春花似錦、人聲如沸脚草。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馏慨。三九已至涩蜘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間熏纯,已是汗流浹背同诫。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留樟澜,地道東北人误窖。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓叮盘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霹俺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柔吼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容