干货分享:Creator使用压缩纹理

概述

之前写过一个关于2DMMO优化的分享,有些人问到其中的压缩纹理要怎么做。其实实施起来很简单,很多看过cocos2dx的人都知道怎么做,这篇分享主要针对对这块不是太了解的新同学。

我假定对这篇分享有兴趣的同学都知道压缩纹理是什么,有什么好处和坏处。如果不大了解,可以先看一下pvr, etc相关的知识。

在手游中使用压缩纹理是很常见的需求,通常:

  • IOS会使用PVR来压缩,IOS要求图片高宽必须是2的幂,且必须是正方形。
  • Android会使用ETC1,由于ETC1不能支持透明通道,对于有透明的图,一般也会用ETC1+Alpha的做法。

使用工具

生成压缩纹理当然是使用现成的工具了:

IOS

使用PVRTexTool,在这里下载,具体的使用方法可能要参考工具的文档,下面是一个简单的例子:

PVRTexToolCLI -i $(infile) -o $(outfile) -square + -pot + -q pvrtcbest -f PVRTC1_4,UBN,lRGB

其中$(infile)$(outfile)分别是原图片名和压缩后的图片名,如果图片没有透明,PVRTC1_4换成PVRTC1_4_RGB

Android

使用Mali Texture Compression Tool,在这里下载,这个工具可以生成ETC1和带透明通道的ETC1

# 原始格式
etcpack ${infile} ${outfile} -c etc1
# 带透明通道
etcpack ${infile} ${outfile} -c etc1 -aa

带透明通道的ETC1其实就是将图片和遮罩合成一张图,最终的图片高度是原始图片的2倍。而要正确显示图片,则需要用Shader把遮罩部分作为Alpha值加到原图上。Shader如下所示:

attribute vec4 a_position; 
attribute vec2 a_texCoord; 
attribute vec4 a_color;  
varying vec4 v_fragmentColor; 
varying vec2 v_texCoord; 
varying vec2 v_alphaCoord;
void main() 
{ 
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color; 
    v_texCoord = a_texCoord; 
}


precision lowp float;
varying vec4 v_fragmentColor; 
varying vec2 v_texCoord; 
varying vec2 v_alphaCoord;
void main() 
{ 
    vec4 v4Colour = texture2D(CC_Texture0, v_texCoord);
    v4Colour.a = texture2D(CC_Texture0, vec2(0.0, 0.5) + v_texCoord).r;
    gl_FragColor = v_fragmentColor * v4Colour; 
}

兼容Web和Native

现在知道如何生成和使用压缩纹理了,要怎么整合进Creator呢?

  • 在开发阶段,我们还是正常使用png, jpg,这样在浏览器和模拟器都能正常显示。
  • 在构建阶段,分成三步走:
    • 用Creator命令行生成原生工程。
    • 调用我们自己的脚本,将工程中的图片转成压缩纹理,但要注意转换后的图片名不要变,比如a.jpg转换后仍然叫a.jpg,只不过内容已经是压缩纹理了
    • 用Creator命令行编译安装包。

这样打出来的包,在手机中是可以正常显示的,原因是cocos-2dx并不是以文件后缀来判断类型的,它是根据文件内容的头几个字节来判断的。

cocos-2dx其实还支持gzip压缩格式的,也就是我们将图片转换成pvretc1后,还可以再压缩成gzip,最终还是可以正常解析出来。但由于文件大小小了很多,加载速度会变快。

要完成这样的构建流程,你可能需要用一个脚本来实现自动化,我比较推荐python,它的库实在太强大和方便了。

另外,并不是所有的图片都适合用压缩纹理,比如UI图片压缩后会有明显的锯齿,像场景, 特效这类就比较适合。总之,在使用压缩纹理之前,你可能需要对图片类型进行一些规范化。

47赞

赞,沙发

赞,技术帖要顶

赞赞赞~

不是一般都用pvr.czz zlib吗 楼主有测试过gzip和zlib哪个更快吗

##顶一下

一样快,因为gzip用的算法和zlib是一样的,只是gzip加了一个文件头,表示这个文件有多大。

这样啊 是说我测试的时候gzip会大一丢丢 不过这样压缩后大小上仍然会比png8要大不少 内存占用和渲染速度倒是优化不少
还没想好如何取舍

请问有推荐的gzip压缩工具吗?

用Python

貌似使用etc1的时候, spine在导出图集的时候不能勾选alpha预乘, 否则就算etc1的shader不重复做预乘也会在半透的地方显示错误. 请问楼主有没有碰到类似的问题?

1赞

大赞,使用压缩纹理可以让安装包体积变小,还能减少内存占用,提高运行速度。
想请问一下,在android下具体如何使用ETC格式+Shader呢,能详细些吗?

关注~

这个要顶,找个时间整合进工作流:slightly_smiling:

nodejs不比python差,我的工具都是用nodejs实现,包括打包,压缩,自动合图。

gzip在测试中会比zlib要快一点,不知道是不是环境不一样,还有一点就是文件如果太大用压缩的话解压起来会卡线程,最明显的就是动画会卡住,不知道是不是我用的工具问题,实际测试中pvr压缩后的图片质量不是很好,颜色太多的会变得很难看,楼主没这个问题?

1赞

Python和NodeJS都可以的,只是我对Python比较熟 ,就用了,这个没什么的。
我们的动画控制在1024x1024大小,如果超出就用分多张。
IOS用ETC2,可以参考我另一个文章,比PVR好太多。代价就是只能在iphone5s以上的手机才可以。

http://forum.cocos.com/t/cocos-etc2/49061/14
看看这个

etc2确实挺好

三四年前es3刚出来就觉得etc2是好东西,可惜都这么多年了,还不怎么普及,搞得开发者用ect1,事多

其实安卓真机已经大部分支持了,最恶心的是所有模拟器只支持ES2。