three.js icon indicating copy to clipboard operation
three.js copied to clipboard

GLTFLoader: Implement support for KHR_meshopt_compression

Open zeux opened this issue 2 months ago • 3 comments

Specification: https://github.com/KhronosGroup/glTF/pull/2517

Since the extension uses the exact same JSON structure as EXT variant, and meshopt decoder automatically decodes v1 attribute blobs and automatically picks up color filters through filter name, the only thing we need to do is to register the extension code twice for two different names.

To decode new v1 vertex streams and color filters, meshopt_decoder needs to be updated to v0.25; the updated module is of course fully compatible with all prior encoded data.

When using gzip/Brotli compression, the .js file got 1.5 KB larger:

  • gzip, before: 6432 bytes
  • gzip, after: 8051 bytes (+25%)
  • Brotli, before: 5754 bytes
  • Brotli, after: 7203 bytes (+25%)

This increase is significant on a relative basis, but given that CDN response headers often approach 1 KB, it's perhaps reasonable in absolute terms. If this becomes a problem in the future, it is possible to shrink the file in various ways, for example removing support for pre-SIMD Wasm engines would remove 2 KB post-gzip.

zeux avatar Nov 01 '25 02:11 zeux

Thank you @zeux!

Support for WASM SIMD looks quite good...

  • https://webassembly.org/features/
  • https://caniuse.com/wasm-simd

... assuming support depends only on the runtime/browser, and not the device/CPU? If that's the case, then I think dropping non-SIMD support would be reasonable. But for three.js' purposes, the Meshopt decoder is already much smaller than Draco or Basis decoders, so I'm not complaining about +1.5 kb here. :)

It'd be nice to have the draft at "Review Draft" or "Release Candidate" status before we merge, but open to other suggestions as well.

Work in progress for glTF Transform:

  • https://github.com/donmccurdy/glTF-Transform/pull/1745

donmccurdy avatar Nov 01 '25 15:11 donmccurdy

support depends only on the runtime/browser, and not the device/CPU

There is some dependency on CPU features too - I'm not sure caniuse report incorporates this. I would not expect this to notably affect the usage percentage. Regardless, this is more of a possibility in the future; I agree that for now the increase seems fine relative to other projects, it's just visible when looking at it relative to the older size :)

Agreed wrt extension status, I posted this PR a draft for awareness + to move the extension along (hopefully existence of draft implementations encourages extension review progress!).

zeux avatar Nov 01 '25 16:11 zeux

I've updated the PR with the 1.0 version of the decoder module; it's more or less the same in terms of size as the original comments indicate (+-20 bytes post deflate); the update is not essential but it's nice to depend on the latest stable release.

zeux avatar Dec 08 '25 17:12 zeux

Per https://github.com/KhronosGroup/glTF/pull/2517#issuecomment-3657759361 this extension is in "review draft" and so hopefully this PR can be reviewed now.

For testing, assets from this comment could be used: https://github.com/KhronosGroup/glTF/pull/2517#issuecomment-3440081285 (glTF-Sample-Assets will get test assets in the future). gltfpack 1.0 also supports this extension via -cz command line argument and could be used for testing on arbitrary glTF files, including re-compressing the asset used in existing three.js sample for glTF compression.

Here's a synthetic cube grid asset that uses various combinations of modes too, and should look approximately like this:

image

zeux avatar Dec 15 '25 22:12 zeux

For completeness, here's an updated version of the asset used by three.js 'webgl_loader_gltf_compressed' example; it can be copied to examples/models/gltf/ folder to test this PR as well. (it seems better to keep this PR focused on the extension support and do that in a separate PR)

coffeemat.zip

@donmccurdy Please let me know if you have any comments!

zeux avatar Dec 20 '25 05:12 zeux