GLTF压缩的技术方法
gltf-transform、gltfpack和gltf-pipeline都是用于处理glTF文件的工具库,但它们在功能和使用上有一些不同之处。下面是它们的纵向对比:
1、gltf-transform:
功能:gltf-transform是一个功能强大的glTF处理库,它提供了对glTF文件进行灵活、高级编辑和优化的功能。它支持修改glTF的结构、添加自定义扩展、处理节点层次结构、更改材质、优化缓冲数据、添加、删除和替换属性等。
优点:提供了高级编辑和优化功能,非常适合需要进行复杂处理和定制化操作的场景。
缺点:功能相对较复杂,需要一定的学习成本。
使用 glTF-Transform 压缩为 KTX
安装完所有内容后,您现在可以压缩 glTF 文件。有不同的压缩选项可用;这里有一些可以帮助您入门的方法。
方法一:UASTC + ETC1S
使用 UASTC 压缩法线和遮挡/粗糙度/金属度 (ORM) 纹理,使用 ETC1S 压缩所有其他纹理:
gltf-transform uastc input.glb output1.glb --level 4 --rdo 4 --slots "{normalTexture,occlusionTexture,metallicRoughnessTexture}" --zstd 18 --verbose
gltf-transform etc1s output1.glb output2.glb --quality 255 --verbose
gltf-transform
是工具本身。uastc
是压缩方法。这比 etc1 压缩得更少,但往往会产生更少的块状伪影。与 ETC1S 相比,它在具有不相关 RGB 值的纹理(例如 ORM 贴图)上产生的伪像更少。input.glb
是您要压缩的文件,其中包含 PNG 和/或 JPEG 纹理。重命名它以匹配正在压缩的任何文件。output1.glb
是要保存的临时文件,带有新的 KTX 纹理。上面代码块中的第一步将使用 UASTC 仅压缩法线凹凸和遮挡粗糙金属纹理,其余部分保持原始格式。然后第二步将使用 ETC1S 压缩剩余的纹理。--level 4
是一个高品质的环境。它产生可达到的最高质量,但速度可能非常慢。如果太慢,请尝试 3。--rdo 4
是中等质量设置,但会生成较小的文件。完整范围为 [.001, 10.0]。较低的值会产生较高质量/较大的 LZ 压缩文件,较高的值会产生较低质量/较小的 LZ 压缩文件。一个不错的尝试范围是 [.25, 10]。对于法线贴图,尝试范围为 [.25, .75]。--slots
允许您使用以下设置包含或排除纹理类型:"{normalTexture,occlusionTexture,metallicRoughnessTexture}"
告诉 glTF Transform 使用 UASTC 仅压缩普通纹理和 ORM 纹理。要查看 GLB 中的纹理槽列表,请使用命令gltf-transform inspect input.glb
这将显示每个纹理的尺寸和文件大小。这对于识别名称特别有用,--slots
因此您可以将不同的压缩设置应用于不同的纹理类型。--zstd 18
应用超级压缩。压缩级别范围为[1, 22],默认18,0为不压缩。值越低速度越快,但压缩程度越低。应谨慎使用 20 以上的值,因为它们需要更多内存。--verbose
逐步显示 glTF Transform 正在做什么。在 Windows 上,压缩期间没有进度指示器,只有闪烁的光标。--verbose
作为进度条很有用,可确保其正常工作,并帮助您确定是否包含了正确的选项。output1.glb
是上面代码块第一步的输出,现在在第二步中使用 ETC1S 压缩其余纹理。output2.glb
第二步是最终的完全压缩模型,所有纹理均为 KTX 格式。将其重命名为所需的任何输出名称。--quality 255
第二步告诉 glTF-Transform 对 ETC1S 使用最高质量,但它应用较少的压缩,并且压缩文件需要更长的时间。当质量比转换速度更重要时使用此选项。
请注意,这是两个单独的命令。第一个命令仅使用 UASTC 压缩法线和 ORM 映射。然后第二个命令使用 ETC1S 压缩所有剩余的纹理。仅在第一个命令完成后才启动第二个命令。第二个命令不需要--slots "!{normalTexture,occlusionTexture,metallicRoughnessTexture}"
参数来省略法线/ORM 映射,因为 glTF-Transform 不会重新压缩现有的 KTX 文件。它仅压缩非 KTX 纹理。
2、gltfpack:
功能:gltfpack是一个专注于减小glTF文件大小的工具,主要通过压缩纹理和几何信息来实现。它支持使用Draco压缩几何信息,将纹理转换为KTX格式,并进行大小调整等。
优点:简单易用,专注于文件大小优化,适合快速优化glTF文件。
缺点:功能相对较为单一,只适合文件大小优化,不提供其他高级编辑功能。
用法
KHR_mesh_quantization`和`EXT_meshopt_compression`可以使用同一个工具`gltfpack > npm i -g gltfpack # gltfpack命令行工具是C项目构建出WASM执行的,目测未来会有更多wasm这类项目产出 # KHR的优化版的basis trancoder是使用assemblyscript编译成wasm # 转成KHR_mesh_quantization > gltfpack -i model.glb -o out.glb # EXT_meshopt_compression只需加个-cc参数即可 > gltfpack -i model.glb -o out.glb -cc
默认情况下,gltfpack 在优化场景时会做出某些假设,例如,属于非动画节点的网格可以合并在一起,并且有一些默认值代表精度和大小之间的权衡,这些默认值适合大多数用例。但是,在某些情况下,生成的
.gltf
文件需要保留某种方式供应用程序操作各个场景元素,而在其他情况下,优化精度或大小更为重要。gltfpack 有一组丰富的命令行选项来控制其行为的各个方面,完整列表可通过gltfpack -h
.经常使用以下设置来减少生成的数据大小:
-cc
:生成压缩的 gltf/glb 文件(需要EXT_meshopt_compression
)-tc
:使用 BasisU 超级压缩将所有纹理转换为 KTX2(需要KHR_texture_basisu
并且可能需要-tp
标志以与 WebGL 1 兼容)-mi
:在序列化对相同网格的引用时使用网格实例(需要EXT_mesh_gpu_instancing
)-si R
:以三角形计数比率 R 简化网格(默认值:1;R 应介于 0 和 1 之间)
以下设置经常用于限制某些优化:
-kn
:保持命名节点和网格附加到命名节点,以便命名节点可以在外部进行转换-km
:保留命名材质并禁用命名材质合并-ke
:保留额外数据-vpf
:使用浮点位置量化而不是默认的定点(这会导致更大的位置数据,但不会插入具有反量化变换的新节点;使用此选项时,也建议-cc
)
代码如下:
import { MeshoptDecoder } from './meshopt_decoder.module.js'; var loader = new GLTFLoader(); loader.setMeshoptDecoder(MeshoptDecoder); loader.load('pirate.glb', function (gltf) { scene.add(gltf.scene); }); const ktx2Loader = new KTX2Loader () // .setTranscoderPath('js/libs/basis/') .setTranscoderPath ('node_modules/three/examples/js/libs/basis/') .detectSupport (_this.renderer ); // const loader = new GLTFLoader().setPath('./public/three/models/gltf/cc_tc/'); const loader = new GLTFLoader (); loader.setKTX2Loader (ktx2Loader );
3、gltf-pipeline:
- 功能:gltf-pipeline是一个综合性的glTF处理工具库,提供了一系列方法用于处理glTF文件,包括优化、拆分、合并、纹理压缩、处理模型等。
- 优点:功能比较全面,可以进行优化、压缩、拆分、合并等多种处理操作。
- 缺点:在某些复杂的场景中,可能没有gltf-transform提供的高级编辑能力。
综合来看,如果你需要对glTF文件进行复杂的编辑和定制化处理,gltf-transform是一个不错的选择。如果你只关注文件大小的优化,gltfpack提供了简单高效的方法。而gltf-pipeline提供了综合性的功能,是一个比较全面的处理工具库,适合在多种场景下使用。根据具体的需求和应用场景,选择合适的工具库进行处理会更加有效和方便