Cocoscreator:自动化设置压缩纹理格式

704 阅读3分钟

在游戏开发中,纹理是游戏中展示图像的重要元素,它是大部分游戏中占据包体最大的资源,并且占据了大量的内存,传统的图片压缩格式,如jpg, png等虽然可以减少图片资源的大小,但是不能被GPU识别,需要先加载到内存,通过CPU解码,最终转换成RGB/RGBA等能被GPU识别的格式,才能传送到GPU进行渲染。

压缩纹理的出现,解决上面的问题,它是一种专门针对GPU的纹理压缩方案。它可以直接被GPU识别和渲染。它具有以下有点:

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

常用的压缩纹理格式

在Cocos Creator中,常用的压缩纹理格式有以下几种:

  • 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的幂次方。

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

  • PVRTC:适用于iOS平台,压缩比率和ETC相似,但在纹理长宽相等、为2的幂次方的要求和画面质量方面存在限制。在实测中还发现转换后的图片质量不如ETC1,存在模糊、毛边现象,对画面要求高的游戏不适合

因此通常安卓平台会选择ETC1方式,IOS平台会选择ETC2

自动化设置压缩纹理

在设置压缩纹理格式时,目前Creator 2.x版本还需手动一个一个设置,下面用node.js自动化设置压缩纹理格式,并随时可以取消,恢复原始设置。

代码如下:

const fs = require('fs');
const path = require('path');

const etcSettings = {
  android: {
    formats: [
      {
        name: 'etc1',
        quality: 'slow',
      },
    ],
  },
  ios: {
    formats: [
      {
        name: 'etc2',
        quality: 'slow',
      },
    ],
  },
};

function lookupDir(url, isCompress) {
  if (!fs.existsSync(url)) {
    return;
  }

  const files = fs.readdirSync(url);
  files.forEach((file) => {
    const curPath = path.join(url, file);
    const stat = fs.statSync(curPath);

    if (stat.isDirectory()) {
      lookupDir(curPath, isCompress); // 遍历目录
    } else if (file.endsWith('.meta')) {
      try {
        const data = fs.readFileSync(curPath, 'utf8');
        const obj = JSON.parse(data);

        if (obj && obj.platformSettings) {
          obj.platformSettings = isCompress ? etcSettings : {};
          const wrdata = JSON.stringify(obj, null, 2);
          fs.writeFileSync(curPath, wrdata, 'utf8');
        }
      } catch (err) {
        console.error(`Error reading or parsing file ${curPath}:`, err);
      }
    }
  });
}

function main() {
  const sourcePath = process.argv[2];
  const isCompress = parseInt(process.argv[3]);

  if (!sourcePath) {
    console.error('Source path not provided.');
    return;
  }

  const absolutePath = path.isAbsolute(sourcePath)
    ? sourcePath
    : path.join(__dirname, sourcePath);

  lookupDir(absolutePath, isCompress);
}

main();

将上面代码保存为auto_etc.js文件

使用 使用命令行:

node auto_etc.js /path/assets isCompress

第二个参数为资源的目录,第三个为是否压缩,1:压缩,0:取消压缩