Skip to content

feat(gsplat): apply render-stage modify hooks in the hybrid renderer#8822

Merged
mvaligursky merged 1 commit into
mainfrom
mv-gsplat-hybrid-modify
Jun 2, 2026
Merged

feat(gsplat): apply render-stage modify hooks in the hybrid renderer#8822
mvaligursky merged 1 commit into
mainfrom
mv-gsplat-hybrid-modify

Conversation

@mvaligursky
Copy link
Copy Markdown
Contributor

@mvaligursky mvaligursky commented Jun 2, 2026

Render-stage material customization — the gsplatModifyVS chunk (modifySplatCenter / modifySplatRotationScale / modifySplatColor) plus defines and uniforms set on app.scene.gsplat.material — now applies to the hybrid (GPU-sorted) renderer, matching the quad renderer. Previously these hooks were silently ignored in the hybrid path because projection happens in the projector compute pass rather than the vertex shader. Builds on the compute WGSL reflection from #8821 (which handles the user-declared uniforms/textures).

Changes:

  • Projector compute hookscompute-gsplat-project-common applies modifySplatCenter and modifySplatRotationScale before computeSplatCov (mirroring gsplatCorner's quaternion handling); compute-gsplat-projector applies modifySplatColor after getColor. Reuses the existing gsplatModifyVS chunk + gsplatHelpersVS.
  • Material plumbing — the projector injects the user's gsplatModifyVS chunk and defines, reflects its declared uniforms/textures into the projector's own bind group, and forwards material parameters. Compute variants are rebuilt only when the chunk/defines change (not per frame). A debug-only check (once per compile) reports user resource names that collide with projector-internal bindings.
  • Compute local renderer — gets the default no-op gsplatModifyVS (it shares projectSplatCommon), so it keeps compiling.
  • Material#definesKey — a cached, lazily-rebuilt content key for material defines, invalidated by setDefine / copy. Lets change-detection avoid scanning the defines map every frame (mirrors ShaderChunkMap.key); generally reusable.

API Changes:

  • Adds Material#definesKey (getter, @ignore). No breaking changes.

Notes:

  • The hybrid renderer's own material intentionally does not copy the user material's settings (the quad's copyMaterialSettings). The geometry/color modification is fully handled in the projector compute and baked into the projection cache, and the engine-side fragment inputs (alphaClip, colorRamp, fog, overdraw) are already synced. The only thing such a copy would add is fragment-shader customization (overriding gsplatPS, or fragment-only defines/params), which is not a supported gsplat customization point today (the only exposed render-stage hook is gsplatModifyVS). If gsplat fragment-shader customization is ever introduced, the hybrid renderer would need a copyMaterialSettings-equivalent at that point.
  • Verified manually on WebGPU with the gsplat shader-effects and reveal examples (hide/reveal scale effects and animated uniforms now work in hybrid mode); full unit suite passes.

The render-stage material customization (app.scene.gsplat.material's
gsplatModifyVS chunk: modifySplatCenter / modifySplatRotationScale /
modifySplatColor, plus defines and uniforms) now also applies to the hybrid
(GPU-sorted) renderer, matching the quad renderer. Previously these hooks were
ignored in the hybrid path because projection happens in the projector compute
pass rather than the vertex shader.

- Inject the modify hooks into the projector compute (compute-gsplat-project-common
  applies center + rotation/scale before computeSplatCov; compute-gsplat-projector
  applies color after getColor), reusing the existing gsplatModifyVS chunk.
- The projector reflects user-declared uniforms/textures from the modify chunk into
  its own bind group (via compute WGSL reflection) and forwards material params and
  defines, rebuilding the compute variants only when the chunk/defines change.
- Add the no-op gsplatModifyVS chunk to the compute local renderer (which shares
  projectSplatCommon) so it keeps compiling.
- Add Material#definesKey: a cached, lazily-rebuilt content key for material defines
  (invalidated by setDefine / copy), used to detect customization changes cheaply
  without scanning the defines map every frame.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Extends the hybrid (GPU-sorted) gsplat renderer's projector compute to honor the same render-stage gsplatModifyVS hooks (modifySplatCenter, modifySplatRotationScale, modifySplatColor) that the quad renderer already uses from app.scene.gsplat.material. Previously these were ignored on the hybrid path because projection happens in a compute pass. Variants are rebuilt only when the user chunk / defines actually change, leveraging a new cached Material#definesKey.

Changes:

  • WGSL projector compute chunks include gsplatModifyVS/gsplatHelpersVS and call the modify hooks at the equivalent points to gsplatCorner/gsplatVS (with the same (w,x,y,z)(x,y,z,w) quaternion swap).
  • GSplatProjector reads the user's WGSL modify chunk and defines from the render material, merges them into the compute (skipping projector-internal defines), forwards material parameters, and adds a debug-only warning when reflected user resource names collide with projector bindings.
  • New Material#definesKey getter — cached, lazily-rebuilt content key for defines, invalidated by setDefine and copy, used by the projector to cheaply detect define changes.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-project-common.js Calls modifySplatCenter then modifySplatRotationScale before computeSplatCov, with the yzwx/wxyz quaternion swap to match the quad path.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-projector.js Includes gsplatHelpersVS/gsplatModifyVS and applies modifySplatColor (post AA compensation) on both pick and non-pick branches.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-local-tile-count.js Adds default gsplatModifyVS include so the local-tile-count compute (sharing projectSplatCommon) keeps compiling.
src/scene/gsplat-unified/gsplat-compute-local-renderer.js Wires the no-op default modify chunk into the local compute renderer's includes.
src/scene/gsplat-unified/gsplat-projector.js Adds _updateMaterial change-detection, injects user modify chunk/defines/parameters into projector compute, and a debug-only collision check against reserved bindings/uniforms.
src/scene/gsplat-unified/gsplat-manager.js Forwards gsplat.material to the projector dispatch params.
src/scene/materials/material.js Adds _definesKey cache + lazy definesKey getter, invalidated by setDefine and copy; doc note discourages direct mutation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mvaligursky mvaligursky merged commit cd095b1 into main Jun 2, 2026
9 checks passed
@mvaligursky mvaligursky deleted the mv-gsplat-hybrid-modify branch June 2, 2026 13:04
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