Home

Awesome

gltf-gpu-compressed-texture

一个用于 GPU 压缩纹理降级的 GLTF 扩展,以及批量 CLI 转换工具,适用于THREEGLTFLoaderDEMO 地址扩展定义

加载策略

  1. 优先使用 pvrtc,因为其体积上面与 jpg 相差不大,与 PNG 有较大优势(done
  2. 无透明通道优先使用 etc1 (done 大小的策略可覆盖这条
  3. 根据 bitmap 与所支持的压缩纹理格式体积比值判断是否使用压缩纹理(done 选择大小小于 bitmap 2 倍的压缩纹理
  4. 少图片和小图片 UI 线程 decode,否则在 Worker 线程 decode(done 少图片

TODO

  1. 多进程 encode (done
  2. 输出加载各压缩纹理类型体积统计 (done
  3. 按一定优先级规则 GPU 压缩纹理类型 (优先 pvrtc
  4. 支持输出 GLB 格式
  5. basisu zstd 参数可自定义(basisu done
  6. 少图片使用 UI 线程 decode, 多图片使用 worker decode (done, 但是对于少贴图模型需要更详细规则
  7. 支持 ETC2 格式
  8. 生成 bitmap 大小,用于策略判断 (done
  9. 可自定义加载策略 (done
  10. 类 tfjs tf.profile 运行时反馈式优化,即运行时遍历出加载时间最少的策略并记录起来(针对当前场景而言)
  11. 升级 zstd wasm 构建参考zstandard-wasm (done DamagedHelmet 95ms -> 81ms 大概15%的提升

CHANGELOG

命令行使用

使用之前请确保zstdbasisu已经在 PATH 里面

> npm i gltf-gpu-compressed-texture -S
# 查看帮助
> gltf-tc -h

  -h --help                                                              显示帮助
  -i --input [dir] [?outdir] [?compress] [?mipmap] [?basisuArgs]         把gltf所使用纹理转换为GPU压缩纹理并支
持fallback

Examples:
  gltf-tc -i ./examples/glb ./examples/zstd
  gltf-tc -i ./examples/glb ./examples/no-zstd 0
  gltf-tc -i ./examples/glb ./examples/no-mipmap 1 false
  gltf-tc -i ./examples/glb ./examples/no-zstd-no-mipmap 0 false
  gltf-tc -i ./examples/glb ./examples/zstd 1 true "-uastc"

# 执行
> gltf-tc -i ./examples/glb ./examples/zstd

done: 9855ms    image3.png      法线:false      sRGB: true
done: 15337ms   image2.png      法线:true       sRGB: false
done: 16189ms   image0.png      法线:false      sRGB: true
done: 16894ms   image1.png      法线:false      sRGB: false
done: 600ms     FINDI_TOUMING01_nomarl1.jpg     法线:true       sRGB: false
done: 612ms     FINDI_TOUMING01_Basecoler.png   法线:false      sRGB: true
done: 1317ms    lanse_banzi-1.jpg       法线:false      sRGB: true

cost: 18.88s
compress: 1, BoomBox summary:
  bitmap: 10.53MB (0.00MB)
  astc  : 6.12MB (-4.41MB)
  bc7   : 6.08MB (-4.44MB)
  dxt   : 2.56MB (-7.97MB)
  pvrtc : 1.87MB (-8.66MB)
  etc1  : 1.41MB (-9.12MB)

compress: 1, Fendi_banzi_blue summary:
  bitmap: 0.33MB (0.00MB)
  astc  : 0.52MB (0.19MB)
  bc7   : 0.53MB (0.19MB)
  dxt   : 0.23MB (-0.10MB)
  pvrtc : 0.20MB (-0.14MB)
  etc1  : 0.21MB (-0.12MB)

Done in 19.43s.

只要设置 -comp_level 6,这个脚本就是烤机工具

NPM 包使用

import {
  GLTFLoader,
  CompressedTexture,
  WebGLRenderer,
} from 'three-platfromzie/examples/jsm/loaders/GLTFLoader';
import { GLTFGPUCompressedTexture } from 'gltf-gpu-compressed-texture';

const gltfLoader = new GLTFLoader();
const renderer = new WebGLRenderer();
const scene = new Scene();

gltfLoader.register(parser => {
  return new GLTFGPUCompressedTexture({
    parser,
    renderer,
    CompressedTexture: THREE.CompressedTexture,
    loadStrategy: GLTFGPUCompressedTexture.DEFAULT_STRATEGY,
  });
});

gltfLoader.loadAsync('./examples/zstd/BoomBox.gltf').then(gltf => {
  scene.add(gltf.scene);
});

性能情况

运行环境 Chrome 93, CPU Intel I9 10900 ES 版,核显 HD630
加载 BC7 格式,use ImageBitmapLoader,THREE r129,localhost,disable cache: true

模型参数loadrender总耗时模型大小依赖大小
banzi_bluegltf-tc zstd no-mimap no-worker36.10ms1.60ms37.70ms506kb22.3kb
banzi_bluegltf-tc no-zstd mimap no-worker25.80ms1.50ms27.30ms2.2mb22.3kb
banzi_bluegltf-tc zstd mimap no-worker37.90ms1.60ms39.50ms648kb22.3kb
banzi_bluegltf ktx2 uastc534.70ms1.70ms536.40ms684kb249.3kb
banzi_blueglb32.80qms6.00ms38.80ms443kb
banzi_bluegltf27.70ms4.90ms32.60ms446kb
BoomBoxgltf-tc zstd mipmap worker153.50ms23.70ms177.20ms6.6mb22.3kb
BoomBoxgltf-tc zstd mipmap no-worker241.10ms9.40ms250.50ms6.6mb22.3kb
BoomBoxglb ktx2 uastc506.10ms9.30ms515.40ms7.1mb249.3kb
BoomBoxglb156.10ms89.50ms245.60ms11.3mb
BoomBoxgltf120.20ms58.80ms179.00ms11.3mb

由于 banzi_blue 贴图小于 4 张,所以在 UI 线程 decode zstd,因为 worker 传数据也会有不少耗时 对比使用的 KTX2Loader 全部 zstd decode 是在 UI 线程,decode in Web Worker PR已提交 依赖大小 22.3kb 是从线上 DEMO 取得,http-server --gzip 不太好使

可以明显看到相比于 KTX2+uastc 的压缩纹理方案,从加载耗时和依赖大小,有大幅优势,模型大小也有不少优势
同时也可以看到 BoomBox gltf-tc zstd mipmap worker load+render 耗时,与 gltf 耗时 相差不大,但是模型大小有大幅优势

但是这些都是相对于 PNG 和压缩纹理对比,从 DamagedHelmet 可看到 jpg 的体积对比,jpg 有十分巨大的体积优势

compress: 1, DamagedHelmet summary:
  bitmap: 3.06MB (0.00MB)
  astc  : 11.49MB (8.42MB)
  bc7   : 11.52MB (8.46MB)
  dxt   : 5.15MB (2.09MB)
  pvrtc : 4.12MB (1.05MB)
  etc1  : 4.71MB (1.65MB)

MI 8 下和火狐的测试数据可以查看 screenshots 目录

微信 webview 下 BoomBox 均比 glb/gltf 快,应该属于异常,chrome 下表现正常,banzi_blue 则稍慢一些,KTX2 的方案依然很慢

示例还有 FlightHelmetCases,但是图片资源太大,火狐 lost context, chrome render process 崩溃

参考

  1. ASTC 纹理压缩格式详解
  2. 你所需要了解的几种纹理压缩格式原理

赞助

如果项目对您有帮助或者有适配需求,欢迎打赏

<img src="https://upload-images.jianshu.io/upload_images/252050-d3d6bfdb1bb06ddd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="赞赏码" width="300">