v2.23.0
X-PLUG/mPLUG-DocOwlv2.23.0Oct 1, 2026by mvaligursky
Upgrading?
AI Summary
This is a major release focusing on WebGPU rendering optimizations, a comprehensive refactoring of the material system, and advanced Gaussian Splatting capabilities. It also removes obsolete browser workarounds and deprecated APIs.
Key Highlights
- Significant WebGPU rendering optimizations including persistent storage buffers and pipeline caching
- Major material system refactoring with bind groups and uniform buffers
- Enhanced Gaussian Splatting with LOD streaming and stochastic alpha rendering
- Removal of obsolete browser workarounds (Safari, Chrome) and immediate mesh rendering
Breaking Changes
- Renamed `supportsUniformBuffers` to `usesMeshBindGroups`
- Deprecated `noFog` in favor of `useFog`
- Removed obsolete immediate mesh rendering functionality
- Removed the shader dump and precompile workflow
- Removed obsolete Mac Chrome blitFramebuffer and Safari texture unit workarounds
New Features
- Added `distanceSq` utility function
- Added `useFog` and `useTonemap` properties to ParticleSystemComponent
- Added ability to load audio assets regardless of URL file extension
- Added headless Node.js execution support without jsdom
- Added bloom threshold to CameraFrame
- Added per-attachment clear colors for multiple render targets
- Added stencil clears inside a render pass on WebGPU
- Added partial vertex and index buffer uploads
- Added stochastic alpha rendering for GPU-sort Gaussian Splatting renderer
Full Release Notes
## Changes * Add distanceSq by @AlexAPPi in #9313 * Add useFog/useTonemap to ParticleSystemComponent, deprecate noFog by @mvaligursky in #9340 * Load audio assets regardless of the URL's file extension by @mvaligursky in #9365 * Poll gamepads every frame without allocating by @willeastcott in #9470 * Run the engine headless in Node.js without jsdom by @willeastcott in #9504 * Replace batch.origMeshInstances[0] with sourceMeshInstance variable by @AlexAPPi in #9454 ## Rendering * Store mesh instance matrices in a persistent storage buffer on WebGPU by @mvaligursky in #9614 * Add a bloom threshold to CameraFrame by @mvaligursky in #9455 * Add per-attachment clear colors to the camera for multiple render targets by @mvaligursky in #9333 * Support stencil clears inside a render pass on WebGPU by @mvaligursky in #9612 * Allow camera viewports extending past the render target on WebGPU by @mvaligursky in #9516 * Add partial vertex and index buffer uploads by @mvaligursky in #9401 * Add screen_size to forward view uniforms and deprecate uScreenSize by @mvaligursky in #9331 * Pack forward view uniforms to reduce alignment padding by @mvaligursky in #9332 * Move per-pass uniforms into the view uniform buffer by @mvaligursky in #9582 * Move textureBias into the view uniform buffer by @mvaligursky in #9484 * Supply per-pass textures through the WebGPU view bind group by @mvaligursky in #9521 * Publish the scene environment textures under their own uniforms by @mvaligursky in #9364 * Add an opt-in std140 packing order to UniformBufferFormat by @mvaligursky in #9400 * Stop creating typed array views for every dynamic uniform buffer update by @mvaligursky in #9418 * Retain WebGPU render pipelines between draws by @mvaligursky in #9380 * Look the WebGPU render pipeline up only when its state changes by @mvaligursky in #9492 * Write WebGPU buffer data directly from its storage by @mvaligursky in #9379 * Pass WebGPU bind group dynamic offsets as a typed array by @mvaligursky in #9487 * Skip WebGPU vertex and index buffer binds the render pass already has by @mvaligursky in #9496 * Keep the backing store of the device vertex buffer list across draws by @mvaligursky in #9498 * Assign bind group slots by index during the update by @mvaligursky in #9425 * Split the bind group update into a scope path and an owner path by @mvaligursky in #9429 * Leave a texture out of the mesh bind group when a supplied group has it by @mvaligursky in #9436 * Let the graphics device own the built-in textures by @mvaligursky in #9438 * Rebuild layer mesh arrays lazily after removals by @mvaligursky in #9378 * Pack the mesh instance light mask into 8 bits, for 24 shader define flags by @mvaligursky in #9617 * Rename supportsUniformBuffers to usesMeshBindGroups by @mvaligursky in #9383 * Split WebGPU device creation from device initialization by @mvaligursky in #9483 * Ignore MeshInstance#setIndirect where indirect draw is not supported by @mvaligursky in #9462 * Remove obsolete immediate mesh rendering by @mvaligursky in #9385 * Remove the shader dump and precompile workflow by @mvaligursky in #9477 * Remove obsolete Mac Chrome blitFramebuffer workaround by @mvaligursky in #9318 * Remove obsolete Safari texture unit workaround by @mvaligursky in #9319 ## Lighting & Shadows * Move light uniforms into the view uniform buffer, uploaded once per pass by @mvaligursky in #9482 * Give every light an absolute slot, shared by all light masks by @mvaligursky in #9475 * Dispatch the lights of a pass once, not per light mask by @mvaligursky in #9479 * Consolidate light slots into a LightList shared by renderer, shaders and lightmapper by @mvaligursky in #9481 * Make world-cluster allocation request/execute based by @mvaligursky in #9473 * Fade directional shadows at the far distance by @mvaligursky in #9417 * Skip shadow sampling beyond the far distance by @mvaligursky in #9419 * Request directional shadow culling from scheduled render passes by @mvaligursky in #9423 * Request local shadow culling from scheduled render passes by @mvaligursky in #9428 * Cull only requested directional shadow cascades by @mvaligursky in #9437 * Skip spot VSM blur when the shadow pass does not execute by @mvaligursky in #9440 * Set shadow caster material state once per material run by @mvaligursky in #9524 * Derive the normal matrix of shader materials in the shadow pass by @mvaligursky in #9585 * Give a mesh instance lightmap its own texture slot by @mvaligursky in #9415 * Bind only the lightmap slots a bake writes by @mvaligursky in #9420 * Fix shadow shader selection when changing cascade count by @mvaligursky in #9343 * Reset clustered shadow lights before preparing each frame by @mvaligursky in #9414 * Fix WebGPU shadow shader compile error for PCSS spot lights by @mvaligursky in #9545 * Pass an empty LightList, not 0, to the shadow pass shaders by @willeastcott in #9556 * Hidden mesh instances with culling disabled no longer cast shadows by @mvaligursky in #9606 ## Materials * Add a material bind group slot and cached shader processing keys by @mvaligursky in #9370 * Hold the textures of a material in its own bind group by @mvaligursky in #9457 * Bind the material bind group at a material switch instead of at every draw by @mvaligursky in #9413 * Store StandardMaterial diffuse in a material-owned uniform buffer by @mvaligursky in #9381 * Store emissive color and intensity in the material uniform buffer by @mvaligursky in #9392 * Store the remaining StandardMaterial colors and numbers in the material uniform buffer by @mvaligursky in #9398 * Store the derived StandardMaterial uniforms in the material uniform buffer by @mvaligursky in #9402 * Store the texture map transforms in the material uniform buffer by @mvaligursky in #9405 * Store the cube map projection box in the material uniform buffer by @mvaligursky in #9406 * Copy the cube map projection box into the material instead of keeping a reference by @mvaligursky in #9411 * Support mesh instance overrides of material uniform buffer values by @mvaligursky in #9386 * Let a mesh instance override a texture of the material bind group by @mvaligursky in #9445 * Restore global scope values after mesh instance parameter overrides by @mvaligursky in #9588 * Warn in debug builds when a mesh instance override array changes in place by @mvaligursky in #9395 * Warn about material and mesh instance parameters of view uniforms by @mvaligursky in #9619 * Add support for all eight UV sets in StandardMaterial by @mvaligursky in #9376 * Make alphaTest an accessor of Material and retire the generic float property helper by @mvaligursky in #9408 * Separate sprite color from material uniforms by @mvaligursky in #9337 * Separate UI element colors from material uniforms by @mvaligursky in #9338 * Pass the model scale to dynamic refraction from the vertex shader by @mvaligursky in #9616 * Fix LitMaterial ambient by making the ambient tint a lit argument by @mvaligursky in #9538 * Fix StandardMaterial shader invalidation for environment textures and 0/1 number changes by @mvaligursky in #9359 * Fix StandardMaterial shader invalidation for refraction thresholds by @mvaligursky in #9363 * Make StandardMaterial texture map iteration ignore prototype properties by @mvaligursky in #9368 * Stop placeholder textures from forcing shader recompiles by @mvaligursky in #9592 ## Gaussian Splatting * Make gsplat LOD distance-only, with target or limit splat budgets by @mvaligursky in #9584 * Only judge oversized gsplat LOD nodes by their middle by @mvaligursky in #9586 * Gsplat LOD: empty level for nodes without coarse data; distance default by @mvaligursky in #9326 * Load streamed gsplat LOD files nearest the camera first by @mvaligursky in #9520 * Update StreamedGSplat presets to use LOD falloff by @mvaligursky in #9369 * Stochastic alpha rendering for the GPU-sort gsplat renderer by @slimbuck in #9443 * Flat per-splat gsplat varyings and fix ComputeRadixSort reallocation on growth by @slimbuck in #9372 * Allow either provoking vertex for WGSL splat varyings by @mvaligursky in #9374 * Prefer first provoking vertex on WebGL by @mvaligursky in #9375 * Use a per-axis focal length for the gsplat footprint by @dfattal in #9486 * Skip compute work for cached Gaussian splat shadows by @mvaligursky in #9416 * Make Gaussian splatting GLB support tree-shakeable by @mvaligursky in #9327 * Make GSplat scene parameters tree-shakeable by @mvaligursky in #9328 * Avoid retaining GSplat work buffer shaders in container bundles by @mvaligursky in #9322 * Apply withCredentials to the gsplat loaders that stream with fetch by @mvaligursky in #9458 * Warn when gaussian splats render into a multisampled target by @mvaligursky in #9532 * Fix gsplat GPU sort flicker from sort key precision loss by @mvaligursky in #9493 * Fix mirrored gsplat footprints in flipped render targets by @mvaligursky in #9490 * Fix fisheye gsplats and sky in flipped render targets by @mvaligursky in #9495 * Correct gsplat spherical harmonics with orthographic cameras by @mvaligursky in #9531 * Fix NVIDIA GPU hangs during gsplat depth picking by @slimbuck in #9572 * Prevent gsplat crash after destroying a splat entity by @mvaligursky in #9522 * Prevent gsplat streaming crash after destroying a camera by @mvaligursky in #9533 * Render gsplats again after a camera re-adds their layer by @mvaligursky in #9535 * Keep gsplat placement changes made in frame:ready handlers by @mvaligursky in #9536 * Stop a gsplat from blanking for a frame when its asset is replaced by @willeastcott in #9610 ## Physics * Add RigidBodyComponent#gravityScale by @willeastcott in #9465 * Add a hitBackFaces raycast option to skip mesh collider back faces by @willeastcott in #9506 * Tighten the public surface of the physics API by @willeastcott in #9519 * Harden physics raycasts and forward the Application physicsWorld option by @willeastcott in #9517 * Ship an Ammo build whose heap starts at 16MB and grows on demand by @willeastcott in #9488 * Route the Ammo internal tick callback through one dispatcher per module by @willeastcott in #9463 * Apply gravity to the physics backend on install and when it changes by @willeastcott in #9439 * Refresh Ammo broadphase bounds when a body is teleported by @willeastcott in #9489 * Mirror mesh colliders with negative scale factors by @willeastcott in #9499 * Keep the orientation of mirrored dynamic bodies across physics steps by @willeastcott in #9500 * Fix mesh colliders sharing a mesh at different scales and rebuild them on scale changes by @willeastcott in #9311 * Sync compound children from their own transforms, not the root's dirty flag by @willeastcott in #9456 * Rebuild a collision component as a trigger when its rigid body is removed by @willeastcott in #9464 * Give both entities of a contact the normal of the other surface by @willeastcott in #9450 ## XR * Stop a double XR start from leaving a broken session by @willeastcott in #9599 * Stop the app freezing when an XR session ends by @willeastcott in #9600 * Stop XR culling from using the previous frame's head pose by @willeastcott in #9601 * Remove XR event listeners that outlive their owners by @willeastcott in #9623 * Apply camera clip plane changes to a running XR session by @willeastcott in #9624 * Correct XR input source rays and velocities by @willeastcott in #9625 * Start XrSession sessions facing the way the camera looks by @willeastcott in #9626 * Keep removed XR planes and meshes readable, and harden hit testing by @willeastcott in #9627 * Keep XrControllers models loaded while input sources share them by @willeastcott in #9631 * Hide XrControllers models while their pose is not tracked by @willeastcott in #9635 * Stop XrNavigation teleporting on system menu gestures by @willeastcott in #9636 * Document the XR select events of ElementComponent by @willeastcott in #9633 ## UI * Warn when image materials have no opaque render pass by @mvaligursky in #9346 * Keep an element's position when it is added to an entity under a screen by @willeastcott in #9525 * Let ElementDragHelper drag an element that is a direct child of a screen by @willeastcott in #9551 * Update a scrollbar's handle when its track is resized by @willeastcott in #9573 * Fix layout group subscriptions when components change by @mvaligursky in #9399 * Build text meshes without a pass over empty arrays by @willeastcott in #9562 * Skip drawing text with an empty render range by @willeastcott in #9567 * Draw CanvasFont glyph cells fully transparent by @willeastcott in #9568 * Fix a markup parser crash when a tag name shadows hasOwnProperty by @willeastcott in #9468 * Correct UI component docs, the Spanish locale fallback and button examples by @willeastcott in #9552 ## Device Recovery * Restore WebGPU rendering resources after device loss by @mvaligursky in #9355 * Restore WebGPU profiling after device loss by @mvaligursky in #9357 * Fix WebGPU recovery for compute, readback and generated data by @mvaligursky in #9358 * Cancel WebGPU recovery when the device is destroyed by @mvaligursky in #9397 * Fix WebGPU resource cleanup on device destruction by @mvaligursky in #9394 * Restore the WebGL backbuffer before recovery callbacks by @mvaligursky in #9347 * Recover SOG streaming across WebGL context loss by @mvaligursky in #9350 * Restore procedural sky lighting after device recovery by @mvaligursky in #9351 * Add cross-backend debug device loss testing by @mvaligursky in #9353 * Restore generated HDR environments in examples after device loss by @mvaligursky in #9345 * Redraw the on-demand splat example after device recovery by @mvaligursky in #9348 * Rebake example lightmaps after device recovery by @mvaligursky in #9352 ## Profiling & Debugging * Redesign MiniStats with compact and grouped profiling views by @mvaligursky in #9307 * Add collapsible MiniStats sections by @mvaligursky in #9361 * Add tracked resource counts to MiniStats by @mvaligursky in #9366 * Expose application performance statistics through AppStats by @mvaligursky in #9308 * Add user counters to AppStats by @mvaligursky in #9341 * Correct MiniStats timing and build availability documentation by @mvaligursky in #9310 * Add TextureRenderer for debug texture previews by @mvaligursky in #9382 * Add per-camera culling and display fixes to TextureRenderer by @mvaligursky in #9387 * Add a debug-engine draw limit for stepping through a render pass by @mvaligursky in #9501 * Add descriptive GPU profiling names for quad passes by @mvaligursky in #9329 * Track shaders on every graphics device by @mvaligursky in #9466 * Add a bare WebGL 2 device type for testing on constrained devices by @mvaligursky in #9471 * Announce apps to a devtools hook by @mvaligursky in #9618 * Add AppOptions#devtools to opt out of the devtools hook by @mvaligursky in #9637 ## Fixes * Add missing TEXTURE_2D_ARRAY entry to targetToSlot by @mvaligursky in #9321 * Fix sprite tint color space conversion by @mvaligursky in #9334 * Clear keyboard and mouse states on detach and focus loss by @mvaligursky in #9344 * Reset stale mouse movement deltas by @mvaligursky in #9349 * Fix WebGPU texture-formats-tier feature names and rename their flags by @mvaligursky in #9390 * Fix skydome depth of field with scene-pass depth by @mvaligursky in #9391 * Wait for container meshes before marking render assets ready by @mvaligursky in #9404 * Fix Picker readback rectangle in the top-left to bottom-left flip by @mvaligursky in #9441 * Reconstruct the picked world position at the pixel center by @mvaligursky in #9446 * Call super.frameUpdate() from RenderPassCompose by @mvaligursky in #9449 * Copy the render style onto a batched mesh instance by @mvaligursky in #9448 * Fix CameraComponent#setShaderPass() throwing when resetting the pass by @mvaligursky in #9451 * Resolve glb model resources against the directory of the glb by @mvaligursky in #9453 * Stop leaking a DrawCommands set per indirect draw per frame by @mvaligursky in #9459 * Fix bundle asset load retrying and error-response handling by @mvaligursky in #9460 * Fix the WebGL multi-draw fallback submitting no draws by @mvaligursky in #9461 * Treat every 2xx HTTP status as success by @willeastcott in #9507 * Accept status 0 responses from non-http schemes by @willeastcott in #9508 * Fix Curve.closest outside unit range by @humairaambreen in #9543 * Return the first key from Curve#closest for times before the curve by @willeastcott in #9544 * Accept mesh instances without a material in Layer#addMeshInstances by @mvaligursky in #9579 * Skip disabled entities in OutlineRenderer by @mvaligursky in #9452 * Fix OutlineRenderer shader errors when clustered lighting is disabled by @mvaligursky in #9590 * Fix OutlineRenderer material cleanup and frameUpdate listener leak by @mvaligursky in #9589 * Fix OutlineRenderer outlines missing with some CameraFrame settings by @mvaligursky in #9594 * Blur the TAA output in the camera frame's bloom and depth of field by @willeastcott in #9591 * Fix calculateNormals returning NaN for vertices with no triangle area by @mvaligursky in #9596 * Fix FloatPacking.float2Half corrupting values too large for a half float by @mvaligursky in #9595 * Clean up pole and tip triangles in sphere, capsule and cone geometry by @mvaligursky in #9597 * Keep screen-space particles square on any canvas aspect by @willeastcott in #9570 * Export skinned meshes to USDZ where their bones place them by @willeastcott in #9546 * Use the WGSL built-in saturate, fixing lightVertexColor on WebGPU by @mvaligursky in #9598 * Flip the vertex normal of back faces for two sided lighting by @willeastcott in #9559 * Initialize GraphicsDevice renderPassIndex to 0 by @mvaligursky in #9605 * Load cubemap faces given as URLs as sRGB color, not RGBP by @mvaligursky in #9607 * Fix Texture#lock on cubemap faces and mip levels by @mvaligursky in #9608 * Fix WebGPU stencil read mask, reuse pipelines across stencil refs by @mvaligursky in #9611 * Make createGraphicsDevice reject instead of hanging when no device can be created by @willeastcott in #9603 * Depth state fixes (depthTest, WebGPU depth bias, layer reset) by @mvaligursky in #9615 * Fix BlendState#setAttachment reviving overrides cleared by copy by @mvaligursky in #9620 ## Examples * Restyle the examples browser by @mvaligursky in #9629 * Slim the collapsed code pane and hide the code minimap by @mvaligursky in #9632 * Open the PlayCanvas Inspector in the examples browser by @mvaligursky in #9621 * Serve the inspector loader as is in the dev server by @mvaligursky in #9638 * Link a whole examples category by URL by @mvaligursky in #9303 * Add category sharing and expand-all controls by @mvaligursky in #9356 * Reveal current example when clearing search by @mvaligursky in #9354 * Rebuild the UI button, panel, masking and custom shader examples by @willeastcott in #9565 * Rebuild the UI text examples by @willeastcott in #9566 * Rebuild the UI layout, image and world examples by @willeastcott in #9569 * Add the UI input, common widgets and drag and drop examples by @willeastcott in #9571 * Add a hidden test example for UI element states by @mvaligursky in #9580 * Add rendering without entities example by @mvaligursky in #9377 * Add environment sources test example by @mvaligursky in #9360 * Give the render to image example a knight of its own by @willeastcott in #9583 * Refresh the MiniStats example scene by @mvaligursky in #9309 * Migrate examples to TextureRenderer by @mvaligursky in #9384 * Load the VAT character data as a binary asset in the vat-characters example by @mvaligursky in #9518 * Render gaussian splat crop and depth-of-field examples without MSAA by @mvaligursky in #9634 * Restore the depth prepass in the gaussian splat depth-of-field example by @mvaligursky in #9639 * Apply area-picker example material changes via update() by @mvaligursky in #9497 * Remove no-op bloom.enabled writes from examples by @mvaligursky in #9476 * Replace the Arial and Courier fonts of the examples and tests with Roboto by @willeastcott in #9577 * Ship the Roboto ExtraLight license with the XR examples' font by @willeastcott in #9576 ## Documentation & Types * Type Entity#addComponent options and result by component name by @willeastcott in #9320 * Type Asset#resource by asset type (Asset<K>, AssetMap, AssetType) by @willeastcott in #9403 * Type the script lookup APIs against Script and return the class you pass in by @willeastcott in #9472 * Type element input events with the browser objects they carry by @willeastcott in #9527 * Add alpha option to createGraphicsDevice typings by @willeastcott in #9317 * Fix JSDoc types that disagree with runtime values, salvaged from #5817 by @willeastcott in #9469 * Fix Debug.assert and Texture levels JSDoc types by @willeastcott in #9491 * Clear all API reference build warnings and treat warnings as errors by @willeastcott in #9412 * Add a Framework category and home the uncategorised public classes by @willeastcott in #9421 * Rewrite Asset-related class overviews and document every resource handler by @willeastcott in #9409 * Rewrite the Math category class overviews by @willeastcott in #9410 * Rewrite the scene graph and render pipeline class overviews by @willeastcott in #9422 * Rewrite the material class overviews by @willeastcott in #9424 * Make the modern input system the Input category and describe its classes by @willeastcott in #9427 * Describe the modern animation classes and mark the legacy ones by @willeastcott in #9430 * Describe the sound classes and template the thin component system pages by @willeastcott in #9432 * Describe the Gizmo and TransformGizmo base classes by @willeastcott in #9433 * Use American spelling in the Material and LitShaderOptions overviews by @willeastcott in #9431 * Document which asset types fire the progress event by @willeastcott in #9474 * Correct RigidBodyComponent group/mask defaults and raycastAll sort order by @willeastcott in #9305 * Fix physics docs for impulse points, kinematic velocity and contact results by @willeastcott in #9515 * Improve OutlineRenderer API documentation by @mvaligursky in #9587 * Correct typos and British spellings across the engine source by @willeastcott in #9547 * Correct typos and British spellings in examples, scripts and tests by @willeastcott in #9550 * Add a context7.json so Context7 indexes usage docs and agent rules by @willeastcott in #9478 * Point the Context7 rules at the llms.txt indexes by @willeastcott in #9503 ## Engine Dependencies * Update dependency sharp to v0.35.4 [SECURITY] in #9330 * Update all npm dependencies in #9434 * Update dependency mocha to v12 in #9435 ### Contributors * @AlexAPPi * @dfattal * @humairaambreen * @mvaligursky * @slimbuck * @willeastcott ## New Contributors * @dfattal made their first contribution in #9486 * @humairaambreen made their first contribution in #9543 **Full Changelog**: https://github.com/playcanvas/engine/compare/v2.22.6...v2.23.0
Related Repositories
public-apis/public-apis★ 491,126
A collective list of free APIs
NousResearch/hermes-agent★ 255,895
The agent that grows with you
yt-dlp/yt-dlp★ 199,990
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,478
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,699
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.