在Cocos2d-x中,精灵CCSprite对象可以直接通过加载图片的形式创建,这是最简单的形式, 这样做有两个弊端,一个是浪费内存,另一个是降低效率。 所谓浪费内存,其原因是在为图片分配内存空间时,需要分配超过图片尺寸的,且是最小的2的幂次的尺寸。如果图片长和宽分别是129px和65px,则分配的内存空间需要256*128*每个像素占用的内存字节数。可以发现实际的图片信息大约只占用了内存空间的1/4,也就是说将近3/4的内存空间被浪费了。每通过图片创建一个精灵,就会发生内存浪费的现象。精灵数量越多,内存的浪费越严重。 所谓降低效率,是指在生成精灵CCSprite对象的时候,Cocos2d-x会进行渲染操作。渲染操作包括图形处理硬件的准备渲染、执行渲染以及最后的清理工作。精灵越多,游戏的执行速度越慢。 那么如何解决呢?可以使用精灵批处理节点CCSpriteBatchNode与纹理贴图集解决,前者主要用于减少相同图片的渲染操作,后者可以有效节约内存。 如果游戏中需要创建很多基于相同图片的精灵,例如屏幕中的大量子弹,如果每次都单独创建一个精灵的话,每次都需要渲染。但是如果将他们加入到精灵批处理节点CCSpriteBatchNode中,则只需执行一次渲染即可。CCSpriteBatchNode类似于图层,它是一个精灵的容器,并且要求这些精灵都基于相同的图片(如果不是相同图片则报错)。 注意,由于创建的精灵都添加到了同一个批处理节点中,所以他们具有相同的Z序。 既然每次通过图片创建精灵都会发生内存浪费的现象,所以何不将所有图片整合成一张大图片呢?这张大图就称作纹理贴图集(Texture Atlas)。通过纹理贴图集和批处理节点,就可以达到既节省内存,又提升渲染速度的目的。纹理贴图集的长和宽都满足2的n次方,应该把尽可能多的图片放入一个纹理贴图集中。
纹理贴图集中的每一个小图片需要对应一个它在贴图集中的尺寸和偏移量信息,这个信息就称作精灵框架(Sprite Frame)。有了精灵框架信息,就能够从大图中取出对应位置的小图。如果你有很多单独的图片,可以使用现有的工具创建贴图集。
TextureAtlas TextureAtlas维持了多个Quad,它们都使用相同的纹理,使用相同的渲染参数,这样通过一次性绘制多个Quad来提高效率。 主要的成员变量:
- GLushort*_indices;
- GLuint_VAOname;
- GLuint_buffersVBO[2];
- bool_dirty;
-
- ssize_t_totalQuads;
- /**quantityofquadsthatcanbestoredwiththecurrenttextureatlassize*/
- ssize_t_capacity;
- /**Textureofthetextureatlas*/
- Texture2D*_texture;
- /**Quadsthataregoingtoberendered*/
- V3F_C4B_T2F_Quad*_quads;
来看一下init函数:
copy
boolTextureAtlas::initWithTexture(Texture2D*texture,ssize_tcapacity)
{
CCASSERT(capacity>=0,"Capacitymustbe>=0");
//CCASSERT(texture!=nullptr,"textureshouldnotbenull");
_capacity=capacity;
_totalQuads=0;
//retainedinproperty
this->_texture=texture;
CC_SAFE_RETAIN(_texture);
//Re-initializationisnotallowed
CCASSERT(_quads==nullptr&&_indices==nullptr,"");
//按照_capacity的大小先把内存分配好
_quads=(V3F_C4B_T2F_Quad*)malloc(_capacity*sizeof(V3F_C4B_T2F_Quad));
_indices=(GLushort*)malloc(_capacity*6*sizeof(GLushort));
if(!(_quads&&_indices)&&_capacity>0)
//CCLOG("cocos2d:TextureAtlas:notenoughmemory");
CC_SAFE_FREE(_quads);
CC_SAFE_FREE(_indices);
//releasetexture,shouldsetittonull,becausethedestructionwill
CC_SAFE_RELEASE_NULL(_texture);
returnfalse;
}
memset(_quads,_capacity*sizeof(V3F_C4B_T2F_Quad));
memset(_indices,_capacity*6*sizeof(GLushort));
#ifCC_ENABLE_CACHE_TEXTURE_DATA
/**listentheeventthatrendererwasrecreatedonAndroid/WP8*/
_rendererRecreatedListener=EventListenerCustom::create(EVENT_RENDERER_RECREATED,CC_CALLBACK_1(TextureAtlas::listenRendererRecreated,this));
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_rendererRecreatedListener,-1);
#endif
//给索引数组赋值
this->setupIndices();
//和Render类类似
if(Configuration::getInstance()->supportsShareableVAO())
{
setupVBOandVAO();
else
setupVBO();
_dirty=true;
}
TextureAtlas提供了对Quad的操作:
voidupdateQuad(V3F_C4B_T2F_Quad*quad,ssize_tindex);
- //下面需要调用memmove移动内存
- voidinsertQuad(V3F_C4B_T2F_Quad*quad,153); font-weight:bold; background-color:inherit">voidinsertQuads(V3F_C4B_T2F_Quad*quads,ssize_tindex,ssize_tamount);
- voidremoveQuadAtIndex(ssize_tindex);
- voidremoveQuadsAtIndex(ssize_tindex,0); background-color:inherit">//将_totalQuads置0
- voidremoveAllQuads();
- voidincreaseTotalQuadsWith(ssize_tamount);
- voidmoveQuadsFromIndex(ssize_toldIndex,ssize_tamount,ssize_tnewIndex);
- voidmoveQuadsFromIndex(ssize_tindex,ssize_tnewIndex);
- voidfillWithEmptyQuadsFromIndex(ssize_tindex,108); list-style:decimal-leading-zero outside; color:inherit; line-height:24px; margin:0px!important; padding:0px 3px 0px 10px!important"> TextureAtlas有自己的绘制函数,在BatchCommand中维持一个TextureAtlas*,在其execute函数中
- voidBatchCommand::execute()
- //Setmaterial
- _shader->use();
- _shader->setUniformsForBuiltins(_mv);
- GL::bindTexture2D(_textureID);
- GL::blendFunc(_blendType.src,_blendType.dst);
- //Draw
- _textureAtlas->drawQuads();
}
转自http://blog.csdn.net/majianfei1023/article/details/51106709
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|