声明:本文部分内容使用AI辅助生成,经人工编辑、审核和补充个人经验。
更新说明:技术栈版本信息基于 Python 3.10+ / OpenGL ES 3.0 / ETC2。
PKM纹理压缩踩坑记录
在做游戏资源优化时,研究了ETC纹理压缩和PKM文件加密,记录一下实现过程。
纹理压缩技术基础
为什么需要纹理压缩
在移动设备上,未经压缩的纹理资源会带来严重问题:
| 问题 | 影响 | 解决方案 |
|---|---|---|
| 内存占用高 | 容易导致OOM | 使用压缩格式 |
| 显存压力大 | 帧率下降 | GPU原生支持的压缩格式 |
| 加载时间长 | 用户体验差 | 减少数据量 |
| 包体过大 | 下载转化率低 | 压缩存储 |
主流纹理压缩格式对比
| 格式 | 压缩比 | 支持平台 | 透明度 | GPU解压 |
|---|---|---|---|---|
| ETC1 | 6:1 | OpenGL ES 2.0+ | 不支持 | 硬件支持 |
| ETC2 | 6:1~8:1 | OpenGL ES 3.0+ | 支持 | 硬件支持 |
| PVRTC | 8:1 | PowerVR GPU | 支持 | 硬件支持 |
| ASTC | 4:1~12:1 | OpenGL ES 3.2+ | 支持 | 硬件支持 |
ETC格式的优势:
- 跨平台支持好(Android主流)
- 解压速度快(GPU硬件解压)
- 压缩率高(ETC2支持透明度)
- 免费使用(无专利费)
ETC压缩原理
ETC(Ericsson Texture Compression)采用分块压缩策略:
1 | 基本原理: |
PKM文件格式详解
PKM文件结构
PKM是ETC压缩纹理的容器格式,文件头包含元数据信息:
1 | PKM文件结构: |
PNG与PKM互转
etcpack工具使用
etcpack是Ericsson官方提供的ETC压缩工具,支持PNG与PKM的相互转换。
PNG转PKM(ETC1):
1 | # 基本转换命令 |
PNG转PKM(ETC2):
1 | # ETC2支持透明度 |
PKM转PNG:
1 | # 解压回PNG |
参数详解:
| 参数 | 可选值 | 说明 |
|---|---|---|
| -c | etc1, etc2 | 压缩格式 |
| -s | fast, slow | 压缩速度 |
| -as | - | 生成Alpha通道 |
| -ext | PNG, PVR, etc | 输出文件扩展名 |
批量转换脚本
Python批量处理脚本
1 | import os |
Cocos Creator ETC批量配置
项目纹理配置
在Cocos Creator中,可以通过meta文件配置纹理压缩格式。
ETC配置结构
1 | { |
配置参数说明:
| 参数 | 说明 | 可选值 |
|---|---|---|
| name | 压缩格式 | etc1, etc2, webp, jpg |
| quality | 压缩质量 | fast, slow |
批量修改脚本
Node.js批量配置脚本
1 | const fs = require('fs'); |
Windows批处理脚本
1 | @echo off |
使用说明
启用ETC压缩:
1 | node setETC.js ./assets 1 |
禁用ETC压缩:
1 | node setETC.js ./assets 0 |
配置说明:
- 脚本会递归遍历指定目录下的所有.meta文件
- 自动添加或移除platformSettings配置
- 根据平台设置不同的压缩格式
PKM文件加密方案
为什么需要加密
虽然PKM已经是压缩格式,但仍可能被提取和还原:
- 保护游戏美术资源
- 防止竞争对手获取资源
- 增加资源破解难度
XOR加密方案
Python加密脚本
1 | import os |
Cocos Creator加载加密PKM
JavaScript/TypeScript加载代码
1 | const {ccclass, property} = cc._decorator; |
资源优化最佳实践
纹理压缩策略
| 平台 | 推荐格式 | 压缩比 | 注意事项 |
|---|---|---|---|
| Android | ETC1/ETC2 | 6:1~8:1 | ETC1不支持透明度 |
| iOS | ETC2/PVRTC | 6:1~8:1 | 优先ETC2 |
| Web | WebP/JPG | 2:1~4:1 | 兼容性考虑 |
工作流程建议
1 | 美术出图(PNG) -> |
性能对比
| 格式 | 内存占用 | GPU解压速度 | 加载速度 | 画质 |
|---|---|---|---|---|
| PNG(RGBA8888) | 100% | 无需解压 | 慢 | 最好 |
| ETC1 | 16.7% | 极快 | 快 | 较好 |
| ETC2 | 12.5%~16.7% | 极快 | 快 | 好 |
| WebP | 100% | 无需解压 | 中等 | 好 |
常见问题处理
ETC格式不支持透明度
问题:ETC1不支持Alpha通道
解决方案:
- 使用ETC2格式(OpenGL ES 3.0+)
- 分离Alpha通道为单独纹理
- 使用其他支持透明度的格式(PVRTC、ASTC)
纹理尺寸要求
要求:
- ETC1:宽高必须是4的倍数
- ETC2:宽高必须是4的倍数
- PVRTC:宽高必须是2的幂且相等
处理方法:
1 | def pad_to_multiple_of_4(width, height): |
加密性能开销
优化建议:
- 异步解密避免阻塞主线程
- 预加载和缓存解密后的纹理
- 只在需要时解密
总结
ETC纹理压缩能有效降低游戏包体和内存占用,配合PKM加密可以保护美术资源。建议Android平台优先使用ETC2,同时建立自动化的资源处理流程。
参考资源: