Mesh optimization library that makes meshes smaller and faster to render
This release contains new algorithms and improvements to the meshoptimizer library, many gltfpack enhancements and JS library updates! Importantly, an experimental meshopt_simplifyWithAttributes
algorithm can take attribute information into account for better appearance, and gltfpack now copies texture files to the output folder when the output format is .gltf
(which can be disabled via -tr
option).
Note that attribute-aware simplification is still in development, and there are some known issues with attribute weighting, discontinuities and geometry preservation, so the interface and behavior is subject to change in future releases. Issue https://github.com/zeux/meshoptimizer/issues/158 can be tracked for development progress.
meshopt_encodeIndexBuffer
and meshopt_encodeIndexSequence
has been updated to 1. Version 1 has been supported since meshoptimizer 0.14 and is the version that is part of glTF EXT_meshopt_compression
extension; if legacy version 0 is needed, this can be overridden via meshopt_encodeIndexVersion
.meshopt_simplifyWithAttributes
algorithm that takes attribute error into account when running simplification at some cost to geometric error and simplification memory and performancemeshopt_dequantizeHalf
which can reverse the quantization done by meshopt_quantizeHalf
for cases when the data is needed on the CPUmeshopt_simplify
now requires ~25% less memory for large meshesmeshopt_optimizeVertexCache
is now ~15% faster for large meshesmeshopt_simplifyPoints
now consumes less memory and supports per-point colors during simplification; the algorithm is still experimental but will likely be stabilized in a future release. The interface has changed to accommodate optional color attribute input.meshopt_simplify
now prevents triangle flipping better in planar regions (although some issues remain, tracked in https://github.com/zeux/meshoptimizer/issues/346)meshopt_remapVertexBuffer
is now up to 4x faster for deinterleaved streams with small stridemeshopt_spatialSortRemap
is no longer experimental (which means it has a stable API like most other functions).gltf
files, gltfpack now copies texture files to the output folder. This can be changed by using the new -tr
option (which also allows to keep texture file references when targeting .glb
files).KHR_materials_anisotropy
extension_ID
, _BATCHID
and _FEATURE_ID_n
)-mi
) transform handling for scenes with non-uniform scale & rotation-mi
) efficiency on some CAD exports by relaxing mesh merging rules-vtf
; this is occasionally useful on scenes with very large texture tiling factors.obj
file parsing: vertex colors are now preserved and more data from .mtl
materials is preservedreorderPoints
function to MeshoptEncoder; this function is recommended for use with point clouds to reduce data size and improve render localityuseWorkers
behavior: calling the function twice no longer leaks workers, and useWorkers(0)
can be used to reclaim WebAssembly instance memorysimplifyPoints
and simplifyWithAttributes
functions to MeshoptSimplifier; these functions may change interface/implementation significantly in future releases and require setting useExperimentalFeatures
to true
.Thanks to @LorenRoosendaal, @1d10t and @Light7734 for contributions to this release!
This release contains several meshoptimizer and gltfpack fixes/improvements as well as tweaks for the JavaScript library. Notably, -vpf
mode in gltfpack can simplify integration into applications that are very sensitive to the scene graph structure as it allows to preserve it better than the default quantization mode does without resorting to disabling quantization entirely.
meshopt_decodeVertexBuffer
performance by 5-10% for Intel/AMD and 15-25% for ARMmeshopt_buildMeshlets
which results in ~2% fewer meshlets with ~5% smaller radius on averagemeshopt_encodeFilterExp
performance by ~3x and make the encoder more flexible with the new mode
parameter-vpf
) which removes the need for dequantization transforms at some cost to geometry size-slb
which can fix gaps between different meshes-vpf
or -noq
, meshes will usually be attached directly to their source nodes without new intermediate nodesMeshoptDecoder.useWorkers
)Thanks to @donmccurdy, @LilyWangLL, @daemyung, @DavidKorczynski, @rafern, @Kuranes and @mosra for contributions to this release!
This release contains several gltfpack fixes/improvements as well as small improvements to the simplifier, and support for simplifier in the JavaScript library.
Importantly, gltfpack now uses basis_universal as a library to implement ETC1S and UASTC texture compression. This means that external executables like basisu
/toktx
are no longer necessary, and compression of complex scenes is much faster due to support for parallel compression using optimized job pool to maximize resource allocation, but it also means that node.js version of gltfpack
can no longer compress textures - native gltfpack
binary should be used instead.
meshopt_simplify
that can be used to specify meshopt_SimplifyLockBorder
option; this option is useful when multiple chunks of a single mesh are simplified independently, as it makes sure the simplified versions will connect without gapsMESHOPTIMIZER_ALLOC_CALLCONV
build setting (fixes #403)mesh_simplifier
module-tj
that can override the degree of parallelism used during texture compression-tl
that can limit the texture width/height during texture compression-tc
option which allows to only compress some textures as ETC1S-vpn
command line optionThis release contains several gltfpack fixes/improvements as well as small tweaks to the core library, and a new JavaScript package, meshoptimizer.
meshopt_encodeFilter*
functions that encode floating point data in a format that can be decoded using decode filters; this can be used together with vertex codec and is mostly designed to support EXT_meshopt_compression
glTF extension.-tfy
) when using texture compression-tu normal
now enables UASTC only for normal maps)KHR_lights_punctual
extensionKHR_materials_volume
extension is usedTo facilitate integration of meshoptimizer compression into web applications, several algorithms that the library provides, specifically mesh reordering, vertex/index compression as well as attribute filters, are now provided as a standalone JS package available through NPM, meshoptimizer.
The package provides meshopt_decoder
module that can be used to decompress meshes, and meshopt_encoder
module that can be used to optimize and compress meshes. Both modules are particularly important for applications that work with EXT_meshopt_compression glTF extension.
Note that these JS modules are low-level and are intended to be used in content pipeline tools (like glTF-Transform) or renderers (like three.js or Babylon.js); it's comparatively rare that these would be useful to integrate directly into a web application as opposed to a high-level library dependency.
This release features many library changes including a few new algorithms and substantial improvements in existing algorithms, notably making mesh simplification and clusterization better, as well as gltfpack fixes and improvements.
meshopt_simplify
now has an extra output parameter, result_error
, which will contain the relative simplification error (which can be converted to absolute with meshopt_simplifyScale
)meshopt_simplifySloppy
interface has changed to align with meshopt_simplify
: the function now expects a larger output index buffer size and accepts an input error that restricts simpification as well as an output error.meshopt_simplify
now tries to avoid simplifications that result in triangle flips; this substantially improves triangulation quality at a moderate performance cost.meshopt_buildMeshlets
interface has changed to allow for almost arbitrary meshlet vertex/triangle limits by outputting three separate arrays of meshlet data instead of one; the resulting layout is also more compact and is often more GPU-friendly.meshopt_buildMeshlets
now implements a new, more expensive algorithm that generates meshlets that are optimized for a balance of vertex reuse, spatial coherency and cone culling efficiency, controlled with an extra cone_weight
parameter. The old linear-time algorithm is still available as meshopt_buildMeshletsScan
.meshopt_generateTessellationIndexBuffer
, that can be used to generate a special index buffer that, together with hardware tessellation stage, can efficiently implement crack-free PN-AEN tessellation for arbitrary meshes.meshopt_decodeVertexBuffer
, making it ~5% fastermeshopt_decodeFilter*
) when vertex count wasn't aligned by 4meshopt_decodeIndexBuffer
This release focuses on gltfpack improvements and also features small improvements to simplifier to improve quality for some edge cases.
gltfpack improves support for instanced meshes substantially in this release. While previously all instances of the same mesh would be merged together unconditionally which could result in large file sizes and/or memory consumption, by default the instances are kept as is now; -mm
can be used to merge the geometry of the instances together, or alternatively -mi
can be used to encode the instance data using EXT_mesh_gpu_instancing
which, given a compatible loader, can significantly reduce the transmission size and improve loading and rendering performance.
To improve support for large scenes even further, gltfpack is now much more memory efficient, requiring ~40% less memory for processing on average.
The extension that's used by gltfpack to compress geometry, animation and instance data, is now part of glTF and is called EXT_meshopt_compression
; gltfpack was changed accordingly to output compressed files conforming the up-to-date specification. This requires loaders to update to the new extension; https://github.com/zeux/meshoptimizer/tree/master/js contains plugins for three.js and Babylon.js and work is underway to integrate these directly upstream.
For texture compression, gltfpack is switching to toktx
from KTX-Software; this enables support for super-compressed UASTC textures and support for texture scaling during encoding (via -ts
option) which can further reduce the file size. Additionally when using toktx
, gltfpack now pads the textures to a multiple of 4 to ensure compatibility with WebGL, and can optionally (via -tp
option) pad to a power of 2 for older browsers. basisu
command-line tool is still supported for now and automatically used if toktx
is not available.
Finally, gltfpack is now available as a JS library in addition to having command-line executables; the library uses a filesystem-like interface. Please refer to gltf/library.js
for documentation on the two exposed functions.
-mm
is now required to merge these instances togetherEXT_mesh_gpu_instancing
via -mi
command line option-km
can now be used to keep unused materials-ke
now keeps extras
on nodes in addition to materialsbasisu
or toktx
are availableKHR_materials_transmission
, KHR_materials_ior
, KHR_materials_specular
and KHR_materials_sheen
toktx
when compressing textures-ts
that can be used to rescale textures to reduce transmission and memory size-tq
now accepts a level from 1 to 10, which is tuned to balance compression ratio vs quality for both ETC1S and UASTC-tp
that can be used to rescale images to power-of-two when using texture compression-tb
in favor of -tc
; the latter uses KHR_texture_basisu
which should be more widely supported-te
; textures are now automatically embedded into .glb
files-r
option which contains various stats about the resulting glTF scene-vc
optionmeshopt_simplify
edge analysis to track edge loops more carefully; this fixes simplification for some cases where an open border would previously get collapsed incorrectlymeshopt_decoder.js
by 40% before gzip and 5% after gzipmeshopt_decoder.js
now has an ES6-friendly variant, meshopt_decoder.module.js
, that can be imported.This release features several new algorithms, mainly aimed at improving the geometry compression, as well as many gltfpack changes with the same goal.
meshopt_optimizeVertexCacheStrip
optimizes triangle lists for vertex cache, favoring long triangle strips over vertex transform efficiency. This function is recommended to use as a replacement for meshopt_optimizeVertexCache
when reducing the compressed geometry size is more valuable than reducing vertex transform cost, or when using meshopt_stripify
to produce shorter triangle strip sequences.meshopt_encodeIndexBuffer
now supports the new strip-optimized order better; this required some bitstream changes that can be enabled with meshopt_encodeIndexVersion(1)
. Version 1 will become the default encoding version in a later release.meshopt_encodeIndexSequence
can be used to compress index buffer data that doesn't represent triangle lists; the encoding is recommended for triangle strip or line lists, but can work with any index sequence (it's less efficient than meshopt_encodeIndexBuffer
at compressing triangle lists)When compressing geometry, using meshopt_optimizeVertexCacheStrip
and meshopt_encodeIndexVersion(1)
is recommended to minimize the distribution size of the resulting meshes; this can make the encoded data ~10% smaller before gzip/zstd compression and up to 20% smaller after gzip/zstd.
Additionally, a set of vertex filters (meshopt_decodeFilterOct
, meshopt_decodeFilterQuat
, meshopt_decodeFilterExp
) was added to support MESHOPT_compression
glTF extension; these are not as useful outside of glTF, and are described in detail in the extension draft. Cumulatively these can substantially reduce the geometry and animation data in glTF files compressed using the extension.
gltfpack incorporates the new algorithms and filters to substantially improve the compression ratios for geometry and animation data. For example, Corset
model from glTF-Sample-Models repository is 20% smaller, BrainStem
model from the same repository is 30% smaller. Most of the changes currently require using a higher compression mode, activated via -cc
command-line option; in a future release -cc
may replace -c
.
The texture compression support was updated to incorporate latest changes in KTX2 / KHR_texture_basisu specification; additionally, gltfpack now supports Basis UASTC encoding via -tu
flag. Note that since gltfpack doesn't support UASTC RDO yet, the UASTC compressed files will be much larger (but much higher quality) compared to ETC1S encoded files.
For easier distribution, gltfpack is now available as an npm package.
KHR_materials_clearcoat
extensionextras
data on material instances when -ke
flag is used-at
, -ar
, -as
)-noq
option that can be used to disable quantization (resulting in much larger files)meshopt_decodeVertexBuffer
now automatically enables SSSE3 SIMD implementation for clang/gcc using __cpuid
-based runtime detection without the need to use extra compile flagsmeshopt_encodeVertexBuffer
now works correctly on empty inputs (count = 0
)MESHOPT_
(note: this breaks shared library builds, fixed in https://github.com/zeux/meshoptimizer/pull/129)This release has several new algorithms, SIMD improvements for vertex codec and a lot of gltfpack changes including Basis support.
meshopt_simplifyPoints
can be used to simplify point clouds. The algorithm is a variant of sloppy simplifier, which means it's fast and not attribute-aware (for now).meshopt_spatialSortRemap
and meshopt_spatialSortTriangles
can be used to reorder vertices or triangles to increase spatial locality. This is helpful when working with point clouds and triangle meshes with redundant connectivity, and can improve clusterization results.meshopt_decodeVertexBuffer
now has an experimental AVX512 implementation, which is ~10% faster than SSSE3 implementation (it uses 128b vectors and as such carries no extra power cost). It requires AVX512-VBMI2 and AVX512-VL (available on Ice Lake CPUs).meshopt_decodeVertexBuffer
now has an experimental WebAssembly SIMD implementation, which is ~3x faster than scalar implementation. It requires a compatible WebAssembly implementation with SIMD enabled (Chrome Canary was used for testing).meshopt_setAllocators
; previously, allocations from meshopt_IndexAdapter
were using global operator new/delete.This change includes a lot of work on extension specification. As a result, MESHOPT_quantized_geometry extension that was being used before got replaced with a new KHR_mesh_quantization extension (extension PR), and the details of MESHOPT_compression extension have changed substantially to allow for fallback data (extension PR), requiring updates to GLTF loaders. Both three.js (r111) and Babylon.JS (4.1) can be used to load these files, with a custom demo/GLTFLoader.js
for three.js and an extension demo/babylon.MESHOPT_compression.js
for Babylon.JS.
As a result, gltfpack-produced files now validate cleanly with the most recent glTF validator build (2.0.0-dev.3.0 (November 2019)).
gltfpack also now supports Basis Universal texture supercompression. Encoding files with these textures requires basisu
executable which can be built from the official repository. Two container format options are provided:
.basis
- native container format for Basis; this is supported by three.js and Babylon.JS today, but is likely to be removed in the future because this is not compatible with glTF specification.ktx
- KTX2 container format from Khronos that supports Basis supercompression; this is not supported by any renderer at the time of this writing, but this is the route that is being specified (spec PR).In addition, there were a lot of changes aimed at increasing efficiency and extending feature support, with the full list below.
MESHOPT_compression
specification, requires updating JSON loaders (GLTFLoader.js)-cf
command line option to support compressed data fallback; files produced with this option don't require MESHOPT_compression
extension, but loaders that support it will not need to load uncompressed data-si R
and -sa
flags that simplify the meshes using default/aggressive (sloppy) simplification-vu
to get better compression by using unnormalized normals/tangents.-tb
to compress textures using basisu
into .basis
container; -tc
to compress textures using KTX2 container which requires extra extensions and isn't supported by renderers yet)-te
flag)extra.targetNames
JSON arrayThis release contains a few improvements for various algorithms, introduces support for triangle strips with degenerate triangles and adds gltfpack (alpha).
Interface changes:
meshopt_stripify
and meshopt_unstripify
now require an extra argument, restart_index
Improvements:
meshopt_simplifySloppy
performance by up to 10% by using three-point interpolation searchmeshopt_optimizeVertexCache
by up to 0.5% by using a new data set obtained with differential evolutionmeshopt_stripify
now supports stitching strips using degenerate triangles instead of restart indices; this typically results in a 10% larger index buffer compared to restart indices, but on some GPUs it can be substantially faster to rendergltfpack:
This release introduces an alpha vesion of gltfpack. gltfpack is a command-line tool that converts .obj or .gltf files to glTF files that are optimized for render performance and transmission time. gltfpack merges meshes and materials to reduce draw call count, merges buffers to reduce draw setup cost, quantizes vertex attributes to reduce GPU memory footprint, optimizes vertex and index data for more efficient GPU rendering, resamples and quantizes animation data to reduce memory footprint, and can optionally compress the vertex/index/animation buffers in the output using meshoptimizer codecs to further reduce the file size.
The resulting files rely on two not-yet-standardized extensions; when compression is not used, the resulting files can be loaded using three.js (r107+) and Babylon.js (4.1+) glTF loaders. Loading compressed files requires integrating JavaScript decoders (js/meshopt_decoder.js
); demo/GLTFLoader.js
contains a custom version of three.js loader that can be used to load them.
This release contains a few improvements for simplifier, introduces a new simplification algorithm, adds support for custom allocators and improves performance and code size of JavaScript decoders.
Interface changes:
meshopt_computeMeshletBounds
now passes meshlet
parameter by pointer instead of by value.New algorithms:
meshopt_simplifySloppy
, that performs decimation without concerns for topological integrity. The algorithm can and will merge small disjoint features together, and is extremely fast at ~20M triangles/sec on large meshes on modern desktop CPUs.meshopt_setAllocator
.Improvements:
target_error
parameter - it now corresponds to linear error, normalized to mesh radius (0.01 means 1% deviation).decoder.js
is now 2.4x smaller (3.5 KB after gzip)Compatibility:
decoder.js
.