一个操作让游戏内存立减50+%-Creator性能优化之压缩纹理

1 什么是压缩纹理

在游戏中,纹理不仅占据大量的包体,也占据了大量的内存。传统的图片压缩格式(如JPEG、PNG等)虽能减少资源大小,但是不能被GPU直接识别,还是需要先加载到内存通过CPU解码,转换成RGB/RGBA等能被GPU识别的格式,才能传送到GPU进行渲染。

为避免这些问题,压缩纹理,指的是一种针对GPU的纹理压缩方案,使纹理能够直接被GPU识别并进行渲染,它具有以下优点。

  • 无需CPU解码,节省了CPU运算,减少耗电量。
  • 纹理直接被传送到GPU,避免了内存占用,提高渲染性能。
  • 高效的压缩算法,减少了包体大小。

2 压缩纹理的原理

传统的图片压缩主要目的是存储和传输,为了尽可能的高效压缩,使用了可变的压缩比率,因此在解压时需要解压更多的像素位才能读取某个像素的位置,不适合随机和快速读取,也发挥不了GPU的并行处理优势。

而压缩纹理使用一个固定的压缩比率,将纹理划分成多个像素块,每个像素块包含2*24*4个像素,然后对每个像素块进行压缩,被压缩的像素信息存储在一个像素集合中,每个像素块的索引位置存储在一个块索引图中。读取时,首先将纹理坐标转化为块索引值,然后在像素集合中查找对应的像素块,最后在这个像素块中找到纹理颜色值。

因为采用了固定的压缩比率,GPU内部可以并行处理,从而快速的解压缩。与之相对的是,纹理的压缩过程发生在程序运行之前,并不在意编码速度,因此在压缩时会遍历所有可能性,找到和原始像素差值最小的编码,这也是纹理压缩耗时较久的原因。

顺便说一下,普通图片格式中,PNG是无损压缩,JPEG是有损压缩。而压缩纹理都是有损压缩,只是在绝大部分情况下,手机上看不出来而已。

3 常用的压缩纹理格式

手机上使用压缩纹理依赖于OpenGL ES的支持,OpenGL ES 2.0本身并没有定义任何纹理压缩格式,它仅提供 glCompressTexImage2D() 方法供应用程序上传压缩纹理,压缩纹理的格式由各个GPU厂商定义和实现。

OpenGL ES 3.0提供了压缩纹理标准,使各个平台都可以使用同一种压缩纹理,但市面上的设备还需要很长时间才会全部过渡到OpenGL ES 3.0。因此,仍然需要对不同的平台和设备使用不同的压缩纹理格式。

手机游戏中常用的有以下格式。

3.1 ETC1

ETC1把4*4的像素块压缩成固定的64位编码(8个字节),4*4像素块是16个像素,每个像素4字节,一共占64个字节,所以压缩比是 64/8=8。但是ETC1只能存储RGB信息,不适用带透明度的纹理,为解决这个问题,Creator在ETC1文件中额外写入了透明度信息,即ETC1+A格式,它的压缩比是 64/16=4。
ETC1/ETC1+A需要OpenGL ES 2.0(对应WebGL 1.0)环境,目前几乎所有Android手机都支持ETC1,但是iOS不支持。
ETC1/ETC1+A纹理的长宽可以不相等,但要求是2的幂次方。

3.2 ETC2

ETC2是ETC1的扩展,压缩比率一样,但压缩质量更高,而且支持透明通道,能完整存储RGBA信息。
ETC2需要OpenGL ES 3.0(对应WebGL 2.0)环境,目前还有不少低端Android手机不兼容,iOS方面从 iPhone5S 开始都支持OpenGL ES 3.0。
ETC2和ETC1一样,长宽可以不相等,但要求是2的幂次方。

3.3 PVRTC

