感谢网上的前辈,因为他们的开源,奉献精神,技术开发才走到更远……
Cocos2d的渲染显示离不开图片资源,对应需要处理的资源部分主要有.png,plist(pvr),exportjson(json)三种格式,涉及到的资源加载及缓存包括如下几个部分:
Texture2D,TextureCache;
SpriteFrame,SpriteFrameCache;
Animation,AnimationCache;
骨骼动画部分涉及到一个异步加载资源的处理。这里大概梳理一下,方便查阅。
一,Texture2D,TextureCache
Texture2D(纹理):
一,简介:
1,纹理会存储在GPU内存中,纹理的像素格式决定了图片所占用的GPU内存,跟加载的所用的时间没有关系,
但可以通过减小PNG/GIF/TIFF/TMP等图片的大小来缩短加载的时间,也可以将图像格式导出成PVR格式,
IOS设备通常使用PowerVR显示芯片,而PVR格式的图片可以直接被该显示芯片直接读取,不需要解析直接显示,
渲染速度更快,更节省内存,pvr.ccz图像格式是pvr的压缩格式,占用空间更小。
2,普通的2D纹理就是一张图片,在OpenGL中称图片为贴图,在cocos2d里,纹理的使用主要分为两步:
1,从本地加载纹理图片,并将纹理数据读取到内存。
2,将内存里的纹理数据以copy的形式上传到GPU内存。
前者主要涉及到的问题是图片尺寸以及加载后的内存占用。
例如,我们要从本地加载了一张1024*1024的png图片(假设是RGBA8888格式),其大小约为1024*1024*4 = 4MB。这意味着,如果这张图片打包进安装包就会使整个程序增加4MB,如果在运行时加载到游戏里就相当于多了至少4MB内存。
二,内存占用
我们常见的图片,无论是png还是jpg图片,他们都是非压缩纹理。
非压缩纹理的意思是,这些图片的RGBA四个通道的像素数据在文件里都是按照一定顺序规则排列的。
类似于RGBA,RGBA,….,RGBA这样的排列,不同的非压缩格式图片的区别在于,有一些只使用了rgb三个通道值,
有一些使用的通道精度是小于28。
cocos2d支持十余种格式的非压缩纹理,上面提到的RGBA8888就是其中一种,也是最常见的一种(一般来说,没有特殊设置图片的像素格式就是RGBA8888)。并且图片的扩展名和它的像素格式没什么直接关系,一个png图片其像素格式可能是RGBA8888、RGBA4444也或者是其他格式。那么RGBA8888纹理有什么特别的地方呢?首先,该纹理格式上的每个像素点包括了R、G、B以及Alpha四个通道值,并且每个通道值是精度28,图片数据是以二进制存储的,我们知道28的bit值等于1byte,所以RGBA8888格式的纹理每个像素通道大小是1byte,所以该格式的纹理每个像素大小就是4*1byte = 4byte。 RGBA4444像素格式就是通道精度为 24,包含RGBA四个通道的纹理。其大小为4*0.5byte = 2byte。
由此可见,RGBA4444纹理的大小是RGBA8888的一半。也就是说,如果我们有张RGBA8888的纹理图片,如果能把它转化为RGBA4444,其尺寸立刻就减小了二分之一。但是我们也注意到RGBA4444相较于RGBA8888,其精度只有24=16。这种精度的损失对一些颜色渐变的纹理来说,影响比较明显。但是无论精度区间是[0,16]还是[0,256],这些像素都会被映射到OpenGL支持的[0,1]这个颜色区间。
三,创建方式
cocos2d提供了多种创建纹理的方式,内部最终走到initWithData方法,因为Texture2D支持直接渲染最后设置渲染的shader(GLProgram::SHADER_NAME_POSITION_TEXTURE),处理成像。
TextureCache(纹理缓存):
1,用于加载和管理纹理。一旦纹理加载完成,下次使用时可使用它返回之前加载的纹理,从而减少对GPU和CPU内存的占用。
如果文件名以前没有被加载时,它会创建一个新的Texture2D 对象,它会返回它。它将使用文件名作为key否则,它会返回一个引用先前加载的图像(TextureCache屏蔽了加载纹理的许多细节).
2,可以异步加载纹理。
利用 addImageAsync 方法。你可以很方面地给addImageAsync方法添加一个回调方法,这样,当纹理异步加载结束的时候,可以得到通知。
3,清理缓存。
//释放当前所有引用计数为1的纹理,即目前没有被使用的纹理。比如新场景创建好后,使用此方法释放没有使用的纹理非常方便。
Director::getInstance()->getTextureCache()->removeUnusedTextures();
//通过给定的纹理贴图(texture)的关键名(key name)从缓存中删除该纹理贴图
Director::getInstance()->getTextureCache()->removeTextureForKey("Images/grossinis.png");
// 清除加载纹理贴图的记录,如果你收到“内存警告”,请调用该方法。
// 在短期内 : 会释放一些资源文件来防止你的app出现闪退现象
// 在中期内 : 会分配更多资源
// 长远来看 : 没有区别
Director::getInstance()->getTextureCache()->removeAllTextures();