Skip to content

feat(gsplat): cast directional shadows from the hybrid renderer#8933

Merged
mvaligursky merged 2 commits into
mainfrom
mv-gsplat-hybrid-shadows
Jun 19, 2026
Merged

feat(gsplat): cast directional shadows from the hybrid renderer#8933
mvaligursky merged 2 commits into
mainfrom
mv-gsplat-hybrid-shadows

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Lets the GPU-sort (hybrid) gsplat renderer cast directional shadows — previously only the CPU-sort quad renderer could, so scenes using the hybrid renderer got no gsplat shadows.

Changes:

  • New GSplatShadowRenderer: a projection-free compute cull (coarse octree-node vs light-frustum reject) producing an unsorted visible-index buffer, then a quad-style per-vertex-projected indirect draw via the standard shadow-caster pipeline (no sort, no projection cache).
  • Supports any number of non-cascaded directional lights, each with its own cull + draw. Shadow casting fans out at the renderer level only — one GSplatWorld per manager regardless of light count.
  • A separate shadow-only manager no longer allocates the unused forward sorter/projector (the hybrid renderer's GPU sort/projection resources are now created lazily on first forward use).
  • Correct world-space PCSS soft-shadow depth range: the shadow caster mesh instances are given the real aggregate splat AABB, matching the forward path.
  • Extracted a shared interval-data builder (gsplat-interval-data.js) reused by the forward interval compaction and the shadow cull.

Examples:

  • gaussian-splatting/shadows: added a "Lights" slider (0–6) demonstrating multiple directional gsplat shadows (lights evenly spaced at the full count, rotating together).

Performance:

  • Shadow casting skips projection and sorting entirely; the coarse node-frustum cull rejects whole octree nodes outside each light's view — the biggest win on large scenes.

The GPU-sort (hybrid) gsplat renderer can now cast directional shadows,
which previously only the CPU-sort quad renderer could.

A new GSplatShadowRenderer runs a projection-free compute cull (coarse
octree-node vs light-frustum reject) producing an unsorted visible-index
buffer, then a quad-style per-vertex-projected indirect draw via the
standard shadow-caster pipeline (no sort, no projection cache). It
supports any number of non-cascaded directional lights, each with its
own cull + draw, fanning out at the renderer level only (one GSplatWorld
per manager regardless of light count). A separate shadow-only manager no
longer allocates the unused forward sorter/projector.

Adds a Lights slider (0-6) to the gaussian-splatting/shadows example.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2287.6 KB (+10.3 KB, +0.45%) 586.6 KB (+1.8 KB, +0.31%) 456.0 KB (+1.2 KB, +0.27%)
playcanvas.min.mjs 2285.0 KB (+10.3 KB, +0.45%) 585.7 KB (+1.8 KB, +0.32%) 455.6 KB (+1.5 KB, +0.33%)

@mvaligursky mvaligursky merged commit 2802778 into main Jun 19, 2026
10 checks passed
@mvaligursky mvaligursky deleted the mv-gsplat-hybrid-shadows branch June 19, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants