v2.21.0
leptos-rs/leptosv2.21.0Jul 21, 2026by mvaligursky
AI Summary
A major engine update introducing Gaussian Splatting support, physics backend decoupling, extensive XR improvements, and performance optimizations for rendering and asset handling.
Key Highlights
- Add support for KHR_gaussian_splatting glTF extension and SPZ format
- Decouple physics into a backend abstraction (Ammo and Null implementations)
- Add volumetric fog rendering to CameraFrame
- Add XrManipulation script for two-hand drag, rotate, and scale in XR scenes
Breaking Changes
- Remove MeshInstance parameter pass flags
- Rename gsplat script classes to match core GSplat casing
New Features
- GSplat glass refraction and tree wind examples
- Volumetric fog rendering
- Instanced wide line renderer
- KTX2 cubemap support
- Physics backend abstraction (Ammo/Null)
- XrManipulation script
- Texture.copy API
- CircleGeometry procedural geometry
- Pen input support in touch sources
- Filtered subscription APIs for checkpoints, transactions, and events
Full Release Notes
## Breaking Changes * [BREAKING] Remove `MeshInstance` parameter pass flags by @mvaligursky in #9071 * [BREAKING] Rename gsplat script classes to match core `GSplat` casing by @willeastcott in #9040 ## Changes * Add instanced wide line renderer by @mvaligursky in #9090 * Add volumetric fog rendering to `CameraFrame` by @mvaligursky in #9069 * Support KTX2 cubemaps by @MotivaCG in #9065 * Add support for `KHR_gaussian_splatting` glTF extension by @mvaligursky in #9015 * Add SPZ gaussian splat format support via external parser by @mvaligursky in #9018 * Re-add `Camera.beforePasses` extension point by @mvaligursky in #9073 * Decouple physics into a backend abstraction with Ammo and Null implementations by @willeastcott in #9043 * Move simulation registration onto the rigid body system by @willeastcott in #9044 * Flatten collision type implementations into a dispatch table by @willeastcott in #9045 * Add `XrManipulation` script: two-hand drag, rotate and scale for XR scenes by @willeastcott in #9030 * Upgrade `XrNavigation` teleport visuals to ballistic arc with ring indicator by @willeastcott in #9024 * Refactor XR scripts: dedupe within-file logic and align naming by @willeastcott in #9032 * Move XR scripts into `scripts/esm/xr` folder by @willeastcott in #9038 * Add Engine Scripts API reference for `scripts/esm` by @willeastcott in #9042 * Add pluggable parser registry to `ResourceHandler` and convert built-in handlers by @mvaligursky in #9001 * Convert `MaterialHandler`, audio, anim and template handlers to the parser registry by @mvaligursky in #9004 #9005 #9006 * Extract glTF extensions from the glb parser into separate modules by @mvaligursky in #9007 #9008 * Convert the obj model parser to an ES module in `scripts/esm/parsers` by @mvaligursky in #9019 * Add `withCredentials` option for asset loading by @mvaligursky in #8983 * Add `Texture.copy` for texture-to-texture copies by @mvaligursky in #8970 * Add `CircleGeometry` procedural geometry class by @mvaligursky in #9027 * Add clear/remove API to `Curve` and `CurveSet` by @mvaligursky in #8980 * Add unclamped scalar interpolation by @mvaligursky in #9087 * Add request/execute mesh-instance culling by @mvaligursky in #8978 * Allow `Texture#mipmaps` to be changed at runtime on WebGPU by @mvaligursky in #9003 * Use uniform buffers for view-level uniforms on WebGL2 by @mvaligursky in #8987 * Route view uniforms through dynamic buffers; remove view bind groups by @mvaligursky in #8967 * Make `StorageBuffer.read` public by @mvaligursky in #8986 * Add public `app` getter to `ResourceHandler`, mark `_app` protected by @mvaligursky in #8991 * Support pen input in touch sources by @d0rianb in #9013 * Skip WebXR startup probe when `xr-spatial-tracking` is disallowed by @mvaligursky in #8964 * Warn about unknown options passed to `addComponent` by @mvaligursky in #8995 * Load MSDF font atlases without mipmaps by @mvaligursky in #9002 * Refactor `OutlineRenderer` to use dedicated shader output by @mvaligursky in #9070 * Refactor light and directional-shadow culling into separate phases by @mvaligursky in #8961 * Rework shadow update-mode lifecycle; keep THISFRAME pending until rendered by @mvaligursky in #8962 * Build the frame graph before mesh and shadow-caster culling by @mvaligursky in #8965 * Allocate local light shadow maps before the frame graph is built by @mvaligursky in #8966 * Decouple `RenderPassForward` from `RenderAction` via `LayerRenderStep` by @mvaligursky in #8975 * Extract visibility culling into a `Culler` class by @mvaligursky in #8979 * Use `Debug.removed` for nonfunctional compatibility shims by @mvaligursky in #9082 * Recommend `EventHandle.off()` for event removal by @mvaligursky in #8974 * Exclude `@ignore` typedefs from generated API docs by @mvaligursky in #8989 * Add compute shader definition types to docs by @mvaligursky in #9067 ## Fixes * Fix crash when a gsplat octree asset is unloaded while still registered in the streaming world by @slimbuck in #9011 * Fix crash when a gsplat component detaches its asset while still registered in the streaming world by @slimbuck in #9016 * Fix crash when unloading SOG assets still referenced by the unified world by @slimbuck in #9035 * Fix gsplat loading progress getting permanently stuck after a cancelled mid-flight load by @slimbuck in #8998 * Rebuild bind groups when a bound texture's GPU resource is recreated by @slimbuck in #8982 * Fix SOG bundle parser continuing after asset unloads mid-load by @mvaligursky in #9037 * Fix SOG streaming re-load returning destroyed textures from loader cache by @mvaligursky in #9039 * Fix GPU device hang when picking gsplats on Windows/NVIDIA by @mvaligursky in #9036 * Re-copy work buffer for streamed gsplat placements and all consumers by @mvaligursky in #9021 * Fix `lodRangeMin`/`lodRangeMax` not applied from `GSplatComponent` init data by @willeastcott in #8968 * Fix gsplat work buffer not re-rendered for non-streaming splats on device restore by @mvaligursky in #8973 * Free SOG bundle archive memory after texture upload by @mvaligursky in #8972 * Fix markup text color shift by storing vertex palettes in linear space by @mvaligursky in #9034 * Fix skybox staying black after cubemap asset unload and reload by @mvaligursky in #9017 * Fix specular-glossiness diffuse texture not marked as sRGB in glb parser by @mvaligursky in #9009 * Fix glTF occlusion strength support by @mvaligursky in #9066 * Fix MSDF text anti-aliasing stability at small sizes by @willeastcott in #8990 * Free font textures when a font asset is unloaded by @mvaligursky in #8969 * Fix inverted buffer usage flags in `Mesh.clear()` by @willeastcott in #9023 * Fix `AnimationComponent` crash on tracks with events by @mvaligursky in #8985 * Fix `XrMenu` finger-poke clicks and textured button tint restore by @willeastcott in #9025 * Fix `XrNavigation` castRay plane coupling and stale teleport cache by @willeastcott in #9026 * Fix compound wiring for collision children that have their own rigidbody by @willeastcott in #9048 * Fix device constructor crash when canvas lacks `getBoundingClientRect` by @mvaligursky in #9000 * Fix deprecated API migration messages by @mvaligursky in #9079 * Fix deprecated gloss aliases by @mvaligursky in #9080 * Mark live API getters readonly by @kpal81xd in #8959 ## Examples * Add gaussian splat glass refraction example by @mvaligursky in #9020 * Add gaussian splat tree wind example with reusable GsplatTrees script by @mvaligursky in #9022 * Add reusable Water script with planar reflection and refraction, and a water example by @mvaligursky in #9029 * Add KTX2 cubemap example by @mvaligursky in #9068 * Modernize the graphics/layers example by @mvaligursky in #9088 * Fix `ProceduralSky` light drifting off the visible sun near sunset by @mvaligursky in #9028 * Fix HUD-only flags in shadow-soft and shadow-cascades examples by @mvaligursky in #9092 #9093 * Fix range/radius in shader toon and wobble examples by @mvaligursky in #9094 ## Engine Dependencies * Update all npm dependencies by @renovate[bot] in #9053 ### Contributors * @d0rianb * @hellohejinyu * @kpal81xd * @MotivaCG * @mvaligursky * @slimbuck * @willeastcott ## New Contributors * @d0rianb made their first contribution in #9013 * @hellohejinyu made their first contribution in #9050 * @MotivaCG made their first contribution in #9065 **Full Changelog**: https://github.com/playcanvas/engine/compare/v2.20.6...v2.21.0