Cocos2d-x纹理管理
声明:本文分析的是cocos2d-x-3.12的代码
当需要显示图片时则需要使用图片创建一个纹理,OpenGL内部可以把纹理对象渲染出来,把图片显示出来。当使用图片创建一个精灵Sprite类时,cocos会生成应该纹理对象,让后把纹理与精灵关联起来。
纹理缓存TextureCache
Cocos的纹理是通过纹理缓存对象来管理的,所有的纹理都存储在TextureCache中。TextureCache类只在导演类Director里面有一个实例,导演类中有一个TextureCache变量 TextureCache *Director::_textureCache,textureCache变量在Director::init函数中进行调用Director::initTextureCache初始化。
void Director::initTextureCache()
{
_textureCache =new (std::nothrow)TextureCache();
}
在TextureCache类中有一个存放所有加载后纹理的哈希列表
std::unordered_map<std::string,Texture2D*> TextureCache::_textures;
哈希表string类型的Key,默认是纹理图片文件的绝对路径,所以这种情况下同一张图片只可以在纹理缓存中存放一次。当然也可以是自定义的字符串,如果是这种情况,则需要手动创建图片Image类对象。
加载纹理函数
Texture2D* addImage(conststd::string &filepath);
Texture2D* addImage(Image *image, const std::string &key);
Virtual void addImageAsync(const std::string &filepath,const std::function<void(Texture2D*)>&callback);
addImge(filepath)会先检查纹理是否已经加载,如果以加载则直接返回,否则会加载纹理并添加到纹理哈希表中。添加流程图大致如下:
addImageAsync是一个异步加载的函数,函数会创建一个线程来加载资源,因此程序主界面可以继续运行。参数callback会在加载完资源后调用。异步加载资源会在加载资源线程调用TextureCache::loadImage函数中加载图片生成Image对象,在TextureCache::addImageAsyncCallBack函数中生成Texture2D对象,并添加到纹理缓存哈希列表中。加载的流程图大致如下:
删除纹理函数
void removeAllTextures();
void removeUnusedTextures();
void removeTexture(Texture2D *texture);
void removeTextureForKey(const std::string &key);
removeUnusedTextures函数会移除所有引用计数为1的纹理对象,之所以移除引用计数为1的纹理,是因为纹理后如果没有任何精灵等使用,则引用计数为1,这样可以保证纹理一直在内存中,下次需要使用时不必从新加载,加载纹理非常耗时。
游戏中占有内存最多的部分就是纹理,可以达到90%,使用纹理缓存可以防止同一张图片纹理被多次加载到内存,从而节省内存。
纹理Texture2D
纹理类Texture2D,纹理加载后都是一个Texture2D类,并将Texture2D类保存在纹理缓存中。
纹理加载默认使用的纹理格式是图片设定的,大部分图片都是使用RGBA8888,32位的纹理,如果需要节省内存可以改用RGBA4444的图片。
纹理可以通过一个图片Image类初始化。
bool Texture2D::initWithImage(Image *image)
通过图像初始化纹理时,会检查平台最大支持的纹理尺寸,如果尺寸过大则会初始失败。
可以通过函数int Configuration::getMaxTextureSize() const获取当前平台支持的最大纹理尺寸。各个平台支持的最大纹理尺寸如下:
精灵Sprite类可以通过设定纹理来改变显示内容。
void Sprite::setTexture(Texture2D *texture)
图像Image
图像类,在加载图片是会创建一个图像Image类来加载图片。
Cocos2d支持的图片类型有:
JPEG、 PNG、 TIFF、WebP、PVR、ETC、S3TC、ATITC、TGA、 Raw Data
注意:不支持bmp格式的图片。