在制作 2d 游戏时,通常我们需要把大量小图素合并到一整张大贴图上。这可以使用装箱算法 (Bin Packing)完成。当然,很多人很懒,那么就用别人做好的工具,比如 Texture Packer 。
但是在实际开发中, Texture Packer 有几个严重的缺陷 ,我个人还是建议自己来做合图的工具,完善工具链。
缺陷 1 :装箱过程其实并不需要了解图片上的内容,而只需要知道图片的尺寸。所以装箱过程需要的内存量应该只和被装的图素个数相关,和图片大小无关。而 texture packer 并不是这样做的,它把装箱和合成贴图两部工作放在一个黑箱里了,会导致运行时无谓的内存消耗(更不用说它本质上是一个 GUI 程序),不是很适合自动化工具链。
缺陷 2 :如果要求最终合并的图是 pvr 或 etc 压缩贴图,那么还需要最后再对目标图做一次压缩。通常这个压缩过程是比较慢的。
这个缺陷 2 在开发期需要反复打包资源时,对开发效率影响尤其大。但其实如果自己好好设计工具链,是完全可以避免的。
下面就谈谈应该怎么处理 ETC 这类压缩贴图的合并问题。
ETC 这类压缩贴图,内部其实是按 4x4 像素为一个单位区分开的。各个单元之间没有相关性,也只有这样,显卡才能快速处理。所以,完全没有必要在合并图素后,对目标大图做压缩。
正确的做法是,为小图生成对应的压缩数据,好比编译器将 .c 文件 编译成 .o 文件;而装箱合图的过程好比链接器,将压缩后的小图合并到目标贴图上去。
开发过程中,每次修改,主要针对的都是部分小图素;甚至只是添加新的图素,而并没有改动老的。所以这样处理可以极大的减少每次合成大贴图的时间。而装箱程序,只需要输入每个图素的尺寸,输出目标图上的排列就够了,然后用图像处理工具根据装箱布局去组合小的压缩过的图像数据,合成最终的贴图。
我们可以找到一些开源的工具来压缩图素,比如 Ericsson 开源的 etcpack 这个实现的非常糟糕,但用的人很多的工具。这个工具可以把图片文件转换成用 ETC 算法压缩过的数据,生成一个后缀为 .ktx d额压缩图片文件。
我今天写了一个 lua 库,帮助你完成合并多个 .ktx 为一个 .ktx 的过程。
如果真想看一眼的话,那么它的代码在 github 上,它没有人维护,没有使用说明,没有注释,没有测试,也不保证运行结果正确。当然如果你发现有 bug 的话,又乐于修正的话,提个 pull request 还是很欢迎的。