ios和android游戏纹理优化和内存优化

news/2024/10/30 23:17:59/

1、2d游戏最占内存的无疑是图片资源。


2、cocos2d-x不同平台读取纹理的机制不同。ios下面使用CGImage,android和windows下是直接调用png库。我测试了下,使用png库直接读取png会比CGImage还要节约1mb左右内存(图片所占内存4mb)但是速度要比CGImage慢一倍。时间和空间如何取舍就看实际情况了。不过最佳的选择似乎是pvr(即使android版本,即使不使用pvrtc4)。


3、一般来说,我们可以直接使用  w * h * bpp得到一张纹理所占的内存,比如一张1024*1024格式为argb8888,那么他所占的内存就是1024*1024*4=4mb。之前看到有博客提到jpg会开辟3倍与此的内存(先转换为png,然后解析png),但是新的ios系统似乎没有这个问题。jpg与png所消耗的内存几乎相同,并且jpg解析速度更快(几乎都是4mb解析+4mb纹理数据,而jpg解析时间是png的一半),但是这样反而很怪异,因为jpg是没有透明色的,一个像素最多3字节,而png一个像素4字节,jpg纹理应该占用内存更小才对,后来看了下cocos2d的ios加载图片的代码,它把所有纹理转换成rgba8888格式,所以无论是jpg还是png,占用的都是4字节。正因cocos2d对其他纹理支持不够好,pvr才会显得那么高效。


4、pvr格式可以被显卡所认可,而不需要开辟临时内存来读取,所以即便同为argb8888格式的图片,pvr也会比png有效率,虽然不会节约程序稳定运行时的内存,但是会避免加载大量图片时的内存暴涨。  并且如果是ios设备的话,可以使用pvrtc4格式的图片,这个格式相当于windows下的dds图片,是可以被显卡直接支持的。它是有损压缩,一个像素只占4位,不过如果不是有渐变半透明色的话,一般效果可以接受,而其节约的内存和cpu时间非常非常显著。


5、pvr也不是万金油。android设备下虽然可以使用pvr格式,但是不能使用pvrtc4,希望通过pvr像ios设备上一样真正减少游戏内存是不太可行的。


6、pvr.ccz其实就是pvr图片zip打包下,程序读的时候还是先解压出pvr资源,然后再读取pvr。不过由于压缩下可以极大的减小图片体积,所以虽然多了解压过程也不会有特别多的cpu消耗。


7、一张jpg图片实际加载过程内存消耗,以一张1024*1024 argb8888 500k的jpg图片为例: a.读取图片文件(消耗图片大小内存,500k)     b、解析jpg数据(cgimage, 4mb) c、释放500k的图片内存    d、opengl纹理数据(4mb)    e、释放cgimage的4mb内存。      注意,这个过程不是必然的顺序执行,释放cgimage内存的实际是有系统决定的,会很快,但是不一定是立即执行。  所以内存会瞬间飙升9mb左右,然后减少5mb,稳定到4mb左右


       png图片的加载过程与此相同


       pvr图片可以节约解析图片数据到纹理这一步的消耗。也就是说读取pvr图片资源(等价于解压pvr.ccz到内存,如果是1024*1024 argb8888格式的话,那么图片大小就是4mb,ccz压缩后图片1mb左右)消耗4mb,将pvr图片数据提交给显卡消耗4mb。然后释放文件数据4mb。这么看似乎跟Png从内存占用上相比也不是非常有优势。(注意这里说的pvr是指pvr封装的argb8888,与pvrtc4的性能有天壤之别)


8、由于最终消耗内存的都是纹理数据,所以只要纹理数据格式是一定的,无论图片是什么格式消耗的内存都是一样的。比如使用Png8图片,体积会减少70%,但是内存占用与png24/png32是等价的(读取的时候会内部把调色板还原成真彩色,也就是说,虽然png8是一个像素只占8位,但是读取到内存中的时候会将调色板颜色还原,依然需要开辟1024*1024*4字节的空间存放纹理数据)。 当然有无透明色,cocos2d的处理还是有区别的。如果是无透明色,可以使用png24,那么所需开辟的纹理空间就是3mb。


       这里还有一点需要说明,一般我们处理windows下的dds纹理的时候,都习惯将其按2的整次幂对其,虽然图片内容只有900*900,但是图片大小却是1024*1024。那我们读取这个图片所消耗的内存就是4mb,按2的整次幂对其是有助于提高运行效率的,但是不是非常必须的。ios和android的设备都支持非2的整次幂的纹理。所以如果是png图片,那么它该多大就多大。此时消耗的内存就只有900*900*4=3mb。


