在creator中,為了降低DC勋颖,提供了一個方法侨赡,在項目運行的時候蓖租,運行時將內(nèi)存中的任意紋理組合成一張虛擬的圖集,當(dāng)渲染一張貼圖的時候羊壹,動態(tài)合圖系統(tǒng)會自動檢測這張貼圖是否已經(jīng)被加入到了動態(tài)合圖系統(tǒng)蓖宦,如果沒有,并且此貼圖又符合動態(tài)合圖的條件油猫,就會將此貼圖合并到動態(tài)合圖系統(tǒng)生成的大貼圖中稠茂。
動態(tài)合圖?是按照?渲染順序?來選取要將哪些貼圖合并到一張大圖中的,這樣就能確保相鄰的 DrawCall 能合并為一個 DrawCall情妖。
注意事項:
在場景加載前睬关,動態(tài)合圖系統(tǒng)會進(jìn)行重置,?SpriteFrame貼圖的引用和 uv 都會恢復(fù)到初始值毡证。
Cocos Creator是如何實現(xiàn)這個功能的呢电爹?
核心思想是數(shù)據(jù)結(jié)構(gòu)中常說的空間換時間, 原理其實并不復(fù)雜料睛,就是幀緩存丐箩,簡單來說就是將多份spriteFrame繪制到RenderTexture上,并記錄其在新的RenderTexture中所屬的位置和長寬恤煞,渲染的時候利用這些信息從RenderTexture所得到的紋理上取所需要的區(qū)域`
```
onstAtlas=require('./atlas');
let_atlases=[];
let_atlasIndex=-1;
let_maxAtlasCount=5;
let_textureSize=2048;
// Smaller frame is more likely to be affected by linear filter
let_minFrameSize=8;
let_maxFrameSize=512;
let_debugNode=null;
functionnewAtlas(){
letatlas=_atlases[++_atlasIndex]
if(!atlas){
atlas=newAtlas(_textureSize,_textureSize);
_atlases.push(atlas);
}
returnatlas;
}
functionbeforeSceneLoad(){
dynamicAtlasManager.reset();
}
let_enabled=false;
/**
* !#en Manager the dynamic atlas.
* !#zh 管理動態(tài)圖集屎勘。
*@classDynamicAtlasManager
*/
letdynamicAtlasManager={
/**
? ? * !#en Enabled or Disabled dynamic atlas.
? ? * !#zh 開啟或者關(guān)閉動態(tài)圖集。
*@propertyenabled
*@type{Boolean}
? ? */
getenabled(){
return_enabled;
},
setenabled(value){
if(_enabled===value)return;
if(value){
this.reset();
cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH,beforeSceneLoad);
}
else{
cc.director.off(cc.Director.EVENT_BEFORE_SCENE_LAUNCH,beforeSceneLoad);
}
_enabled=value;
},
/**
? ? * !#en The maximum number of atlas that can be created.
? ? * !#zh 可以創(chuàng)建的最大圖集數(shù)量阱州。
*@propertymaxAtlasCount
*@type{Number}
? ? */
getmaxAtlasCount(){
return_maxAtlasCount;
},
setmaxAtlasCount(value){
_maxAtlasCount=value;
},
/**
? ? * !#en The size of the atlas that was created
? ? * !#zh 創(chuàng)建的圖集的寬高
*@propertytextureSize
*@type{Number}
? ? */
gettextureSize(){
return_textureSize;
},
settextureSize(value){
_textureSize=value;
},
/**
? ? * !#en The maximum size of the picture that can be added to the atlas.
? ? * !#zh 可以添加進(jìn)圖集的圖片的最大尺寸挑秉。
*@propertymaxFrameSize
*@type{Number}
? ? */
getmaxFrameSize(){
return_maxFrameSize;
},
setmaxFrameSize(value){
_maxFrameSize=value;
},
/**
? ? * !#en Append a sprite frame into the dynamic atlas.
? ? * !#zh 添加碎圖進(jìn)入動態(tài)圖集。
*@methodinsertSpriteFrame
*@param{SpriteFrame} spriteFrame
? ? */
insertSpriteFrame(spriteFrame){
if(CC_EDITOR)returnnull;
if(!_enabled||_atlasIndex===_maxAtlasCount||
!spriteFrame||spriteFrame._original)returnnull;
lettexture=spriteFrame._texture;
if(textureinstanceofcc.RenderTexture||texture._isCompressed())returnnull;
letw=texture.width,h=texture.height;
if(w>_maxFrameSize||h>_maxFrameSize||w<=_minFrameSize||h<=_minFrameSize
||texture._getHash()!==Atlas.DEFAULT_HASH){
returnnull;
}
letatlas=_atlases[_atlasIndex];
if(!atlas){
atlas=newAtlas();
}
letframe=atlas.insertSpriteFrame(spriteFrame);
if(!frame&&_atlasIndex!==_maxAtlasCount){
atlas=newAtlas();
returnatlas.insertSpriteFrame(spriteFrame);
}
returnframe;
},
/**
? ? * !#en Resets all dynamic atlas, and the existing ones will be destroyed.
? ? * !#zh 重置所有動態(tài)圖集苔货,已有的動態(tài)圖集會被銷毀犀概。
*@methodreset
? ? */
reset(){
for(leti=0,l=_atlases.length;i<l;i++){
_atlases[i].destroy();
}
_atlases.length=0;
_atlasIndex=-1;
},
/**
? ? * !#en Displays all the dynamic atlas in the current scene, which you can use to view the current atlas state.
? ? * !#zh 在當(dāng)前場景中顯示所有動態(tài)圖集,可以用來查看當(dāng)前的合圖狀態(tài)夜惭。
*@methodshowDebug
*@param{Boolean} show
? ? */
showDebug:CC_DEV&&function(show){
if(show){
if(!_debugNode||!_debugNode.isValid){
letwidth=cc.visibleRect.width;
letheight=cc.visibleRect.height;
_debugNode=newcc.Node('DYNAMIC_ATLAS_DEBUG_NODE');
_debugNode.width=width;
_debugNode.height=height;
_debugNode.x=width/2;
_debugNode.y=height/2;
_debugNode.zIndex=cc.macro.MAX_ZINDEX;
_debugNode.parent=cc.director.getScene();
_debugNode.groupIndex=cc.Node.BuiltinGroupIndex.DEBUG;
cc.Camera._setupDebugCamera();
letscroll=_debugNode.addComponent(cc.ScrollView);
letcontent=newcc.Node('CONTENT');
letlayout=content.addComponent(cc.Layout);
layout.type=cc.Layout.Type.VERTICAL;
layout.resizeMode=cc.Layout.ResizeMode.CONTAINER;
content.parent=_debugNode;
content.width=_textureSize;
content.anchorY=1;
content.x=_textureSize;
scroll.content=content;
for(leti=0;i<=_atlasIndex;i++){
letnode=newcc.Node('ATLAS');
lettexture=_atlases[i]._texture;
letspriteFrame=newcc.SpriteFrame();
spriteFrame.setTexture(_atlases[i]._texture);
letsprite=node.addComponent(cc.Sprite)
sprite.spriteFrame=spriteFrame;
node.parent=content;
}
}
}
else{
if(_debugNode){
_debugNode.parent=null;
_debugNode=null;
}
}
},
update(){
if(!this.enabled)return;
for(leti=0;i<=_atlasIndex;i++){
_atlases[i].update();
}
},
};
/**
*@modulecc
*/
/**
*@propertydynamicAtlasManager
*@typeDynamicAtlasManager
*/
module.exports=cc.dynamicAtlasManager=dynamicAtlasManager;
```