EXTMeshoptCompression

EXT_meshopt_compression provides compression and fast decoding for geometry, morph targets, and animations.

Meshopt compression (based on the meshoptimizer library) offers a lightweight decoder with very fast runtime decompression, and is appropriate for models of any size. Meshopt can reduce the transmission sizes of geometry, morph targets, animation, and other numeric data stored in buffer views. When textures are large, other complementary compression methods should be used as well.

For the full benefits of meshopt compression, apply gzip, brotli, or another lossless compression method to the resulting .glb, .gltf, or .bin files. Meshopt specifically pre-optimizes assets for this purpose — without this secondary compression, the size reduction is considerably less.

Be aware that decompression happens before uploading to the GPU. While Meshopt decoding is considerably faster than Draco decoding, neither compression method will improve runtime performance directly. To improve framerate, you'll need to simplify the geometry by reducing vertex count or draw calls — not just compress it. Finally, be aware that Meshopt compression is lossy: repeatedly compressing and decompressing a model in a pipeline will lose precision, so compression should generally be the last stage of an art workflow, and uncompressed original files should be kept.

The meshoptimizer library (github, npm) is a required dependency for reading or writing files, and must be provided by the application. Compression may alternatively be applied with the gltfpack tool.

Example

import { NodeIO } from '@gltf-transform/core';
import { reorder, quantize } from '@gltf-transform/functions';
import { EXTMeshoptCompression } from '@gltf-transform/extensions';
import { MeshoptDecoder, MeshoptEncoder } from 'meshoptimizer';

await MeshoptDecoder.ready;
await MeshoptEncoder.ready;

const io = new NodeIO()
.registerExtensions([EXTMeshoptCompression])
.registerDependencies({
    'meshopt.decoder': MeshoptDecoder,
    'meshopt.encoder': MeshoptEncoder,
});

// Read and decode.
const document = await io.read('compressed.glb');

// Write and encode. (Medium, -c)
await document.transform(
    reorder({encoder: MeshoptEncoder}),
    quantize()
);
document.createExtension(EXTMeshoptCompression)
    .setRequired(true)
    .setEncoderOptions({ method: EXTMeshoptCompression.EncoderMethod.QUANTIZE });
await io.write('compressed-medium.glb', document);

// Write and encode. (High, -cc)
await document.transform(
    reorder({encoder: MeshoptEncoder}),
    quantize({pattern: /^(POSITION|TEXCOORD|JOINTS|WEIGHTS)(_\d+)?$/}),
);
document.createExtension(EXTMeshoptCompression)
    .setRequired(true)
    .setEncoderOptions({ method: EXTMeshoptCompression.EncoderMethod.FILTER });
await io.write('compressed-high.glb', document);

Hierarchy

Static properties

EncoderMethod: unknown
EXTENSION_NAME: "EXT_meshopt_compression"

Properties

extensionName: "EXT_meshopt_compression"

Methods

  • dispose(): void
  • Configures Meshopt options for quality/compression tuning. The two methods rely on different pre-processing before compression, and should be compared on the basis of (a) quality/loss and (b) final asset size after also applying a lossless compression such as gzip or brotli.

    • QUANTIZE: Default. Pre-process with quantize() (lossy to specified precision) before applying lossless Meshopt compression. Offers a considerable compression ratio with or without further supercompression. Equivalent to gltfpack -c.
    • FILTER: Pre-process with lossy filters to improve compression, before applying lossless Meshopt compression. While output may initially be larger than with the QUANTIZE method, this method will benefit more from supercompression (e.g. gzip or brotli). Equivalent to gltfpack -cc.

    Output with the FILTER method will generally be smaller after supercompression (e.g. gzip or brotli) is applied, but may be larger than QUANTIZE output without it. Decoding is very fast with both methods.

    Example:

    import { EXTMeshoptCompression } from '@gltf-transform/extensions';
    
    doc.createExtension(EXTMeshoptCompression)
        .setRequired(true)
        .setEncoderOptions({
            method: EXTMeshoptCompression.EncoderMethod.QUANTIZE
        });
    
  • isRequired(): boolean
  • Indicates to the client whether it is OK to load the asset when this extension is not recognized. Optional extensions are generally preferred, if there is not a good reason to require a client to completely fail when an extension isn't known.

  • listProperties(): ExtensionProperty[]
  • Indicates to the client whether it is OK to load the asset when this extension is not recognized. Optional extensions are generally preferred, if there is not a good reason to require a client to completely fail when an extension isn't known.

Function symbol, where the argument and output are a box labeled 'glTF'.

Made by Don McCurdy. Documentation built with greendoc and published under Creative Commons Attribution 3.0.