9、不要过于迷信所谓的去除alpha通道以节约内存。这个还要实际分析下具体结果。  我测试过(分别用cocos2d-x和鬼火3d引擎),rgba8888和rgb888格式的png图片显示所消耗的内存是一样的。24位图片虽然读取的时候开辟的内存只有3mb(1024*1024*3,注意如果是用CGImage读取的话,那这个值就是4mb),但是glTexImage2D提交给显卡后依然会增加4mb内存。可能跟显卡的数据对齐有关。


     这里我测试还有一个诡异的地方,如果是用pvr的npot图片的话,rgb888要比rgba8888所消耗的内存要小,但是pot图片两者又是一样的(png图片两种情况都是一样的)。可能是powervr显卡有特殊处理。


10、rgb565和rgb5551的图片所消耗的内存是rgba8888的一半,如果没有透明渐变的话,视觉上也看不出什么区别。一些大的背景图可以优先选择这种格式。


11、pvr图片加载速度要比png和jpg快3~5倍(同样1024*1024 argb8888),png消耗的时间可能是700ms左右,但是pvr只需要100ms左右。如果是pvr.ccz压缩下,消耗的时间是200ms左右。可见pvr在加载速度上还是有非常大的优势的。这个应该是因为png和jpg需要把图片数据还原为rgba,但是pvr可以直接把图片数据传递给显卡。pvrtc4的图片是可以被powervr显卡直接支持的。






总结下:


1、最终决定图片占用内存的是它的像素格式和大小,与其扩展名无关。png8  png32 jpg pvr只要其像素格式都是argb8888,那么最终图片占用的内存是一样的。


2、如果不是pvrtc4的格式,那么不要扩展成2的整次幂,因为图片越小,占用内存越小


3、单单去除透明通道不会减少图片所消耗的内存,png和jpg图片也无法减少图片体积,所以不推荐rgb888的格式。替代选择rgb565和rgb5551。


5、小心加载图片时临时开辟的纹理数据造成的内存飙高,可以考虑加入内存池,及时的开辟和释放缓冲区。


6、如果是为了减少图片体积可以选择:1、jpg--压缩比最高,质量较好,但是不支持半透明    2、png8--同样图片会比jpg略大一些,使用ImageAlpha进行转换,视觉上几乎看不出差别。    这两种图片格式都可以极大的减少图片体积(减少70%~80%),但是无助于减少内存


7、如果是为了减少内存可以选择:1、没有透明色的图片统一转换为rgb565格式,这个时候无法使用png8了,所以png和pvr.ccz图片大小几乎相同,pvr.ccz速度更快,所以推荐pvr.ccz的rgb565格式    2、如果透明色仅仅是进行关键色标注,而没有渐变混合,那么推荐rgb5551 (r5_a1)的pvr.ccz格式


8、可以考虑写个打包系统,统一把资源文件打包,而不是单个文件用pvr.ccz进行zip压缩,这样可以获得更高的效率。(比如我封装了下暴雪的mpq打包,其读取速度与本地文件读取速度相当,这样就可以获得最佳的读取效率)






使用NPOT纹理
NOPT是“non power of two”的缩写,译作“不是2的幂”。NPOT stands for “non power of two”. 在cocos2d1.x的时候,你必须在ccConfig.h文件中开启对NPOT的支持,但是,cocos2d 2.x就不需要了,它默认是支持NPOT的。所有3代(iphone 3GS)以后的ios设置都支持cocos2d 2.x(因为它们支持OpenGL ES2.0),所以也都能支持NPOT纹理。
如果纹理图集(texture atlas)使用NPOT的纹理,它将有一个具大的优势:它允许TP更好地压缩纹理。因此,我们会更少地浪费纹理图集的空白区域。而且,这样的纹理在加载 的时候,会少使用1%到49%左右的内存。而且你可以使用TP强制生成NPOT的纹理。(你只需要勾选“allow free size”即可)
为什么要关心NPOT呢?因为苹果的OpenGL驱动有一个bug,导致如果使用POT的纹理,则会产生额外33%的内存消耗。


http://kobenini.blog.163.com/blog/static/200571197201343010311616/

破解版的下载地址:http://115.com/file/be822cr1#nbwCzTApB7S0yN8r


1. 使用脚本生成图片,如果有白边的情况,需要加 --premultiply-alpha 语句。
2. RBGA4444格式,改变抖动选项为“FloydSteinberg+Alpha”。Texture Packer将会在动态修改你的图片,而且马上显示出效果来。
3. 如何使用脚步自动生成图片:http://www.cnblogs.com/andyque/archive/2011/05/15/2045784.html
4. 优化:http://www.cnblogs.com/andyque/archive/2011/03/18/1988097.html
优化背景图片:把图片格式改成RBG565(对于大的图片来说,你可能需要更好的质量),然后改变抖动方法为“FloydSteinberg”(为什么不是FloydSteinberg+Alpha呢?因为像素格式是RBG565,没有了Alpha通道)
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565];



PS:顺便说一下如何处理独立的ALPHA通道
【CocoaChina论坛招募版主,期待您的加入】
pvrtc 和 etc是硬件支持的格式,因此,不会进行内存和显存解码,将会省许多
同时,由于不会解码,那CPU到GPU的传输量就会变少,在手机平台这种总线带宽小的设备上,可以得到一定量的性能提升。


但pvrtc只适合IOS,etc适合android, 需要做两个平台的分别优化,并且etc1(刚刚有修改,先前是说的etc,随着OPENGL ES 3.0的发布,etc2也出了,支持ALPHA通道,但就目前的市场,可以不用考虑)不支持ALPHA通道,所以需要解决一些问题。


png24/32是无压缩格式的RGBA通道,质量是最好的
JPG是有损压缩的格式,不支持ALPHA通道,但是是安装包最小的。


但JPG会进行内存解压,也就是说,一个JPG读入到内存后,与png24/32读入内存是一样的。


综上可知。
prvtc,etc不仅可以减少安装包大小,也能减少内存显存开销,并能提升一定的性能
png24/32可以保证原始质量,但内存和安装包大小 会很大
jpg不能省内存显存,但jpg可以使安装包较小,且它不支持ALPHA通道。


而对于pvrtc,etc打出来的文件大小,比jpg要大得多。


在此,我们还可能会用到一种叫 grunt - png8的压缩格式,这种格式可以将png24/32压缩到1/4的大小,且几乎可以维持图像质量需求,这个比JPG大,但支持ALPHA通道。




那选择策略就需要针对不同的资源进行优化了


1、如果游戏是那种大量关卡资源,但同关卡中出现的资源和元素较少,这种一般不会有内存和性能瓶颈,那可以选择JPG+grunt-PNG8,这样一来,可以将安装包大小减少到1/4左右
2、如果游戏是那种同屏复杂度较大的,那就需要对游戏中的元素分类处理了, 一般对于UI,直接使用png8即可, 对于单张场景,我们使用JPG,对于里面的小元素,比如特效,人物精灵动画等,则建议使用pvrtc或者etc格式。


纹理格式的选择不是死的,只要你明白了不同格式的优缺点,那就可以很容易地做出判断。。








在这里,顺便说一下,如何处理独立的ALPHA通道。
首先,美术出图还是用原始PNG。 我们可以用PYTHON的IMAGE库,将RGB和ALPHA分离出来。RGB可以用原图,而分离出来的ALPHA通道,使用8位的PNG来存放,注意,这里和上面说的PNG8是有区别的。东西不一样。
这样我们就有两张纹理图,color + alpha_mask 现在我们开始进行纹理转换,我们肯定是要将color图转换为pvrtc或者etc1的,而对于alpha_mask,就看你爱好 了,可以转,可以不转。

这里还有另一种处理方法,就是将ALPHA纹理拼接到原来的纹理上,这样我们的纹理就只有一张,涉及的资源加载的改动就较少。 这个大家自行考虑





有了这个,我们要处理的,就是SHADER和纹理的ALPHA MASK问题,首先我们在纹理加载处,要进行纹理判定。
对于分享的ALPHA MASK,我们有两种方法处理, 一种是统一命名, 比如 ooxx.png 打包为etc后,变成  ooxx.png(etc1格式,只是后缀保持原来的) + ooxx.png.alpha_mask(这个格式根据自己爱好,可以直接是8位PNG图) 这样一来,我们在加载ooxx.png的时候,无脑判定一下ooxx.png.alpha_mask是否存在,如果存在,就加载这个纹理,并存放于CCTexture2D里面,同时提供一个getAlphaMask来访问。




SHADER肯定是要改的,不管用哪种方法,SHADER都得改,对于上面这种,正常情况下的SHADER是
vec4 c = tex2d(tex,uv)
那我们要改成




vec4 c = tex2d(tex,uv)
c.w = tex2d(alpha_tex,uv).w
就可以了。




