Package Exports
- etcpack-wasm
- etcpack-wasm/wasm
Readme
ETCPACK WASM API 文档
概述
ETCPACK WASM 提供了完整的 ETC/EAC 纹理压缩功能,支持在浏览器中进行高质量的纹理压缩。
安装
# 构建 WASM 模块
cd wasm
./build.sh prod快速开始
import { createETCPACK, TextureFormat } from './etcpack-api.js';
// 初始化
const encoder = await createETCPACK();
// 压缩 RGB 图像
const compressed = encoder.compressRGB({
data: rgbData, // Uint8Array
width: 512,
height: 512,
format: TextureFormat.ETC2_RGB
});
console.log(`压缩比: ${compressed.compressionRatio.toFixed(2)}:1`);TypeScript 类型
TextureFormat
enum TextureFormat {
ETC1_RGB = 0, // ETC1 RGB (向后兼容)
ETC2_RGB = 1, // ETC2 RGB
ETC2_RGBA1 = 2, // ETC2 RGB + 1-bit Alpha
ETC2_RGBA = 3, // ETC2 RGBA (with EAC)
EAC_R11 = 4, // EAC R11 unsigned
EAC_R11_SIGNED = 5, // EAC R11 signed
EAC_RG11 = 6, // EAC RG11 unsigned
EAC_RG11_SIGNED = 7 // EAC RG11 signed
}CompressOptions
interface CompressOptions {
data: Uint8Array | Uint8ClampedArray; // 图像数据
width: number; // 宽度(必须是 4 的倍数)
height: number; // 高度(必须是 4 的倍数)
format?: TextureFormat; // 格式(可选)
}CompressResult
interface CompressResult {
data: Uint8Array; // 压缩后的数据
width: number; // 图像宽度
height: number; // 图像高度
format: TextureFormat; // 压缩格式
compressedSize: number; // 压缩后大小(字节)
originalSize: number; // 原始大小(字节)
compressionRatio: number; // 压缩比
}DecompressOptions
interface DecompressOptions {
data: Uint8Array; // 压缩数据
width: number; // 宽度
height: number; // 高度
format: TextureFormat; // 压缩格式
}DecompressResult
interface DecompressResult {
data: Uint8Array; // 解压后的数据
width: number; // 图像宽度
height: number; // 图像高度
channels: number; // 通道数 (3=RGB, 4=RGBA, 1=R, 2=RG)
}API 方法
ETCPACKEncoder
compressRGB(options: CompressOptions): CompressResult
压缩 RGB 图像为 ETC1/ETC2 格式。
参数:
data: Uint8Array - RGB 图像数据width: number - 图像宽度(必须是 4 的倍数)height: number - 图像高度(必须是 4 的倍数)format: TextureFormat - 压缩格式(默认 ETC2_RGB)
返回: CompressResult
示例:
const result = encoder.compressRGB({
data: rgbData,
width: 512,
height: 512,
format: TextureFormat.ETC2_RGB
});decompressRGB(options: DecompressOptions): DecompressResult
解压 RGB 图像。
参数:
data: Uint8Array - 压缩数据width: number - 图像宽度height: number - 图像高度format: TextureFormat - 压缩格式
返回: DecompressResult(channels = 3)
compressRGBA(options: CompressOptions): CompressResult
压缩 RGBA 图像为 ETC2 + EAC Alpha 格式(16 字节/块)。
参数:
data: Uint8Array - RGBA 图像数据width: number - 图像宽度height: number - 图像高度
返回: CompressResult
示例:
const result = encoder.compressRGBA({
data: rgbaData,
width: 256,
height: 256
});decompressRGBA(options: DecompressOptions): DecompressResult
解压 RGBA 图像。
返回: DecompressResult(channels = 4)
compressRGBA1(options: CompressOptions): CompressResult
压缩 RGBA 图像为 ETC2 + 1-bit Alpha(punchthrough)格式(8 字节/块)。
适用于二值 Alpha(完全透明或完全不透明)。
示例:
const result = encoder.compressRGBA1({
data: rgbaData,
width: 512,
height: 512
});decompressRGBA1(options: DecompressOptions): DecompressResult
解压 RGBA1 图像。
compressR11(options: CompressOptions & { signed?: boolean }): CompressResult
压缩单通道 11-bit 数据(EAC R11)。
参数:
data: Uint8Array - 单通道数据(16-bit)width: number - 宽度height: number - 高度signed: boolean - 是否有符号(默认 false)
用途:
- 高度图 / 位移贴图
- 法线贴图(单通道)
- 灰度图
示例:
const result = encoder.compressR11({
data: heightmapData,
width: 1024,
height: 1024,
signed: false
});decompressR11(options: DecompressOptions & { signed?: boolean }): DecompressResult
解压 R11 图像。
返回: DecompressResult(channels = 1,16-bit 输出)
compressRG11(options: CompressOptions & { signed?: boolean }): CompressResult
压缩双通道 11-bit 数据(EAC RG11)。
用途:
- 法线贴图(XY 通道)
- 双通道数据
示例:
const result = encoder.compressRG11({
data: normalMapData,
width: 512,
height: 512,
signed: true // 法线通常使用有符号
});getCompressedSize(width: number, height: number, format: TextureFormat): number
计算压缩后的数据大小(字节)。
示例:
const size = encoder.getCompressedSize(512, 512, TextureFormat.ETC2_RGB);
console.log(`预期大小: ${size} 字节`); // 32768 字节validateDimensions(width: number, height: number): boolean
验证图像尺寸是否有效(必须是 4 的倍数)。
抛出: Error - 如果尺寸无效
示例:
try {
encoder.validateDimensions(513, 512);
} catch (e) {
console.error(e.message); // "Image dimensions must be multiples of 4..."
}使用场景
1. WebGL 纹理压缩
async function uploadCompressedTexture(
gl: WebGLRenderingContext,
imageData: Uint8Array,
width: number,
height: number
) {
const encoder = await createETCPACK();
const compressed = encoder.compressRGB({
data: imageData,
width,
height,
format: TextureFormat.ETC2_RGB
});
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
const ext = gl.getExtension('WEBGL_compressed_texture_etc');
gl.compressedTexImage2D(
gl.TEXTURE_2D, 0,
ext.COMPRESSED_RGB8_ETC2,
width, height, 0,
compressed.data
);
return texture;
}2. Canvas 图像压缩
async function compressCanvas(canvas: HTMLCanvasElement) {
const encoder = await createETCPACK();
const ctx = canvas.getContext('2d')!;
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
return encoder.compressRGBA({
data: imageData.data,
width: canvas.width,
height: canvas.height
});
}3. 批量纹理处理
async function compressBatch(textures: Array<{name: string, data: Uint8Array, width: number, height: number}>) {
const encoder = await createETCPACK();
const results = textures.map(tex => ({
name: tex.name,
...encoder.compressRGB({
data: tex.data,
width: tex.width,
height: tex.height
})
}));
return results;
}性能参考
| 格式 | 压缩比 | 质量 | 速度 | 用途 |
|---|---|---|---|---|
| ETC1 RGB | 6:1 | 中 | 快 | 旧设备兼容 |
| ETC2 RGB | 6:1 | 高 | 快 | 不透明纹理 |
| ETC2 RGBA1 | 6:1 | 高 | 快 | Cutout 透明 |
| ETC2 RGBA | 4:1 | 高 | 中 | 完整 Alpha |
| EAC R11 | 2:1 | 极高 | 中 | 高度图 |
| EAC RG11 | 1:1 | 极高 | 中 | 法线贴图 |
注意事项
- 尺寸要求:图像宽高必须是 4 的倍数
- 内存使用:压缩/解压过程会临时分配内存
- 浏览器兼容:需要 WebAssembly 支持(现代浏览器)
- 纹理格式支持:使用前检查
WEBGL_compressed_texture_etc扩展
错误处理
try {
const result = encoder.compressRGB({
data: imageData,
width: 513, // 不是 4 的倍数
height: 512
});
} catch (error) {
if (error.message.includes('multiples of 4')) {
console.error('图像尺寸必须是 4 的倍数');
}
}文件大小对比
| 分辨率 | RGB 原始 | ETC2 压缩 | 节省 |
|---|---|---|---|
| 512×512 | 768 KB | 128 KB | 83% |
| 1024×1024 | 3 MB | 512 KB | 83% |
| 2048×2048 | 12 MB | 2 MB | 83% |
| 4096×4096 | 48 MB | 8 MB | 83% |