Creator中常用的是PVRTC4+A,压缩比和ETC一样,iOS全系列支持,但是Android不支持。另外PVR要求纹理长宽相等(正方形)且是2的幂次方,例如1280*720的PNG图片,转换后变成2048*2048,这一点会大大增加内存消耗。在实测中还发现转换后的图片质量不如ETC1,存在模糊、毛边现象,对画面要求高的游戏不适合。

4 压缩纹理的使用

压缩纹理的使用非常简单,根据构建平台添加需要的格式即可,具体参见Creator官方文档,本文不再重复。

Creator编辑器还提供了转换压缩纹理的选项,根据转换速度分为Fast、Slow等好几档,速度越慢则画面质量越好。但不管选哪个,只影响显示效果和转换时长,显存占用都是一样的。一般情况下,显存占用就是压缩纹理的文件大小,例如文件大小是1.5M,则它占用的显存也是1.5M。

在设置压缩纹理格式时,目前Creator 2.x版本还需手动一个一个设置。如果想一次性设置所有或部分资源,记得有大佬提供过插件,当然自己写个脚本遍历修改对应的.meta文件也比较方便,这里是一个我写好的脚本 一键自动化设置压缩纹理格式

5 总结

在实际项目中的测试结果是,单图、自动图集、TexturePack合图加起来超过两千张图片的Creator工程,使用PNG时打出来的apk包大小近500M,内存占用1.3G。采用压缩纹理后,包体大小降到150M,内存占用降到600M。

  • 压缩纹理的初始文件大小比PNG大1-2倍,但经过zip或打包成apk、ipa后,大小比PNG小了1/2-1/3,对减小包体有巨大好处。
  • 从OpenGL ES 2.0开始,GPU纹理支持非2幂次方(例如,小于2048的图片比2048图片更节省内存),目前所有手机都已经是OpenGL ES 2.0及以上了。
  • 对于Android原生平台,要想兼容尽可能多的设备,又想发挥内存和包体优势,目前最佳选择是ETC1。
  • 对于iOS原生平台,PVR画面质量不佳,如果只考虑 iPhone5S 及以上设备,则使用ETC2比PVR好。
  • OpenGL ES 3.0开始新推出一种ASTC格式,Android和iOS都支持,画面质量比PVR好,且不要求纹理长宽相等和2的幂次方。ASTC可能会是未来的统一格式,但目前很多Android低端设备还不支持。
32赞

压缩纹理是好东西,不过android ios 要分别做热更新,这。。。。就怕到时手忙脚乱
看了你的帖子让我又又又想试一次看看具体提升,但一看千儿八百的png要一张张的改导出,算啦先。。

写个js脚本,一键搞定。

这就是为什么你是star writer啊,刚才就看你是star writer羡慕不已,真心的。
自从一个人做手游,过年期间每天都写代码十个小时以上,我给自己买了全套保险生怕自己猝死,做什么都是实现功能,而不去深究,时间也不允许,一个手游要做的事太多了,还请不吝赐教给说说有什么快捷的办法没有

你的头像有点意思 张保长?

一直没看到过类似文章,多谢普及。。。。

一个人做?美术资源也自己处理嘛?大。。。大佬。。。

用引擎自带的打包自动转,慢的要命。。。

2.4开始会缓存纹理了

一个人做手游,我也真心的佩服你,无以为敬,特意写了个自动化设置压缩纹理格式的脚本,需要的话试试吧。

一键自动化设置压缩纹理格式

1赞

感谢万分:pray: 给跪了

贾贵,百度有惊喜,个人很喜欢的演员

从策划到作图,前端和后台,也得益于以前是做C++和JAVA的,所以还能勉强写懂。如果不是cocos3.0不支持js(有人说ts里能写js,这…)blender也自学了一阵,后来不得不放弃,时间上不允许就暂时作罢了。
也不是我真的想自己来做,手游成本高,前期也出不起钱来招人,加上国内你也知道的,有关部门要求独立开发者都做圣人。
说点个人的感受,在公司,人员沟通成本也是挺高的,从业这些年,最高做到技术总监,感觉初期一个人效率上应该是最高的。缺点也很明显,全险一定要买上,万一嗝屁了,还能留下一笔给老婆孩子。