而在SPRITE等提交纹理的地方,我们通过判定getAlphaMask来确定是否要切换SHADER,并且设置这个alphaMask参数。








说到这里,可能许多朋友会问,我在代码里使用 display.newSprite("ooxx.png") 但是我的ooxx.png打包后,是ooxx.pkm怎么办。
这就是为什么我上面要把ooxx.pkm的名字换回ooxx.png的原因,这样一来,逻辑代码就不用动了。




而随之而来的,就是2.2.x版本中,加载纹理的时候, 是使用后缀名判定。
这个太好办了,把3.x版本中,通过文件头判定纹理格式的代码弄进来,即可实现后缀 名无关的纹理格式判定。




PPS:有了后缀名无关的纹理格式判定,我们会想,每次都检查 纹理.alpha_mask是否存在,会不会影响效率, 答案是肯定的,要多一次磁盘路径查找。 如果你觉得这点效率是心结,那你完全可以将ooxx.png和ooxx.png.alpha_mask使用工具(如PYTHON)写成一个文件,依然叫ooxx.png,但我们强加一个头,比如 'T','E''X','P' 如果发现头四字节(由于大小端问题,记得逐BYTE读取)是TEXP,我们认为这是我们的原图+ALPHA_MASK的纹理包,然后根据自己的格式读取出数据即可,后面的步骤,就和上面的一样了。




上面只是一些经验上的描述,实际实现过程中其实还是会遇上许多特别的问题。 大家共勉。


http://www.cocoachina.com/bbs/read.php?tid=214811&page=1


在游戏项目优化中都会碰到一个问题,如何既能减少内存又能尽量减少包的大小?在实际项目中有些经验分享一下,事实上2D游戏中最占内存的就是图片资源,一张图片使用不同的纹理格式带来的性能差异巨大,下表是我在IOS平台一个小Demo中的测试结果,该Demo的原始内存占用是7M,测试方法是一次性加载5张2048*2048的图片,使用TexturePacker工具生成图片,内存统计使用Instrument工具,加载时间统计用-X引擎提供的CCTime类,单位是微秒。


图片格式               加载时间   内存占用 备注
png                         782080     88M         5张 2048*2048 的PNG
pvr.ccz(POT)      394769       102M        5张 2048*2048 的pvr.ccz(POT:2的整次方)
pvr.ccz(NPOT)   338099      85M          5张 2047*1680 的pvr.ccz(NPOT:非2的整次方,即图的实际大小)
pvr(PVRTC4)     8875            33M          5张 2048*2048 的pvr(PVRTC4:压缩比率为8:1的有损压缩,实际测试发现画质基本没有损失)


结论:
1)比较加载速度:原始PNG是最慢的,使用POT的pvr.ccz大约是原始PNG的50%,使用NPOT的pvr.ccz大约是原始PNG的43%,使用pvr则只要原始PNG的1%;
2)比较内存占用:使用POT的pvr.ccz大约是原始PNG的1.2倍,使用NPOT的pvr.ccz和原始PNG差不多,使用pvr只要原始PNG的40%;


从中可以看到,对于尺寸大的图片,选择纹理格式时,最优先使用的是PVR,其次是NPOT的pvr.ccz,考虑到多平台支持,综合起来,对图片资源的管理方案可以如下(以下所说图片尺寸以iPad高清为标准):
1)对于1024*1024及以下的小图片,还是使用PNG,因为简单,所有平台都能用;
2)对于1024*1024以上的图片,首选用pvr,它能直接载入到IOS设备的显存里,无需经过内存解析,所以快;但是,遗憾1:安卓设备不支持;遗憾2:TP工具不支持生成2048*2048以上的pvr;
3)如2所述,对于2048*2048以上的图片,及安卓设备,则使用NPOT的pvr.ccz,在Cocos2d-x 2.x引擎里默认已经支持,所有3代(iphone 3GS)以后的ios设置都支持cocos2d 2.x(因为它们支持OpenGL ES2.0),所以也都能支持NPOT纹理;
4)经过测试,安卓设备也支持NPOT,所以方案比较简单,1024*1024及以下的用PNG,1024*1024以上的使用NPOT选项的pvr.ccz;


采用以上方案后,游戏所占内存从90多M降到了60多M,在IOS各种设备跑过了,touch3、touch4、iPad1等低端设备都没问题。

 Zwoptex生成的spritesheet除了可以导出png格式的图片外还有pvr格式。pvr格式是iOS的显示芯片可以直接读取的,不需要经过解析就能直接显示,所以渲染速度更快,更节省内存。

我特意在cocos2D 2.0 rc1版本做了一项测试:
    一个空的cocos2D模版工程运行起来之后占用的内存大约是4MB。
    直接用CCSprite显示一张2048*1024的数据格式为RGBA565的PNG图片之后,内存占用达到了20MB。
    同样的情况下换成pvr格式之后,内存占用为16MB。也就是说png格式的图片占用了20-4=16MB,pvr格式的图片占用了16-4=12MB。节省了25%。

    Zwoptex还有一个选项叫做“ccz压缩”,选中之后图像的大小几乎可以减小一半。这样的文件格式成了:xxx.pvr.ccz,cocos2d是可以识别的。

     PVRTC2 PVRTC4 是两种pvr压缩的图像格式,他们都是pvr文件。这两种图像格式比普通图像有更快的加载速度和更小的内存占用。
PVRTC4: Compressed format, 4 bits per pixel, ok image quality
PVRTC2: Compressed format, 2 bits per pixel, poor image quality
一般pvr格式文件的图像格式有:
RGBA8888: 32-bit texture with alpha channel, best image quality
RGBA4444: 16-bit texture with alpha channel, good image quality
RGB565: 16-bit texture without alpha channel, good image quality but no alpha (transparency)
图像占用内存的公式是: numBytes = width * height * bitsPerPixel / 8
也就是说2048*2048的RGBA8888占用内存16MB,而PVRTC4只占用2MB


http://www.ppmy.cn/news/815403.html

相关文章

iOS 平台游戏如何对接 GameCenter

现在随着手游市场的不断扩大,活跃在IOS平台下的游戏厂商为了增加玩家的粘性,以及为自己的游戏前途考虑都纷纷开始接入苹果国内公司的游戏平台GameCenter;今天呢我就把我对接GameCenter的一些心得以及操作分享给大家,内容很简单也希望在这方面…

ios模拟器装ipa包_ios模拟器怎么安装游戏应用教程

iOS模拟器是苹果Xcode IDE的一部分,主要用来为Mac,iPhone和iPad创建应用程序,为了给iOS模拟器打包应用程序,利用–package 在命令行上执行ADT并使用–target来指定其中一个目标。 比如,对于检测注释目标你可以执行下面…

在ios上运行安卓计算机软件,安卓竟然也能运行iOS,苹果怒了!

iPhone最大的优势是什么? 答案肯定是iOS。 很多人离不开iPhone, 就是因为其丝滑般的系统,强大的生态。 但是,如果这种优势不复存在呢? 也许你会说,怎么可能? 目前的安卓还比不了iOS。 这话说的没…

如何在Mac上玩安卓手游(支持各大安卓手机游戏数据同步)

很多小伙伴由于手机的型号不同,各大厂商的游戏端不同,导致在助手上下载的游戏不支持自己原来手机的里游戏资料。下面跟随小编来帮助你解决这个烦恼 首先我们需要借助腾讯手游助手 for mac版 腾讯手游助手 mac版是一款可以让用户在mac电脑上玩手机游戏的软件,腾讯手游助手m…

自锁电路分析与应用

原理图分享 今天工作中遇到一个设计很妙的电路,请教了一下硬件的工程师。 大家自己直接看图可以分享出这个电路的作用吗,可以在评论区告诉我哦! 自锁电路 如上图就是一个自锁电路,和下面的电路一样: 电路现象描述&a…

map和set介绍及使用

目录 一、什么是关联式容器 二、set 1.set的介绍 2.set的使用方法 三、mutiset 四、map 1.map简介 2.map的使用 五、multimap 一、什么是关联式容器 在了解map、set之前,你肯定已经使用过vector、list、deque、forward_list(C11)等这些容器,而他…

小规模企业如何做账 e-mail_小规模公司自学做账方法

小规模公司成立之后半个月之内就要开始做好当月的账目信息、用于当月的财务申报工作。最常见的方法是聘请代账公司帮忙记账。由于现在创业的热潮比较高、对于创业注册公司的要求越来越低、新公司的注册量非常的多,又由于新公司的成立后经营不好、出现倒闭的也多。甚…

电脑上的记账本,添加无限个账户记录

账本告诉你钱去哪里?收入支出的一些零钱,一日三餐,看上去好像很固定,但是生活中总有很种的不同收支需要记录,如何选择一个可添加多个账户来记录不同的地方的使用收支呢?下面一起来看晨曦记账本如何添加多个…