v2.18.0
playcanvas/enginev2.18.0Apr 17, 2026by mvaligursky
AI Summary
Major release focused on compute-based Gaussian Splatting rendering for WebGPU with significant performance optimizations, new fisheye projection support, and fog rendering capabilities. Also includes HTML-in-Canvas support and various GSplat renderer improvements.
Key Highlights
- Add compute-based tiled GSplat renderer for WebGPU with local compute and dynamic buffer sizing
- Introduce fisheye projection for Gaussian splats and skybox support
- Add fog support for Gaussian splat rendering
- Implement WebGPU subgroup operations support
- Add GSplatParams.renderer enum for runtime renderer selection
New Features
- Compute-based tiled GSplat renderer (WebGPU)
- Local compute GSplat renderer with dynamic buffer sizing
- Fisheye projection for Gaussian splats
- Fog support for Gaussian splats
- WebGPU subgroup operations
- HTML-in-Canvas support with texElementImage2D
- Interactive hit testing
- Heatmap debug mode for compute GSplat rasterizer
- GPU compute benchmark example
Full Release Notes
## Changes * Remove per-resource instance vertex buffer from GSplat rendering by @mvaligursky in #8513 * Expose GSplat rendering properties on GSplatParams by @mvaligursky in #8518 * Add HTML-in-Canvas support with texElementImage2D and interactive hit testing by @mvaligursky in #8519 * Refactor GSplatRenderer into base class with GSplatQuadRenderer derived class by @mvaligursky in #8520 * Refine GSplatRenderer API: rename methods for clarity by @mvaligursky in #8522 * Extract FramePass base class from RenderPass by @mvaligursky in #8523 * Add WebGPU subgroup operations support by @mvaligursky in #8528 * Optimize GPU radix sort with bitmask ranking and multi-element processing by @mvaligursky in #8529 * Add compute-based tiled GSplat renderer (WebGPU) by @mvaligursky in #8531 * Add local compute GSplat renderer and dynamic buffer sizing (WebGPU) by @mvaligursky in #8536 * Replace full-screen quad composite with tile-based indirect draw in local compute GSplat renderer by @mvaligursky in #8544 * Add orthographic camera support to compute GSplat renderers by @mvaligursky in #8545 * Improve compute GSplat rendering and add tonemapping support by @mvaligursky in #8546 * Support dynamic work buffer formats in compute GSplat renderers by @mvaligursky in #8547 * Remove redundant shader includes from ShaderUtils.createShader callers by @slimbuck in #8551 * Add WebGPU Bare device type for testing without optional features by @mvaligursky in #8555 * Add picking support and fix color pipeline in local compute GSplat renderer by @mvaligursky in #8556 * Remove global compute GSplat renderer by @mvaligursky in #8558 * Remove per-splat GPU compaction for CPU sort path by @mvaligursky in #8559 * Extract GSplatFrustumCuller from GSplatWorkBuffer by @mvaligursky in #8560 * Merge frustum culling into compute, convert to storage buffers, fix >16M splat dispatch by @mvaligursky in #8561 * Make frustum culling always-on and remove dead pcNodeIndex pipeline by @mvaligursky in #8562 * Reduce register pressure in compute GSplat TileCount projection by @mvaligursky in #8563 * Store conic form in projection cache to avoid per-tile conversion by @mvaligursky in #8565 * Add GSplatParams.renderer enum for runtime renderer selection by @mvaligursky in #8567 * Remove centers array dependency from GSplatInfo interval check by @mvaligursky in #8568 * Add minContribution property for compute GSplat contribution culling by @mvaligursky in #8571 * Increase default minContribution from 2 to 3 by @mvaligursky in #8575 * Add fisheye projection for Gaussian splats by @mvaligursky in #8576 * Add fisheye projection support for skybox by @mvaligursky in #8577 * Refactor rasterize variant management and beforePasses scheduling by @mvaligursky in #8579 * Add depth testing for compute GSplat renderer when CameraFrame depth prepass is enabled by @mvaligursky in #8581 * Simplify Camera.beforePasses to a plain FramePass array by @mvaligursky in #8582 * Add fog support for Gaussian splat rendering by @mvaligursky in #8583 * Replace atomic scatter with pair-buffer tile binning and cooperative large-splat processing by @mvaligursky in #8586 * Split viewDepth into separate depthBuffer for sort cache locality by @mvaligursky in #8587 * Move FisheyeProjection to scene/graphics for shared use by @mvaligursky in #8588 * Modernize README and improve npm discoverability by @willeastcott in #8591 * Remove Bundlephobia badge from READMEs by @willeastcott in #8592 * Per-node granular SH color updates with angle-based threshold by @mvaligursky in #8593 * Optimize tile-count pass with multi-splat threads and extract dispatch prep shaders by @mvaligursky in #8594 * Remove workgroup-level early-out atomics from rasterize pass by @mvaligursky in #8596 * Vectorize Gaussian evaluation across 2x2 pixel quad in rasterize pass by @mvaligursky in #8597 * Unify GSplat debug rendering into a single enum-based API by @mvaligursky in #8598 * Add heatmap debug mode for compute GSplat rasterizer by @mvaligursky in #8599 * Revert tile-count pass to single-splat-per-thread by @mvaligursky in #8603 * Decouple compute GSplat renderer from work buffer via setDataSource by @mvaligursky in #8605 * Add shader defines for prepass to support alpha test and dithered opacity by @slimbuck in #8606 * Improve GSplat compute renderer cold-start buffer capacities by @mvaligursky in #8610 ## Fixes * Reset render pass merge flags each frame in FrameGraph.compile() by @mvaligursky in #8516 * Fix TAA ghosting artifacts on WebGPU by @mvaligursky in #8517 * Prevent division by zero in CAS sharpening shader by @slimbuck in #8532 * Preserve blend state in drawQuadWithShader / RenderPassQuad by @mvaligursky in #8535 * Fix double decrement of octree file ref counts on entity disable by @mvaligursky in #8537 * Use y-first approach in Compute.calcDispatchSize to minimize wasted workgroups by @mvaligursky in #8538 * Round up compressed texture dimensions to block size on WebGPU by @mvaligursky in #8540 * Replace StopThePop tile intersection with exact FlashGS method in compute GSplat by @mvaligursky in #8548 * Smooth Gaussian falloff for capped splat radii in compute renderer by @mvaligursky in #8549 * Avoid workgroupUniformLoad on atomic type for iOS WGSL compatibility by @mvaligursky in #8552 * Use unfilterable-float sample type for RGBA32F textures in node culling shader by @mvaligursky in #8553 * Use unfilterable-float sample type for RGBA32F GSplat textures on WebGPU by @mvaligursky in #8554 * Pass alphaClip to scatter pass instead of hardcoding 1/255 by @mvaligursky in #8564 * Match quad renderer near-plane behavior in compute GSplat renderer by @mvaligursky in #8566 * Match raster minPixelSize culling threshold in compute GSplat renderer by @mvaligursky in #8569 * Use logarithmic depth quantization in compute GSplat bitonic sort by @mvaligursky in #8570 * Match raster Gaussian radius cap in compute GSplat renderer by @mvaligursky in #8573 * Improve compute GSplat tile entry buffer scaling to reduce overflow artifacts by @mvaligursky in #8574 * Preserve layerPlacementsDirty flag when octree placements are removed by @mvaligursky in #8584 * Include fresnelSchlick chunk when refraction is enabled without specular by @willeastcott in #8595 * Suppress frame:ready until full LOD update after param changes by @mvaligursky in #8602 ## Examples * Fix FOV slider default value in LOD streaming example by @mvaligursky in #8510 * Hide test two-sided lighting example thumbnails by @mvaligursky in #8511 * Add radial sorting toggle to LodStreaming example by @mvaligursky in #8515 * Add clear button to examples sidebar filter input by @mvaligursky in #8541 * Limit examples sidebar to left half of screen on mobile by @mvaligursky in #8542 * Use consistent XR session check for viewport sizing and add stereo GSplat test example by @mvaligursky in #8557 * Add URL input and orientation controls to LOD streaming example by @mvaligursky in #8572 * Add procedural weather particle system example using Gaussian splats by @mvaligursky in #8580 * Add renderer selection UI to all Gaussian splat examples by @mvaligursky in #8585 * Add environment map and metallic reflections to html-texture example by @mvaligursky in #8589 * Add URL parameter support to LOD streaming example by @mvaligursky in #8590 * Add GPU compute benchmark and GSplat benchmark example by @mvaligursky in #8600 * Add cloud shadows shader chunk override example by @mvaligursky in #8604 * Replace share buttons with save buttons in GSplat benchmark example by @mvaligursky in #8608 ## Engine Dependencies * Update rollup to v4.59.0 (security) in #8483 ### Contributors * @mvaligursky * @slimbuck * @willeastcott **Full Changelog**: https://github.com/playcanvas/engine/compare/v2.17.2...v2.18.0