Skip to content

GLTFLoader: Implement support for KHR_meshopt_compression#32163

Merged
donmccurdy merged 3 commits intomrdoob:devfrom
zeux:khr-meshopt
Jan 2, 2026
Merged

GLTFLoader: Implement support for KHR_meshopt_compression#32163
donmccurdy merged 3 commits intomrdoob:devfrom
zeux:khr-meshopt

Conversation

@zeux
Copy link
Copy Markdown
Contributor

@zeux zeux commented Nov 1, 2025

Specification: KhronosGroup/glTF#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 added 2 commits August 26, 2025 10:08
This change brings in new features required for new glTF meshopt
extension, notably decoding v1 vertex/attribute blobs and color filter
support. The module is 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%)

While the increase is noticeable, the increase is close to typical CDN
response *headers* (~1 KB), and any reasonable glTF asset will see
higher gains from new compression so this should be worthwhile. If we
ever decide to shrink things further, it's possible to split the decoder
module as around 25% of the cost is supporting legacy browsers without
Wasm SIMD support; removing that would save ~2 KB for both gzip and
Brotli.
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.
@donmccurdy
Copy link
Copy Markdown
Collaborator

donmccurdy commented Nov 1, 2025

Thank you @zeux!

Support for WASM SIMD looks quite good...

... 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:

@zeux
Copy link
Copy Markdown
Contributor Author

zeux commented Nov 1, 2025

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 zeux marked this pull request as ready for review November 23, 2025 12:31
This updates meshopt_decoder.module.js to latest version from 1.0 that
will be released soon. The changes are minor in code size and behavior
relative to 0.25 update and this is just to ensure that we're using the
stable 1.0.
@zeux
Copy link
Copy Markdown
Contributor Author

zeux commented Dec 8, 2025

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 zeux changed the title GLTFLoader: Implement support for KHR_meshopt_compression draft GLTFLoader: Implement support for KHR_meshopt_compression Dec 8, 2025
@zeux
Copy link
Copy Markdown
Contributor Author

zeux commented Dec 15, 2025

Per KhronosGroup/glTF#2517 (comment) this extension is in "review draft" and so hopefully this PR can be reviewed now.

For testing, assets from this comment could be used: KhronosGroup/glTF#2517 (comment) (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
Copy link
Copy Markdown
Contributor Author

zeux commented Dec 20, 2025

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!

Copy link
Copy Markdown
Collaborator

@donmccurdy donmccurdy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @zeux! Changes look good to me. Given the "review draft" status, applicability and adoption of the EXT extension, and minimal added complexity of the implementation, I think we can merge support for KHR_meshopt_compression now.

@donmccurdy donmccurdy merged commit 16e912f into mrdoob:dev Jan 2, 2026
9 checks passed
@donmccurdy donmccurdy added this to the r183 milestone Jan 3, 2026
@zeux zeux deleted the khr-meshopt branch January 3, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants