Skip to content

fix(material): honor scene clip plane in built-in PBR and Standard materials#386

Draft
ryantrem wants to merge 5 commits into
masterfrom
fix/clip-plane-builtin-materials
Draft

fix(material): honor scene clip plane in built-in PBR and Standard materials#386
ryantrem wants to merge 5 commits into
masterfrom
fix/clip-plane-builtin-materials

Conversation

@ryantrem

@ryantrem ryantrem commented Jul 8, 2026

Copy link
Copy Markdown
Member

Problem

Forum report: Lite: setClipPlane — PBR, Standard, and Shader materials are not clipped

setClipPlane writes the clip plane into the scene UBO, but only Node Material (via ClipPlanesBlock) ever read it. The built-in PBR and Standard fragment shaders ignored scene.clipPlane entirely, so those materials were never clipped — a divergence from Babylon.js, where a scene clip plane clips every material family automatically.

Fix

Thread the existing scene.clipPlane UBO value into the built-in fragment shaders and discard fragments on the positive side of the plane (dot(vec4(worldPos, 1.0), clipPlane) > 0.0 → discard), matching BJS' clipPlaneFragment and Lite's ClipPlanesBlock:

  • PBR (pbr-template.ts) and Standard (standard-template.ts): emit the clip test at the top of fn main, before any texture work, so it applies on every fragment path (color, depth‑prepass, ESM shadow).
  • ShaderMaterial (shader-material.ts): a custom material owns its full WGSL and has no guaranteed world‑position varying, so Lite cannot inject clipping for it — same as Babylon.js, where ShaderMaterial must opt in. Documented how to do so using the scene.clipPlane value already exposed in the shader prelude.
  • setClipPlane JSDoc (scene-ubo-extras.ts) updated to state which material families honor it automatically.

The test is emitted unconditionally and runtime‑gated by the UBO value: when no clip plane is set, the clipPlane slot stays (0,0,0,0), so dot(..) > 0 is always false and nothing is clipped — a true no‑op for the vast majority of scenes that never call setClipPlane.

Why inline, not a dynamically imported fragment

Fog and ACES tonemap use a dynamic‑import pattern (await import(...) gated by a scene‑feature flag, then threaded into the template) specifically so their WGSL — which is large (fog is ~780 bytes: a calcFogFactor helper plus a blend block) — stays out of the shared pbr-renderable chunk that every PBR scene ships. That machinery only pays off when the deferred payload is bigger than the flag + dynamic‑import + threading code it adds.

The clip test is a single ~55‑byte WGSL line with no helper function. We prototyped the fog‑style approach (compile‑gated flag + pbr-clip-wgsl.ts dynamic import) and measured it against inlining:

  • Dynamic‑import approach: the guard/threading code added ~0.2 KB to the shared pbr-renderable chunk shipped by all PBR scenes, pushing 11 tight‑ceiling PBR scenes over their bundle‑size limits.
  • Inline approach (this PR): adds only the ~55‑byte literal (~0.1 KB) to PBR/Standard scenes; all 208 bundle‑size checks pass, no ceilings raised.

In short: the tree‑shaking machinery costs more than the string it would defer. Inlining is both smaller and simpler, and it matches how Standard already handles this kind of cheap, always‑on scene state. (For completeness we also empirically confirmed the inverse for fog: inlining fog shrinks the one PBR‑fog scene by ~200 B but grows every non‑fog PBR scene by ~540 B, so fog correctly stays dynamic.)

Testing

  • New parity scene 264 (scene264-clip-plane-materials): two spheres — one StandardMaterial, one PBRMaterial — sliced by a single setClipPlane (y > 0 discarded), covering both fixed families in one scene. MAD ≈ 0.001 vs. the Babylon.js reference (ceiling set to 0.1).
  • pnpm test:parity (includes bundle-size.spec.ts): all green — 208 bundle‑size checks pass, no ceiling changes.
  • Per‑scene bundle manifests regenerated and committed (mandatory); the small deltas across PBR/Standard scenes are the expected ~0.1 KB record of the inlined clip WGSL.

Notes

  • No public API changes; no golden references or existing ceilings modified.
  • Node Material behavior is unchanged (it already honored setClipPlane).

ryantrem and others added 3 commits July 7, 2026 17:30
Built-in PBR and Standard materials previously ignored the scene clip
plane set via setClipPlane; only Node Material's ClipPlanesBlock read
scene.clipPlane. Thread the clip plane into both fragment shaders so
setClipPlane clips built-in materials, matching Babylon.js and Lite's
Node Material.

Approach A (this branch): PBR uses a compile-gated dynamic import
(pbr-clip-wgsl.ts + PBR_HAS_CLIP_PLANE flag), mirroring the fog
precedent, so non-clipping PBR scenes bundle zero clip shader bytes.
Standard emits an inline runtime-gated discard (no-op when the UBO
clip plane is (0,0,0,0)), mirroring Standard's fog.

Adds parity scene264 (Standard + PBR spheres sliced by one clip plane),
BJS reference, spec, thumbnail, and per-scene bundle manifests.

Note: the PBR dynamic-import guard JS grows the shared pbr-renderable
chunk ~0.2 KB on every PBR scene, tipping 11 tight-ceiling scenes over.
Retained here for A/B comparison against an inline-only alternative.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Switch the PBR scene clip plane from the compile-gated dynamic-import
mechanism (Approach A) to an inline runtime-gated discard, matching how
Standard already does it and how both families treat cheap always-on
scene state.

Removed: PBR_HAS_CLIP_PLANE flag bit, pbr-clip-wgsl.ts module, the
scene.clipPlane dynamic import in pbr-renderable, the sceneFeatures OR,
and the _clipBlock threading through pbr-compose/pbr-template. Replaced
with a single unconditional WGSL line emitted at the top of the PBR
fragment main; it is a no-op when the UBO clip plane is (0,0,0,0).

Motivation: the dynamic-import guard/flag/threading JS added ~0.2 KB to
the shared pbr-renderable chunk that EVERY PBR scene ships, tipping 11
tight-ceiling scenes over their bundle-size limits. The inline literal
costs ~0.1 KB in that shared chunk instead, so all 208 bundle-size
ceilings pass with no ceiling changes. scene264 parity is unchanged
(MAD=0.001) since both approaches inject identical shader WGSL.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 8, 2026 01:20
@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 0a94969d..267d003d 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4937,7 +4937,6 @@ export interface ShaderMaterialOptions {
     readonly depthOnlyFragment?: boolean;
     // (undocumented)
     readonly depthWrite?: boolean;
-    // (undocumented)
     readonly fragmentSource: string;
     // (undocumented)
     readonly name?: string;
@@ -4952,7 +4951,6 @@ export interface ShaderMaterialOptions {
     readonly transmissive?: boolean;
     // (undocumented)
     readonly uniforms?: readonly ShaderUniformOption[];
-    // (undocumented)
     readonly vertexSource: string;
 }

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.

Pull request overview

This PR fixes a Babylon.js parity gap where setClipPlane only affected Node Material: it threads scene.clipPlane from the scene UBO into the built-in PBR and Standard fragment shaders and discards clipped fragments so those material families are properly clipped.

Changes:

  • Add a scene clip-plane discard test at the top of the built-in Standard and PBR fragment main, driven by scene.clipPlane.
  • Document clip-plane behavior: built-in materials honor it automatically; ShaderMaterial must opt in.
  • Add new parity coverage via Scene 264 and update bundle-size per-scene manifests to reflect the shader-code change.

Reviewed changes

Copilot reviewed 169 out of 170 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/lite/parity/scenes/scene264-clip-plane-materials.spec.ts Adds parity test validating clip planes affect both Standard and PBR.
scene-config.json Registers Scene 264 with MAD thresholds and bundle-size ceiling.
packages/babylon-lite/src/scene/scene-ubo-extras.ts Updates setClipPlane JSDoc to clarify which materials honor clip planes automatically.
packages/babylon-lite/src/material/standard/standard-template.ts Injects clip-plane discard into Standard fragment shader.
packages/babylon-lite/src/material/pbr/pbr-template.ts Injects clip-plane discard into PBR fragment shader.
packages/babylon-lite/src/material/shader/shader-material.ts Documents how ShaderMaterial authors can manually apply scene.clipPlane.
lab/lite/src/lite/scene264.ts Adds Lite Scene 264 demo using Standard + PBR materials with a clip plane.
lab/lite/src/bjs/scene264.ts Adds Babylon.js reference implementation for Scene 264.
lab/lite/scene264.html Adds dev HTML entry point for Lite Scene 264.
lab/lite/babylon-ref-scene264.html Adds dev HTML entry point for Babylon.js reference Scene 264.
lab/lite/bundle-scene264.html Adds bundle-mode HTML entry point for Lite Scene 264.
lab/lite/bundle-bjs-scene264.html Adds bundle-mode HTML entry point for Babylon.js Scene 264.
lab/public/bundle/manifest/scene264.json Adds bundle-size baseline manifest for the new Scene 264.
lab/public/bundle/manifest/scene1.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene2.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene3.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene4.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene5.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene6.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene7.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene8.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene9.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene10.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene11.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene12.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene13.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene14.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene15.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene16.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene17.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene18.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene19.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene20.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene21.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene22.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene23.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene24.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene25.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene26.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene27.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene28.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene29.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene30.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene31.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene32.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene33.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene34.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene35.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene36.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene37.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene38.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene39.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene40.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene41.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene42.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene43.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene44.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene45.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene46.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene47.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene48.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene49.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene52.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene53.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene54.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene56.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene57.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene59.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene66.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene73.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene75.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene84.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene90.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene91.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene94.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene95.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene98.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene99.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene100.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene101.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene102.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene103.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene104.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene105.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene106.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene110.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene111.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene112.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene113.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene114.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene115.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene116.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene128.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene129.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene141.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene142.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene143.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene144.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene145.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene146.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene147.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene148.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene149.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene150.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene151.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene152.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene154.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene155.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene156.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene157.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene158.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene164.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene170.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene171.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene172.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene173.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene174.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene175.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene176.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene177.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene178.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene179.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene200.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene201.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene202.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene203.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene204.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene205.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene206.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene207.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene209.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene210.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene211.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene212.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene213.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene214.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene215.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene216.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene217.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene218.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene219.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene221.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene222.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene223.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene224.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene225.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene227.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene228.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene229.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene240.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene241.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene242.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene243.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene244.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene245.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene246.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene247.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene248.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene249.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene251.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene252.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene253.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene254.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene255.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene257.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene258.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene259.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene260.json Updates bundle-size baseline after shader change.
lab/public/bundle/manifest/scene261.json Updates bundle-size baseline after shader change.

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

Comment thread tests/lite/parity/scenes/scene264-clip-plane-materials.spec.ts
Comment thread packages/babylon-lite/src/material/standard/standard-template.ts Outdated
Addresses PR #386 Copilot review comments:
- Force-add the gitignored scene264 parity golden
  (reference/lite/scene264-clip-plane-materials/babylon-ref-golden.png)
  so CI's compareImages() can load it; previously untracked.
- Minify the inlined Standard clip-plane WGSL (drop whitespace) to match
  the PBR block and GUIDANCE's minimal-whitespace rule for hot shared
  shader paths. Whitespace-only; render output and bundle sizes unchanged
  (per-scene manifests unaffected at 0.1 KB precision).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 10 — PBR Rough Sphere
scene10
53 KB 52 KB +1 KB
Scene 15 — SpotLights + Ground
scene15
48 KB 47 KB +1 KB
Scene 42 — Physics Clone Pre-Step
scene42
52 KB 51 KB +1 KB
Scene 47 — Physics Heightfield
scene47
93 KB 92 KB +1 KB
Scene 75 — Effect RTT Sphere
scene75
51 KB 50 KB +1 KB
Scene 91 — CSG2 Operations
scene91
59 KB 58 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 171 - Navigation Crowd Path
scene171
97 KB 96 KB +1 KB
Scene 175 - Navigation Raycast
scene175
96 KB 95 KB +1 KB
Scene 218 — Vertex Animation Texture (VAT)
scene218
93 KB 92 KB +1 KB
Scene 261 — Temporal Anti-Aliasing
scene261
55 KB 54 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 0a94969d..267d003d 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4937,7 +4937,6 @@ export interface ShaderMaterialOptions {
     readonly depthOnlyFragment?: boolean;
     // (undocumented)
     readonly depthWrite?: boolean;
-    // (undocumented)
     readonly fragmentSource: string;
     // (undocumented)
     readonly name?: string;
@@ -4952,7 +4951,6 @@ export interface ShaderMaterialOptions {
     readonly transmissive?: boolean;
     // (undocumented)
     readonly uniforms?: readonly ShaderUniformOption[];
-    // (undocumented)
     readonly vertexSource: string;
 }

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 10 — PBR Rough Sphere
scene10
53 KB 52 KB +1 KB
Scene 15 — SpotLights + Ground
scene15
48 KB 47 KB +1 KB
Scene 42 — Physics Clone Pre-Step
scene42
52 KB 51 KB +1 KB
Scene 47 — Physics Heightfield
scene47
93 KB 92 KB +1 KB
Scene 75 — Effect RTT Sphere
scene75
51 KB 50 KB +1 KB
Scene 91 — CSG2 Operations
scene91
59 KB 58 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 171 - Navigation Crowd Path
scene171
97 KB 96 KB +1 KB
Scene 175 - Navigation Raycast
scene175
96 KB 95 KB +1 KB
Scene 218 — Vertex Animation Texture (VAT)
scene218
93 KB 92 KB +1 KB
Scene 261 — Temporal Anti-Aliasing
scene261
55 KB 54 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260708.3 - merge @ 5a6f67e

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

📋 parity — Test Report

View full Playwright report

Build 20260708.3 · merge @ 5a6f67e

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

📋 perf — Test Report

View full Playwright report

Build 20260708.3 · merge @ 5a6f67e

The inline always-on clip discard `dot(worldPos, scene.clipPlane) > 0` is a
mathematical no-op when no plane is set, but on the CI cloud GPU the added
dot()+branch perturbed the shader compiler enough that non-clip PBR scenes
diverged from the Babylon.js parity reference (9 scenes) and regressed perf
(3 scenes).

Gate the clip line behind a new PBR_HAS_CLIP_PLANE scene-feature bit (threaded
via sceneFeatures, mirroring PBR_HAS_FOG) so a scene without a clip plane emits
a fragment shader byte-identical to before this feature. Only scenes that call
setClipPlane carry the ~55-byte WGSL literal, kept inline (no dynamic-import or
per-feature threading machinery) to stay within the tight PBR bundle ceilings.
Shortened the literal (vec4(v,1.), >0.) so the tightest PBR scene (210) stays
under its 77 KB ceiling.

Standard material keeps its always-on runtime-gated clip (matches its own fog
pattern and passed CI). Removes the dead pbr-clip-wgsl.ts Approach-A leftover.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ryantrem

ryantrem commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Pushed a follow-up (1a5508c4) that fixes the failing Parity (Cloud Browser) and Performance checks.

Root cause of the CI failures: the inline always-on clip discard dot(vec4(worldPos,1), scene.clipPlane) > 0 → discard is a mathematical no-op when no plane is set (UBO slot is (0,0,0,0)), and it stays a perfect no-op on real local GPUs. But on the CI cloud GPU (BrowserStack macOS) the extra dot()+branch perturbs the shader compiler just enough that the 9 non-clip PBR scenes diverged from the live BJS parity reference (which emits no clip line), and 3 perf scenes regressed.

Fix: compile-time gate the PBR clip line behind a new PBR_HAS_CLIP_PLANE scene-feature bit, threaded via sceneFeatures exactly like PBR_HAS_FOG. A scene without a clip plane now emits a fragment shader byte-identical to pre-feature master, so all 12 non-clip scenes match their references again; only scenes that call setClipPlane carry the WGSL literal.

On the earlier "inline vs dynamic-import" rationale: that tradeoff still holds — this keeps the literal inline (no dynamic import / new module / per-feature string threading), so it avoids Approach A's ~0.2 KB shared-chunk cost that breached 11 ceilings. The only change is that the inline literal is now gated by the feature bit instead of being always-on. Shortened the literal (vec4(v,1.), >0.) so the tightest PBR scene (210) stays under its 77 KB ceiling. No ceiling raises; bundle-size 208/208 pass locally.

Standard keeps its always-on runtime-gated clip — it never failed CI (matches its own fog vFogInfos.x > 0 pattern), so gating it would only add unnecessary bundle cost.

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 0a94969d..267d003d 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4937,7 +4937,6 @@ export interface ShaderMaterialOptions {
     readonly depthOnlyFragment?: boolean;
     // (undocumented)
     readonly depthWrite?: boolean;
-    // (undocumented)
     readonly fragmentSource: string;
     // (undocumented)
     readonly name?: string;
@@ -4952,7 +4951,6 @@ export interface ShaderMaterialOptions {
     readonly transmissive?: boolean;
     // (undocumented)
     readonly uniforms?: readonly ShaderUniformOption[];
-    // (undocumented)
     readonly vertexSource: string;
 }

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 10 — PBR Rough Sphere
scene10
53 KB 52 KB +1 KB
Scene 12 — PBR Shader Balls
scene12
104 KB 103 KB +1 KB
Scene 14 — Flight Helmet
scene14
90 KB 89 KB +1 KB
Scene 15 — SpotLights + Ground
scene15
48 KB 47 KB +1 KB
Scene 42 — Physics Clone Pre-Step
scene42
52 KB 51 KB +1 KB
Scene 47 — Physics Heightfield
scene47
93 KB 92 KB +1 KB
Scene 75 — Effect RTT Sphere
scene75
51 KB 50 KB +1 KB
Scene 91 — CSG2 Operations
scene91
59 KB 58 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 171 - Navigation Crowd Path
scene171
97 KB 96 KB +1 KB
Scene 175 - Navigation Raycast
scene175
96 KB 95 KB +1 KB
Scene 218 — Vertex Animation Texture (VAT)
scene218
93 KB 92 KB +1 KB
Scene 261 — Temporal Anti-Aliasing
scene261
55 KB 54 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260708.4 - merge @ 8a56f75

@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

📋 perf — Test Report

View full Playwright report

Build 20260708.4 · merge @ 8a56f75

1 similar comment
@bjsplat

bjsplat commented Jul 8, 2026

Copy link
Copy Markdown

📋 perf — Test Report

View full Playwright report

Build 20260708.4 · merge @ 8a56f75

@ryantrem ryantrem marked this pull request as draft July 8, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants