问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Three.js中gltf文件压缩方法详解与性能优化实践

创作时间:
作者:
@小白创作中心

Three.js中gltf文件压缩方法详解与性能优化实践

引用
1
来源
1.
https://www.mvrlink.com/gltf-file-compression-for-threejs-performance-optimization-2/

本文详细探讨了在Three.js中使用gltf文件压缩的几种方法,包括KHR_draco_mesh_compression、KHR_mesh_quantization和EXT_meshopt_compression。通过实际测试数据和设备兼容性测试,为不同业务场景提供了优化建议。

3D模型在线预览提供多种低代码平台3D模型在线预览解决方案,实现了将多种3D模型格式无缝集成到低代码业务表单中。这意味着用户可以在不离开低代码平台的情况下,直接查看和操作3D模型,极大地提升了数据可视化的效果和用户交互体验。

glTF文件压缩

如上面介绍,glTF 文件包括.gltf/.glb 文件、.bin 文件以及纹理资源。glTF2.0 相关的插件主要有以下:

那么我们从中取一些来分析一下。

网格压缩

KHR_draco_mesh_compression

最常见的一种网格压缩方式,采用开源的Draco算法,用于压缩和解压缩3D 网格和点云,并且可能会改变网格中顶点的顺序和数量。压缩的使文件小得多,但是在客户端设备上需要额外的解码时间。

  • 压缩方式

可以使用 gltf-pipeline gltf 文件优化工具进行压缩

  • 使用方式(在 Three.js 中)

  • 性能分析对比

这个 glb 文件原大小为 3.2M,draco 压缩后为 1.8M,约为原文件的56%。从上面的代码中可以看出,创建解码器实例需要引入额外的库来进行解码,

setDecoderPath 会自动请求 wasm 文件来进行解密操作。而这两个 wasm 文件同时也增加了请求时间和请求数量,那么加上这两个文件,真实的压缩率约为62.5%。

所以,如果一个项目需要加载多个 glTF 文件,那么可以创建一个 DRACOLoader 实例并重复使用它。但如果项目只需要加载一个 glTF 文件,那么使用 draco 算法是否具有“性价比”就值得考量了。

用 demo 进行一下性能对比:

可见 draco 算法首次加载和解密时间,要大于原文件。而在实际项目中,这个差距更加明显,并且偶尔会出现解密堵塞的情况,需要重新进入页面才能恢复功能。

除此以外,还有一个很直观的问题,模型画质的损失是肉眼可观的。

总而言之,如果要将 draco 压缩算法运用到大规模项目中,需要结合实际项目进行以下对比:

  • (1) 请求两个文件+解密耗时,与本身 glb 文件压缩后的体积大小相比,真实性能对比;
  • (2) 画质是否会出现设计师无法接受的损失。

KHR_mesh_quantization

顶点属性通常使用 FLOAT 类型存储,将原始始浮点值转换为16位或8位存储以适应统一的3D或2D网格,也就是我们所说的quantization向量化,该插件主要就是将其向量化。

例如,静态 PBR-ready 网格通常需要每个顶点 POSITION(12 字节)、TEXCOORD(8 字节)、NORMAL(12 字节)和 TANGENT(16 字节),总共 48 字节。通过此扩展,可以用于 SHORT 存储位置和纹理坐标数据(分别为 8 和 4 字节)以及 BYTE 存储法线和切线数据(各 4 字节),每个顶点总共 20 字节。

  • 压缩方式

可以使用 gltfpack 工具进行压缩

  • 使用方式(在 Three.js 中)

普普通通地用就好了,和不压缩的没什么区别

  • 性能对比

原文件3.2M,压缩后1.9M,为原文件的59.3%,比原模型加载速度也快上不少。

放到实际项目中,没有画质损失和加载时间过长的问题。

EXT_meshopt_compression

此插件假定缓冲区视图数据针对 GPU 效率进行了优化——使用量化并使用最佳数据顺序进行 GPU 渲染——并在 bufferView 数据之上提供一个压缩层。每个 bufferView 都是独立压缩的,这允许加载器最大程度地将数据直接解压缩到 GPU 存储中。

除了优化压缩率之外,压缩格式还具有两个特性——非常快速的解码(使用 WebAssembly SIMD,解码器在现代桌面硬件上以约 1 GB/秒的速度运行),以及与通用压缩兼容的字节存储。也就是说,不是尽可能地减少编码大小,而是以通用压缩器可以进一步压缩它的方式构建比特流。

  • 压缩方式

可以使用 gltfpack 工具进行压缩

  • 使用方式(在 Three.js 中)

  • 性能分析对比

原文件3.2M,压缩后1.1M,为原文件的65.6%,首次加载时间比原模型快上不少。

放到实际项目中,没有画质损失和加载时间过长的问题。

多个机型设备与优化对比结果

为了避免上文提到的“draco”压缩使得模型受损的情况,找了几台iPhone、安卓的手机来进行了一下性能与兼容的测试,让我们看一下结果。

iPhone 12(iOS 14.4)

Huawei Mate 40 pro(HarmonyOS)

Xiaomi Mix2(Android 8.0)

iPhone 6sp (iOS 13.7)

总结

可见,对于小部分需要使用模型的,并且只需要加载一个模型的业务,采用 KHR_mesh_quantization 或 EXT_meshopt_compression 进行网格压缩,再使用 gltf-pipeline 进行模块区分并对纹理图片压缩,是目前找到的较好的优化方案。

本文原文发布于2024年9月19日。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号