纹理贴图集中的每一个小图片需要对应一个它在贴图集中的尺寸和偏移量信息,这个信息就称作精灵框架(Sprite Frame)。有了精灵框架信息,就能够从大图中取出对应位置的小图。如果你有很多单独的图片,可以使用现有的工具创建贴图集。
TextureAtlas
TextureAtlas维持了多个Quad,它们都使用相同的纹理,使用相同的渲染参数,这样通过一次性绘制多个Quad来提高效率。 主要的成员变量:
GLushort* _indices; //索引 GLuint _VAOname; //VAO GLuint _buffersVBO[2]; //0: vertex 1: indices bool _dirty; //indicates whether or not the array buffer of the VBO needs to be updated /** quantity of quads that are going to be drawn */ ssize_t _totalQuads; /** quantity of quads that can be stored with the current texture atlas size */ ssize_t _capacity; /** Texture of the texture atlas */ Texture2D* _texture;//说明所有quad共享一个纹理 /** Quads that are going to be rendered */ V3F_C4B_T2F_Quad* _quads;
bool TextureAtlas::initWithTexture(Texture2D *texture, ssize_t capacity) { CCASSERT(capacity>=0, "Capacity must be >= 0"); // CCASSERT(texture != nullptr, "texture should not be null"); _capacity = capacity; _totalQuads = 0; // retained in property this->_texture = texture; CC_SAFE_RETAIN(_texture); // Re-initialization is not allowed 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: not enough memory"); CC_SAFE_FREE(_quads); CC_SAFE_FREE(_indices); // release texture, should set it to null, because the destruction will // release it too. see cocos2d-x issue #484 CC_SAFE_RELEASE_NULL(_texture); return false; } memset( _quads, 0, _capacity * sizeof(V3F_C4B_T2F_Quad) ); memset( _indices, 0, _capacity * 6 * sizeof(GLushort) ); #if CC_ENABLE_CACHE_TEXTURE_DATA /** listen the event that renderer was recreated on Android/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; return true; }
void updateQuad(V3F_C4B_T2F_Quad* quad, ssize_t index); //下面需要调用memmove移动内存 void insertQuad(V3F_C4B_T2F_Quad* quad, ssize_t index); void insertQuads(V3F_C4B_T2F_Quad* quads, ssize_t index, ssize_t amount); void removeQuadAtIndex(ssize_t index); void removeQuadsAtIndex(ssize_t index, ssize_t amount); //将_totalQuads置0 void removeAllQuads(); void increaseTotalQuadsWith(ssize_t amount); void moveQuadsFromIndex(ssize_t oldIndex, ssize_t amount, ssize_t newIndex); void moveQuadsFromIndex(ssize_t index, ssize_t newIndex); void fillWithEmptyQuadsFromIndex(ssize_t index, ssize_t amount); TextureAtlas有自己的绘制函数,在BatchCommand中维持一个TextureAtlas*,在其execute函数中 void BatchCommand::execute() { // Set material _shader->use(); _shader->setUniformsForBuiltins(_mv); GL::bindTexture2D(_textureID); GL::blendFunc(_blendType.src, _blendType.dst); // Draw _textureAtlas->drawQuads(); }