目录

1. creator游戏开发之纹理压缩

2. 常用的压缩纹理格式

3. 测试

4. ETC2 格式测试

6. ASTC格式测试

送上下载链接 不修改引擎的实现ASTC格式加载.zip-cocos2D文档类资源-CSDN下载

7.  最后附上插件代码


1. creator游戏开发之纹理压缩

目的:减少运行内存,减少耗电量发热

2. 常用的压缩纹理格式

  1. 常用压缩格式有 ETC1、ETC2、PVRTC、ASTC
  1. 分析对比:

兼容 、内存、 效果 各方面分析对比

ETC1的问题是不支持透明通道;而PVRTC的问题是透明图片质量太差,且图片大小必须是2的幂和正方形。ETC2的出现正好弥补了这两个格式的不足。

ETC2 需要 OpenGL ES 3.0 支撑。

OpenGL ES 3.0的兼容情况,大概是这样的:

  • 软件:
  • android 4.3以上支持ES3.0
  • android  minSdkVersion版本18
  • IOS 7以上支持ES3.0
  • 硬件:
  • Adreno 300 and 400 series (Android, BlackBerry 10, Windows Phone 8, Windows RT)
  • Mali T600 series onwards (Android, Linux, Windows 7)
  • PowerVR Series6 (iOS, Linux)
  • Vivante (Android, OS X 10.8.3, Windows 7)
  • Nvidia (Android, Linux, Windows 7)
  • Intel (Linux)
  • 苹果设备从A7开始支持ES3.0,最低要求的设备是:
  • iPhone 5S
  • iPad Air
  • iPad mini with Retina display

ASTC 6x6的内存容量小于ETC2 4 bits,压缩质量高于ETC2 4 bits。creator3.0以后支持ASTC ,受版本限制creator2.4需要修改c++底层逻辑来加载ASTC

3. 测试

测试的纹理图片:1.jpg (720*1600) 位深度24、2.png( 614*902) 位深度8、3.png( 462*689)位深度8

补充知识:

RGBA4444 :每个通道占4位(bit)4*4 = 16位

RGBA8888 :每个通道占8位(bit)32位

RGB565 :占用的存储大小 5+6+5 = 16 位 = 2Byte

RGB888 :每个通道占8位(bit)24位 = 3Byte

纹理内存计算:(12* 720*1600 + 4* 614*902 + 4* 462*689)/(1024*1024) = 16.5M

测试工程:不加载任何纹理 (空包内存):50.6M

显示那3张图片内存:67.3M

4. ETC2 格式测试

  • 准备工作

需要android  minSdkVersion版本18

使用的 ext.COMPRESSED_RGBA8_ETC2_EAC

引擎目录jsb-adapter/bin/jsb-builtin.js可以看到支持的压缩格式

压缩工具在引擎目录:\2.4.3\resources\static\tools\texture-compress\mali\Windows_64\

etcpack.exe

相关工具ImageMagick 中文站

构建后需要关注的变化:

查阅 CCMacro.js的 SUPPORT_TEXTURE_FORMATS和 resources\engine\cocos2d\renderer\gfx\ enums.js 的enums

回到构建后的assets目录下资源,压缩需要处理的贴图得到pkm

0 换成 6@29

  • IOS 需要改用ES3.0的EGLContext 参考 PR #1685

creator2.4支持

creator2.4.3 提示只支持导出,但实际测试是已经支持加载了。可能编辑器没同步更新。

  • 结果

ETC2 fast 内存:减少%40以上

一共花了约2分钟

ETC2 slow 压缩一张图片要3-5分钟,实在太慢了。好在有缓存不用重复压缩,和fast模式差别不大,可能图片质量高一些,看不太出来。

问题

  1. 透明渐变区域有波纹(透明通道)
  1. mac平台纹理压缩 后透明度不对, etc2存在alpha精度丢失

解决方式(Mac 升级工具链)

6. ASTC格式测试

ASTC 6x6的内存容量小于ETC2 4 bits,压缩质量高于ETC2 4 bits。

需要参考creator3.x的实现方式自行修改 参考这里

送上下载链接 不修改引擎的实现ASTC格式加载.zip-cocos2D文档类资源-CSDN下载

7.  最后附上插件代码

插件说明:插件实现在构建的时候自动将项目贴图资源压缩,无感操做

完整构建插件:packages\pack-render

核心代码文件(main.js):

/*main.js*/
/* eslint-disable no-undef */
const Fs = require('fs');
const Path = require('path');
const FsExtra = require('fs-extra');
const { resolve } = require('path');const settingPath = "packages://pack-render/config/setting.json"
const astc = "packages://pack-render/astcenc/astcenc-avx2"
var isCompress = true;
var platform = "android"// 开始构建
function onBeforeBuildStart (options, callback) {isCompress = options.isCompressplatform = options.platformEditor.log("pack-render:start::", isCompress);if (!isCompress) {callback();return;}Editor.Ipc.sendToMain("pack-render:doWork", "start", function (event, args) {Editor.log("doWork  start >>> Complete");callback();});
}
// 构建完成
function onBeforeBuildFinish (options, callback) {callback();
}function onBuildFinish (options, callback) {isCompress = options.isCompressplatform = options.platformEditor.log("pack-render:finish::", isCompress);if (!isCompress) {callback();return;}Editor.Ipc.sendToMain("pack-render:setBuildResults", options.bundles);Editor.Ipc.sendToMain("pack-render:doWork", "finish", function (event, args) {Editor.log("doWork finish >>> Complete");callback();});
}const Types = {NONE: "none",ETC2_RGBA: "etc2",ASTC_6_6: "astc_6_6",ASTC_8_8: "astc_8_8"
}function autoSetTypeSelectWithPlatform (setting, p) {if (p === 'ios') {setting.typeSelect = Types.ASTC_6_6} else if (p === 'android') {setting.typeSelect = Types.ETC2_RGBA}
}module.exports = {data: {setting: {},platformSettings: {},cmd: "start",buildBundles: null},messages: {'open' () {Editor.Panel.open('pack-render');// 面板加载时,直接显示缓存数据.setTimeout(() => {Editor.Ipc.sendToPanel("pack-render", "loadConfigs", "arg1", "arg2");}, 2000);},'onStart' (event, arg1, arg2) {Editor.log("onStart", arg1, arg2);},'setBuildResults' (event, bundles) {// Editor.log("setBuildResults:", bundles);this._setBuildResults(bundles);},async 'doWork' (event, arg1) {// this.encNativeTexture("D:/build/jsb-default/assets/testui/native/2e/2ef15057-867c-45ec-a6b1-1dabeaeec6bc.c4c12.png");// return;Editor.log("doWork:", arg1);await this.updateSetting()this.cmd = arg1let isAstc = this.isASTC()if (this.cmd == "start") {if (this.setting.include && this.setting.include.length > 0) {// if (isAstc) {//   setTimeout(() => {//     if (event.reply) {//       event.reply(null, 'Fine, thank you!');//     }//   }, 1000);// } else {this.findPaths(this.setting.include, event)// }}} else if (this.cmd == "finish") {if (this.setting.include && this.setting.include.length > 0) {if (isAstc) {this.findImports(this.setting.include, event)} else {this.findPaths(this.setting.include, event)}}}}},load () {this.updateSetting();Editor.Builder.on('build-start', onBeforeBuildStart); // 构建开始时触发。// 在构建结束 之前 触发,此时除了计算文件 MD5、生成 settings.js、原生平台的加密脚本以外,大部分构建操作都已执行完毕。我们通常会在这个事件中对已经构建好的文件做进一步处理。Editor.Builder.on('before-change-files', onBeforeBuildFinish);Editor.Builder.on('build-finished', onBuildFinish); // 构建完全结束时触发。},unload () {Editor.Builder.removeListener('build-start', onBeforeBuildStart);Editor.Builder.removeListener('before-change-files', onBeforeBuildFinish);Editor.Builder.removeListener('build-finished', onBuildFinish);},addLog (...str) {Editor.Ipc.sendToPanel("pack-render", "addLog", str.join(':'));Editor.log(str.join(':'))},// 同步配置updateSetting () {return new Promise(resolve => {// 检查配置文件Fs.access(Editor.url(settingPath), Fs.constants.R_OK | Fs.constants.W_OK, (err) => {if (err) {autoSetTypeSelectWithPlatform(this.setting, platform)Fs.writeFile(Editor.url(settingPath), JSON.stringify({}), 'utf-8');return resolve(this.setting)} else {// Editor.log(`${settingPath} exists, and it is read-writable`);Fs.readFile(Editor.url(settingPath), 'utf-8', (err, res) => {if (err) {return resolve(this.setting);}const settingObj = res ? JSON.parse(res) : {};autoSetTypeSelectWithPlatform(settingObj, platform)Editor.log("update setting", JSON.stringify(settingObj));this.setting = settingObjreturn resolve(this.setting)});}})});},isASTC () {return this.setting.typeSelect == Types.ASTC_6_6 || this.setting.typeSelect == Types.ASTC_8_8},_setBuildResults (bundles) {this.buildBundles = bundles},// 查询资源async findPaths (include, event) {//for (let index = 0; index < include.length; index++) {const config = include[index];let path = "db://assets/" + config.path + "/**/*"// "db://assets/testui/**/*"let results = await this.queryAssets(path)if (!results) {continue;}for (let itemidx = 0; itemidx < results.length; itemidx++) {const item = results[itemidx];if (this.isExcludePath(item.url)) {this.addLog("排除:", item.url);continue}// Editor.log("绝对路径:", item.path);let uuid = item.uuid;this.addLog("设置纹理格式:", item.url);await this.changeMeta(item.uuid, item.url)}if (index == include.length - 1) {this.addLog(">>> Complete");if (event.reply) {event.reply(null, 'Fine, thank you!');}}}},isExcludePath (url) { // 排除for (let index = 0; index < this.setting.exclude.length; index++) {const path = this.setting.exclude[index].path;if (url.indexOf(path) >= 0) {return true;}}return false;},queryAssets (urlPath) {Editor.log("查询目录:", urlPath);return new Promise(resolve => {Editor.assetdb.queryAssets(urlPath, "texture", (err, results) => {if (err) {Editor.log("error:", err);return resolve(null)}Editor.log("找到文件个数:", results.length);return resolve(results)});});},// 修改metachangeMeta (uuid, url) {return new Promise(resolve => {let type = this.setting.typeSelectthis.platformSettings = {android: {formats: []}}if (this.cmd == "finish") {this.platformSettings = {};} else {if (type == Types.ETC2_RGBA) {this.platformSettings.android.formats.push({ name: "etc2", quality: "fast" })} else if (type == Types.ETC2_RGB) {this.platformSettings.android.formats.push({ name: "etc2_rgb", quality: "fast" })} else {this.platformSettings = {};}}var platformSettingsTemp = this.platformSettings// Editor.log("修改meta:", JSON.stringify(this.platformSettings));// Editor.log("修改meta:", uuid);Editor.Ipc.sendToMain("asset-db:query-meta-info-by-uuid", uuid, function (err, info) {let metaInfo = JSON.parse(info.json)// Editor.log("修改前meta:", platformSettingsTemp);metaInfo.platformSettings = platformSettingsTemp// Editor.log("修改后meta:", JSON.stringify(metaInfo))Editor.assetdb.saveMeta(metaInfo.uuid, JSON.stringify(metaInfo, null, 2), function (err, info) {resolve()});})});},// 查询importasync findImports (include, event) {if (!this.isASTC()) {return;}for (let index = 0; index < this.buildBundles.length; index++) {const bundle = this.buildBundles[index];// Editor.log("bundle:", bundle)if (bundle.name == "internal" || !bundle.root) {continue}var buildResults = bundle.buildResults;//let querypath = bundle.root + "/**/*"let results = await this.queryImports(querypath)if (!results) {continue;}for (let j = 0; j < results.length; ++j) {let item = results[j];if (this.isExcludePath(item.url)) {this.addLog("排除:", item.url);continue}Editor.log("ready astcEnc :", item.url)let uuid = item.uuidvar nativePath = buildResults.getNativeAssetPath(uuid);let importUrl;if (buildResults._md5Map) {let import_md5 = buildResults._md5Map[uuid];importUrl = bundle.dest + "/import/" + uuid.slice(0, 2) + "/" + uuid + "." + import_md5 + ".json"} else {importUrl = bundle.dest + "/import/" + uuid.slice(0, 2) + "/" + uuid + ".json"}await this.astcEnc(importUrl, nativePath);}}if (event.reply) {event.reply(null, 'Fine, thank you!');}},queryImports (urlPath) {Editor.log("查询目录:", urlPath);return new Promise(resolve => {Editor.assetdb.queryAssets(urlPath, "texture", (err, results) => {if (err) {Editor.log("error:", err);return resolve(null)}return resolve(results)});});},async astcEnc (importUrl, nativeUrl) {Editor.log("importUrl:", importUrl);await this.changeImportJson(importUrl)Editor.log("nativeUrl:", nativeUrl);await this.encNativeTexture(nativeUrl)return new Promise(resolve => {resolve();});},// 废弃getAssetPath (uuid, bundelName) {for (let index = 0; index < this.buildBundles.length; index++) {const bundle = this.buildBundles[index];// if (bundle.name != bundelName) {//   continue// }var buildResults = bundle.buildResults;// Editor.log("bundle:", JSON.stringify(bundle));// Editor.log("buildResults:", buildResults);// 获得指定资源依赖的所有资源// var depends = buildResults.getDependencies(uuid);// Editor.log("depends:", depends);// 获得构建后的原生资源路径(原生资源有图片、音频等,如果不是原生资源将返回空)var nativePath = buildResults.getNativeAssetPath(uuid);let importUrl;if (buildResults._md5Map) {let import_md5 = buildResults._md5Map[uuid];importUrl = bundle.dest + "/import/" + uuid.slice(0, 2) + "/" + uuid + "." + import_md5 + ".json"} else {importUrl = bundle.dest + "/import/" + uuid.slice(0, 2) + "/" + uuid + ".json"}// Editor.log("importPath:", importUrl);// 获取资源类型// var type = buildResults.getAssetType(uuid);// Editor.log("type:", type);return { nativeUrl: nativePath, importUrl: importUrl }}},changeImportJson (importUrl) {return new Promise(resolve => {Fs.readFile(importUrl, 'utf-8', (err, res) => {if (err) {return resolve();}let obj = JSON.parse(res)if (this.setting.typeSelect == Types.ASTC_6_6) {obj[5][0] = "7@34,9729,9729,33071,33071,0,0,1"} else if (this.setting.typeSelect == Types.ASTC_8_8) {obj[5][0] = "7@37,9729,9729,33071,33071,0,0,1"}// Editor.log("changeImportJson:", JSON.stringify(obj));Fs.writeFileSync(importUrl, JSON.stringify(obj), 'utf-8');return resolve(obj)});});},encNativeTexture (nativeUrl) {return new Promise(resolve => {// var cmd = Editor.url('packages://pack-render/astcenc/a.bat') + " " + nativeUrl;// var cmd = Editor.url('packages://pack-render/astcenc/do.bat') + " " + nativeUrl;let outfile = nativeUrl.replace(/\.\w+$/, ".astc");let sel = "6x6"if (this.setting.typeSelect == Types.ASTC_6_6) {sel = "6x6"} else if (this.setting.typeSelect == Types.ASTC_8_8) {sel = "8x8"}var cmd = "python " + Editor.url('packages://pack-render/astcenc/runner.py') + ` -cl ${nativeUrl} ${outfile} ${sel} -medium`;this.exec(cmd, () => {Fs.unlink(nativeUrl, (err) => {if (err) {Editor.error(err)}Editor.log('>>> encNativeTexture complete');return resolve();});})// let pythonFile = Editor.url('packages://pack-render/') + "test.py"// this.python(pythonFile, [nativeUrl, Editor.url('packages://pack-render/')], () => {//   Editor.log('>>> encNativeTexture complete');// })});},exec (cmd, callback) {var exec = require('child_process').exec;Editor.log('exec::' + cmd);exec(cmd, function (err, stdout, stderr) {if (err) {Editor.log('execall:: error:' + stderr);} else {// var data = JSON.parse(stdout);Editor.log(stdout)callback()}});},shell (cmd, callback) {var callfile = require('child_process');var ip = '1.1.1.1';var username = 'test';var password = 'pwd';var newpassword = 'newpwd';callfile.execFile('xxx.sh', ['-H', ip, '-U', username, '-P', password, '-N', newpassword], null, function (err, stdout, stderr) {// callback(err, stdout, stderr);});},python (pythonUrl, pramas, callback) {var exec = require('child_process').exec;exec('python ' + pythonUrl + ' ' + pramas[0] + ' ' + pramas[1] + ' ', function (error, stdout, stderr) {if (stdout.length > 1) {Editor.log('you offer args:', stdout);} else {Editor.log('you don\'t offer args');}if (error) {Editor.info('python call error::' + stderr);}});}}

参考

1.

Cocos Creator 纹理压缩插件 - Creator - Cocos中文社区

2. etc2

【技术分享之三】cocos实现对ETC2的支持 - Creator - Cocos中文社区

astc

大佬们有没有计划或者方案在2.4.x上使用astc - Creator - Cocos中文社区

creator贴图纹理压缩(creator2.4.x 实现ETC2和ASTC)相关推荐

  1. UE4 Material 101学习笔记——08-12 凹凸和视差贴图/纹理压缩/布料/体积冰/摇曳树叶

    UE4 Material 101学习笔记--08-12 凹凸和视差贴图/纹理压缩/布料/体积冰/摇曳树叶 Lec08 凹凸和视差贴图 Bump Offset and Parallax Occlusio ...

  2. unity 纹理压缩格式‘_[2018.1]Unity贴图压缩格式设置

    一.移动平台GPU 参考文档: 各种移动GPU压缩纹理的使用方法 - LuMing - 博客园​www.cnblogs.com 1.Imagination Technologies的PowerVR S ...

  3. OpenGL蓝宝书源码学习(十)第五章——纹理的应用、Mip贴图、各项异性过滤和纹理压缩基础

    一.纹理应用 1.纹理坐标 我们是通过为每个顶点指定一个纹理坐标而直接在几何图形上进行纹理贴图的.纹理坐标要么是指定为着色器的一个属性,要么通过算法计算出来.纹理贴图中的纹理单元是作为一个更加抽象的纹 ...

  4. cocos creator | 为什么 shader 效果在编辑器中显示正常,运行后却显示异常? 合图纹理的uv计算

    获取源码,请关注公众号: 感谢QQ群(521643513)内 honmono 大佬的指导 01 uv 坐标 之后的文章中,我们再详细介绍顶点着色器,片段着色器,纹理等知识 这里简单了解下基本概念 渲染 ...

  5. unity 纹理压缩格式‘_纹理优化:让你的纹理也“瘦”下来

    在上一期<纹理优化:不仅仅是一张图片那么简单>中,我们针对纹理相关的优化,挑选了部分知识点分析.无论是大家在开发时的疏忽,还是对相关知识点的理解不足,这些问题的积累最终都会反映到项目的性能 ...

  6. 【Unity3D】图片纹理压缩方式,干货走起!

    Unity3D引擎对纹理的处理是智能的:不论你放入的是PNG,PSD还是TGA,它们都会被自动转换成Unity自己的Texture2D格式. 在Texture2D的设置选项中,你可以针对不同的平台,设 ...

  7. 【百人计划】图形3.5 纹理压缩的格式

    笔记部分> 一.什么是纹理压缩格式(概念) 为了解决内存和带宽问题,在计算机图形渲染中(储存纹理)的一种图像压缩.优化技术. 二.为什么要进行纹理压缩? 对于低硬件设备和移动端,有两个问题需要解 ...

  8. unity 纹理压缩 内存优化

    1.界面打开慢可分为首次打开慢和再次打开慢,首次打开慢一般是由于需要加载过多的UI资源.而再次打开慢就是程序不合理造成的了.首次界面打开加载的资源(如:贴图)会被缓存在内存中,这样再次打开界面由于内存 ...

  9. DXT纹理压缩格式解析

    我们知道游戏中对于3D物体表面细节的表现最重要的还是靠贴图来实现的,那么越是高分辨率越是真彩色的贴图自然表现力也是越强,但是同时带来的问题是所需占用的内存会成倍的上升,而节省内存这一点在目前的游戏中还 ...

  10. 纹理优化三-KTX纹理压缩

    KTX简介: KTX (Khronos Texture) 是一种纹理存储格式,大部分移动设备的 GPU 均支持这种格式.可以有效降低设备的显存占用,提高运行效率和稳定性. ktx是容器,astc是算法 ...

最新文章

  1. Swift3实现的绘制股票K线库, FastImageCache提升图片的加载和渲染速度,Chameleon颜色框架
  2. python怎么输出文本_python输出语句怎么用
  3. How many levels are there at the in the digital transformation?
  4. elasticsearch和php,快速开始 | Elasticsearch-PHP | Elastic
  5. 最近幻影的两个ARP欺骗工具 挺不错的
  6. PHP 下载远程图片
  7. spark shuffle流程入门
  8. JavaScript基础(三)
  9. VideoView播放视频会引起其它音乐播放器暂停问题解决
  10. windows2012R2 无系统盘 安装netframe3.5 (需连公网)
  11. 浏览器对URL的长度限制
  12. 论合同管理的现状、发展趋势及重要性
  13. 【逻辑思考】有时评论比内容更精彩
  14. api 二次 开发 禅道_禅道 Rest API 开发
  15. 2021-05-12 MongoDB面试题 “ObjectID“有哪些部分组成
  16. php文字验证码插件,php中文验证码实现方法
  17. halcon算子翻译——dev_update_off、dev_update_on
  18. 【C++】%d,%05d,%-5d,%.5d的区分
  19. SSL/TLS 双向认证(一) -- SSL/TLS工作原理
  20. 微电子基本知识---绝缘相关性质(电阻率,介电常数,漏电流,漏电流密度,击穿电压,击穿场强)

热门文章

  1. 无法复制文件到远程桌面的解决办法
  2. 吴伯凡-认知方法论-矩阵式认知与苏格拉底
  3. 正面管教:不凶不吼教出好孩子读后感
  4. 4.13 期货每日早盘操作建议
  5. python绘图矩阵散点图_Python数据可视化:用Seaborn绘制高端玩家版散点图
  6. itextpdf生成列表基本用法
  7. oeasy教您玩转python - 008 - # ascii码表
  8. 计算机应用责编处理录用几率大吗,等待责编处理是什么意思
  9. 项目市场调查报告的撰写要则
  10. USB学习笔记——认识USB