移动设备的纹理压缩方案
一、纹理压缩的必要性
1、无须CPU解压即可被GPU读取,节省CPU时间和带宽。
2、节省大量内存,极限时可以减少16倍消耗。
3、部分压缩格式可以节省图片体积。
二、常用的压缩格式与其内存消耗
压缩格式 | 内存消耗 (bytes/pixel) |
iOS | |
RGB Compressed PVRTC 2 bits | 0.25 bpp |
RGBA Compressed PVRTC 2 bits | 0.25 bpp |
RGB Compressed PVRTC 4 bits | 0.5 bpp |
RGBA Compressed PVRTC 4 bits | 0.5 bpp |
Android | |
RGBA Compressed ATITC 8bits | 1 bpp |
RGBA Compressed S3TC(DXT1) 4bits | 0.5 bpp |
RGB Compressed ETC1 4 bits | 0.5 bpp |
RGBA Compressed ETC2 8 bits | 1 bpp |
RGB Compressed PVRTC 2 bits | 0.25 bpp |
三、业界常用的压缩方案
Android:
目前android上虽然支持ETC1,ETC2,ATITC,S3TC(DXTC),PVRTC这五种压缩格式,但是考虑到适配问题,业界一般选择ETC1,因为它是OpenGL ES图形标准的一部分,并且被所有使用opengl2.0的Android设备所支持。
由于ETC1不带alpha通道,因此遇到半透明的图时, 需要将原贴图的alpha抽离,一分为二并别压缩,最后在渲染时再合并计算。该种方式R、G、B、A的在压缩中的占位是相等的。
IOS:
IOS上支持的压缩纹理格式比较有限,通常使用pvrtc,pvr有2 bits和4 bits两种格式,由于2 bits在画质上的损失过于严重,所以业界一般使用pvrtc RGBA 4bits格式。
四、Phero项目的压缩方案
Android:
除了ETC1之外,唯一可用的格式是ETC2,根据官方的说明,ETC2是ETC1的超集合,可以向下兼容解码ETC1的纹理,并且支持RGB和RGBA两种格式,由于ETC1是4 * 2像素作为一个压缩单位,而ETC2是4 * 4像素作为一个压缩单位,因此品质更高,所以理论上ETC2可以成为ETC1的替代者。
于是笔者对其进行了测试。ETC2的兼容性因为测试机型比较有限,因此无法给出结论。在表现力方面,根据测试结果(数据详见第五部分,下同),ETC2的RGB4 bits格式跟ETC1的几乎无任何区别, RGBA 4bits的格式由于Alpha通道上的质量比较差,表现还不如ETC1,ETC2的8bits格式表现略优于ECT1,但是内存扩大一倍,性价比一般。因此Phero项目仍然采用稳妥的ETC1格式
另外,由于opengl1.0的android机器不支持ETC1压缩,因此在实际操作中,首先需要检查机器是否支持,根据结果下载是否压缩过的纹理,并且在代码中加以选择。
IOS:
PVRTC RGBA 4bits格式虽然带alpha通道,但是压缩时如下图所示,R和G占位最高,A占位最低,同时半透明的占位均比不透明的低,因此理论上半透明的图实际表现并不会太理想,测试中也验证了这点,一些贴图中出现了很明显的毛刺,一些贴图则出现了边缘轮廓线,因此质量难以达到要求。
因此提高质量的思路是提高alpha在压缩中的比重,于是我们采用PCRTC RGB 4bits方案。透明图片的处理方式与ECT1一致,即将一个图片生成两个纹理,一个是RGB,一个RGB中的r存储着图片的alpha数据。在绘制的时候使用纹理单元,将带有alpha数据的RGB做为另个带RGB纹理的alpha。
五、实际测试结果对比
Android的测试机型为华为P6,IOS的测试机型为iPhone 5s,给出了压缩前和各种格式压缩后的内存和表现数据,因为是屏幕截图所以不是特别清晰,请特别注意画红框部分。
格式 | 单图内存 | 效果图 |
RGBA 32bit 未压缩 | 16M | |
ETC2 RGB+ 1bit Alpha 4bit Android | 2M | |
ETC2 RGBA 8bit Android | 4M | |
ETC1 RGB 4bit Android | 2M | |
PVRTC RGBA 4Bit IOS | 2M | |
PVRTC RGB 4bit IOS | 2M |