2赞

大佬真的牛逼!

话说现在的市场环境,没有运营和推广,手游上线后也没几个用户啊。

个人做微信或头条小游戏是不是轻松一些?不用操心这么多硬件或设备适配的事情,生态够大,分享和传播也方便。

一键修改真的好棒,slow build的有些慢,十分钟了还没动静…haha

确实是这样的,刚做出的时候哭爹喊娘的求玩家来玩,想想那时候就很心酸,也正是做游戏的这些时间,让我对人对事有了更成熟的看法,或者说成长。
手游的优化是最累的,再加上还要当客服,整天被玩家骂,也不清楚为什么国内玩家那么容易气愤,我已经习以为常了,就算骂飞了,我依然笑脸相迎,再或者装死不说话。
最开始我所有的游戏元素都是自己做的,并且想依靠微信小游戏的风口,ps做UI,做个地图背景就要一两周,3dmax 3转2,这也是为什么当时用了cocos(1.93的时候,cocos源生的表现算不上多好),服务器架构也搞得很讲究,分布式外加消息队列,弄的花样十足,但没人玩啊,小游戏刚开通的时候给了一千个人的量,留存估计十个都没有。
当时做就做了两年吧,小游戏风口也过去了,真正击垮我的,是小游戏要求游戏不能是角色扮演,角色扮演就不能更新,我做的明显是策略游戏,手游不能更新就直接宣告死刑。为了能更新,期间给小游戏审核发红包,求他们,哭爹喊娘,还是没能通过,何止一个惨,死的心都有(拿铅笔把生命线划断),于是我就把这些玩家全部都转到了APP,开始了源生的路子。
后来呢我就用那些倒闭了的游戏的素材,就是一些序列帧和UI,而这些倒闭游戏的玩家就成了我的第一笔资源,我把之前的玩法全推翻,全部改成了倒闭游戏的玩法,也好在和这个倒闭游戏的差别不是太大,花了半年的功夫改了。
就这样,我顶着这帮玩家的谩骂,说我是私服,说我是侵权(也确实有这个成分),我那时候也有些气愤,我是走投无路复活了一个手游,总不该这样被骂吧,还是说我做的太像了,咱行内知道:UI只是游戏的一部分,或者说小部分,策划、开发等等太多了,与其说是复活,不如说又重新开发了这个倒闭的游戏。但我不敢声张啊,毕竟用了人家的东西。与其这几年心血白费,顶着侵权的名声,侵就侵了吧。
后来这帮玩家我积攒下来了,我就开始推出自己的东西,评价有好的有坏的,慢慢改进吧,我很重视这些玩家,这都是来之不易的宝贝玩家。
作为80后的网瘾少年,我觉得只要坚持,我应该是能做出一款好的游戏。
半个小时了,构建还卡住不动,slow果然是slow。。。

6赞

兄弟写了这么多字,我太困看不过来了,明天再细看吧。

临睡前告诉你一句实话,用slow压缩,估计你的工程得超过30个小时才能压缩完,今晚别等了~~

效果拔群,内存从1.1G降到了590MB左右(同场景)

看得我挺心酸啊,一个人坚持这么久真不容易,挺佩服你的。
有玩家群吗?我想观摩学习下。

额,全套保险啊。
苟命要紧
留得青山在,哪怕没柴烧?

大佬6p霍冰阔落。。。
我没胆这么走,只能是计划在空闲的时候做个小东西,争取上线,不在乎收入,纯当圆当年入坑的梦吧,过年的时候写了几个晚上,目前进度才10%左右,唉。。。而且还没图,到时准备去爱给网上看能不能弄点素材音效什么的用用。现在全是用的Graphics组件自己话的简单图形,难受得一批,dc飞起