http://wap.oschina.net/question/565065_79814
在目前的移动平台游戏开发过程中,很多朋友会遇到开发出来的DEMO占用内存过大,导致渲染效率低下的问题。究其原因,是由硬件本身和软件逻辑两方面的因素造成的。在硬件上,移动设备往往可用内存相比于PC还比较小,所以所能使用的内存就少。在软件逻辑上,大量使用大图片导致占用内存过大,以及过多单图片导致渲染时多次切换使用的纹理,也会大大降低渲染效率。本节我将带领大家进入到纹理优化的实际操作中,希望可以抛砖引玉,使大家对于纹理优化有更好的认识。
首先,硬件的内存限制我们是没有办法逾越的。比如当下流行的Iphone 4S 总内存容量为512M,而实际可用的内存大大少于这个数字,所以在你开发一款游戏时,一定要清楚的知道你的程序在运行时的内存需求量,它务必要小于可用内存,而且要越少越好。我们在开发2D游戏时,最多用到的资源就是纹理,一张宽高均为1024大小的格式为RGBA8888的纹理。其占用的内存量至少是4M。所以,你一定要在纹理的优化上下功夫。
纹理的优化,方案有很多。我们逐个来列举。
(1)色深优化
大家先来看一下下面这张对比图:
第一张图是A8R8G8B8格式,第二张图是我转为A1R5G5B5后的PVR图,我以一个一般玩家的视角来看是看不出有什么差别的。但是第一个图每个像素占4字节,而第二张图每个像素占2字节。这意味着看起来几乎相同的图片,占用的内存可以减少一半。
这一方案并不适用于所有情况,你需要对每种图片进行考虑,如果说你的图片的ALPHA通道不是用于镂空,而是用于渲染ALPHA混合。那你转为只占1位的ALPHA通道格式纹理是肯定不行的,你可以试试ARGB4444。而对于无ALPHA通道的图片,如果使用的是RGB888,可以尝试转为RGB565。另外,转换之后一定要由美术人员进行实际观察进行确定。如果转换后的图像有明显的失真,那就算了。
(2)拼图优化
还是先上图吧
首先是一堆小图:
这一堆小图共有20张,都是PNG格式的RGBA8888。其中有15张图大小是85x121,一张52x139,两张是52x200,还有两张是37x37。
下面是拼合后的PNG图,格式与小图一致。使用的是“红孩儿纹理打包器1.1版本”。
下载地址:http://download.****.net/detail/honghaier/4671677
此图大小为512x512,可以看到其仍然有很大一片空白可供继续拼合一些小图。
好吧,我们来对比一下它们所占的内存。
第二张图大小为512x512,所以创建RGBA8888格式纹理需要1M内存来存储像素数据。
前面那一堆小图呢?
15张图大小是85x121。我们知道OpenGL ES在生成纹理时大小会扩展成2的幂次方。那85x121图片所生成的实际纹理大小为128x128,一张128x128大小的RGBA8888格式纹理需要64K内存来存储像素数据。15x64K = 960K。
1张52x139,实际纹理大小为64x256 ,也需要64K
两张是52x200,实际纹理大小为 64x256,需要64K,两张需要128K
还有两张是37x37。实际纹理大小为64x64,两张需要32K
算一算吧,只是存储像素数据总共需要的内存大小为 1184K。还不包括产生的纹理其它信息所占用的内存量,而且我们的拼合图还有很大的空白可供更多的小图进行拼合占用。
这还会导致一个更明显的效率问题,因为在渲染中,使用散图意味着增加切换纹理的开销,如果图片很多,那么纹理的频繁切换会导致你的游戏FPS大大降低。而采用拼合图,你将只需要很少次设定使用纹理,就可以渲染出大量的图形,大大减少了切换纹理的开销。
(3)骨骼动画
也是刚知道Cocos2d-x2.0.3版本已经支持骨骼动画系统。Cocosbuilder2.1版本工具中也可以进行相应的骨骼动画编辑。这对于优化内存是一个很好的方案。
以前做人物动画我们常常使用每一帧画一幅图片的逐帧动画方式。使用骨骼动画可以大大降低图片帧的数量,它只需要很少的图量就可以达到几乎相同的动画效果。但需要做比较复杂的编辑工做,对每一个关健帧的骨骼点进行编辑。
骨骼动画的制做流程一般为:
1.通过设定基础的骨骼点并构建出骨架关系树。将人物按骨架树划分成各个身体部件。
2.按照划定的身体部件来制做人物或动物图片,当然一般是将整个人物或动物图片进行切图命名图块来取得。
3.将身体部件图块绑定到相应的骨骼上。
4.设定关键帧,编辑关键帧上所有骨骼的位置及缩放与旋转变化。
5.播放动画,使骨骼按照时间进行两个关键帧间的变化插值计算,使用插值后的结果来影响身体部件图块绘制时的顶点位置。
骨骼动画的算法关键是对于骨骼动画编辑器的掌握,希望大家多多研究使用。
可参看网友豆奶哥哥的博文:
http://www.cnblogs.com/lovegame/archive/2012/10/15/2722626.html
(4)批次处理
批次,即Batch,也是游戏引擎中一个重要的优化指标。它指的是一次渲染凋用。显而易见,渲染的次数越少则游戏的运行效率越高。
Cocos2d-x是明显懂得这个道理的,举个最明显的栗子。咱们之前讲过的“深入分析Cocos2d-x中的图字原理”中有一个类CCSpriteBatchNode,它就是为了降低渲染批次而创造的一个专门管理精灵的类。这么说吧,我们渲染一段话“你吃了么?”,这里面有五个字,所以要创建五个CCSprite来对应这五个这的图块绘制,但绘制时我们如果一个一个的绘制,那是很恐怖的一件事,你的游戏写的字如果很多,你就可以放弃干其它的事情了,因为渲染调用次数太多而导致效率低下。为了提高渲染效率,专门的类CCSpriteBatchNode就出现了!他在一次渲染中把这所有的CCSprite都绘制了出来。所以,我想说,如果你要提高你的渲染效率,好好分析分析怎么使用CCSpriteBatchNode,将你的游戏中的大量图片精灵尽可能的放在CCSpriteBatchNode中来渲染,一定可以提高FPS的。
Cocos2d-x 2.0之后在左下角加入了渲染批次统计,呵呵,好像借鉴了OGRE的统计方式,为什么要统计渲染批次呢?就是为了让我们在进行优化时有个可以观察的指标。如图所示:
(5)使用压缩纹理
IOS设备用的是PowerVR显示芯片,而PVR格式可以被该显示芯片直接读取,在之前的博文里有分析过PVR格式纹理的源码,大家可以从中了解到PVR格式所支持的多种压缩格式。我们在开发IOS游戏时,也应该尽量使用合适的压缩格式的图片。如“pvr.ccz”。
这部分有个性能小测试,有兴趣的可以参见:
http://blog.sina.com.cn/s/blog_6fbe210701015j7z.html
经过上面的一些优化策略,应该已经可以大大的降低内存使用,并提高渲染效率。如果大家还有什么更好的方案,也欢迎大家随时提出来。下课~