Skip to content

feat(standard): opt-in deform features (skeleton/vertex-color/uv-offset) + dynamic fog#338

Draft
PatrickRyanMS wants to merge 2 commits into
BabylonJS:masterfrom
PatrickRyanMS:standard-deform-features
Draft

feat(standard): opt-in deform features (skeleton/vertex-color/uv-offset) + dynamic fog#338
PatrickRyanMS wants to merge 2 commits into
BabylonJS:masterfrom
PatrickRyanMS:standard-deform-features

Conversation

@PatrickRyanMS

Copy link
Copy Markdown
Member

Summary

Two related, fully tree-shakable additions to StandardMaterial:

  1. Opt-in deform features — per-vertex color, skeletal skinning, and UV offset, exposed as import-triggered enablers (enableStandardVertexColor / enableStandardSkeleton / enableStandardUvOffset). They add zero bytes to scenes that do not import them.
  2. Dynamic fog — Standard fog WGSL is now dynamic-imported only when scene.fog is set, mirroring the existing PBR fog path (pbr-fog-wgsl).

Why fold fog away, and how it affects every Standard scene

Until now the Standard material's fog code (the calcFogFactor helper + the fog blend block) lived in the always-included standard-template, so every Standard scene shipped the fog shader — including the large majority that render no fog at all. PBR already gates its fog behind a dynamic import; this brings Standard in line.

The helper/block move into a new std-fog-wgsl module that standard-group-builder dynamic-imports only when scene.fog is set, threading the strings through the renderable into composeStandardShader (empty string for non-fog scenes, so the shader compiles identically). The net result is that fog bytes now ride only on scenes that actually use fog.

Bundle impact (measured against a fresh master build in the same environment)

Bucket Count Delta
Standard scenes that no longer carry fog WGSL ~81 **~ -1.1 KB each**
Scenes unchanged (deform opt-ins fold to zero) 126 0.0 KB
Fog scene (scene3) now loads the dynamic-fog chunk 1 +0.3 KB
Net across all existing scenes (already including scene3's increase) -86 KB

The one small increase

scene3 is a fog scene, so it now pulls in the dynamic-fog chunk, which carries ~0.3 KB of chunk-wrapper overhead versus inlining — the identical tradeoff PBR's fog path already makes. scene3 had zero ceiling headroom (54.0 KB), so its maxRawKB is raised 54 -> 54.5. Even after that bump, the branch is a net -86 KB reduction across the suite.

New parity scene

scene231 is a new in-code (no glTF) parity scene that exercises all three deform features together — skinning + per-vertex color + UV offset — with programmatically animated bones frozen at a deterministic frame. It renders pixel-identical to Babylon.js (MAD 0.000). (This adds new test-scene bundle content; it is not an engine-size change.)

Byte-neutrality note

The enableStandard* opt-ins are imported via their deep module path rather than re-exported through the index.ts barrel. Re-exporting them through the barrel perturbed terser export-name mangling in shared chunks and added bytes to every scene (including non-Standard scenes); the deep import keeps index.ts byte-identical to master.

Validation

  • Typecheck (babylon-lite + lab): clean.
  • Bundle-size ceilings: all pass.
  • Full visual parity: 418 pass — scene3 fog MAD 0.000, scene231 MAD 0.000; only the 3 machine-sensitive Havok physics scenes fail locally (environmental, unrelated to this change).
  • The tracked per-scene bundle baseline (lab/public/bundle/manifest/<scene>.json) is regenerated for the 84 scenes whose size or runtime chunks moved, plus scene231, per docs/lite/architecture/38-bundle-size-tooling.md.

PatrickRyanMS and others added 2 commits June 29, 2026 12:10
…code scene231 (port onto upstream BabylonJS#300)

Reuses the validated integration of the Standard skeleton, vertex-color and uvOffset deform
features onto the current upstream base (0a556d3, BabylonJS#300), plus the in-code scene231 parity
scene (programmatic bone animation, MAD 0.000). Branches cleanly off upstream (yesterday's
local commit is not an ancestor).

Byte-neutrality: the enableStandard* opt-ins are exposed via the deep module path
(babylon-lite/material/standard/enable-standard-mesh-features.js), NOT re-exported through the
index.ts barrel. Re-exporting through the barrel perturbed Rollup/terser export-name mangling
in shared chunks, adding ~10 bytes to every scene (incl. non-Standard scenes); the deep import
keeps index.ts byte-identical to upstream so non-feature scenes don't shift. The remaining
~0.1KB shift on a few Standard scenes is the inherent terser shift from the in-pipeline hooks
(folds the feature code, but the source edit nudges mangling) and is offset by the fog
optimization in the next commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…o fog bytes

Ports the dynamic fog gating from the prior Branch A onto upstream BabylonJS#300, mirroring the PBR
fog path (pbr-fog-wgsl.ts). The fog `calcFogFactor` helper + blend block move out of the
always-included standard-template into a new std-fog-wgsl module that standard-group-builder
dynamic-imports ONLY when scene.fog is set; the strings are threaded through the renderable
into composeStandardShader (_fogHelper/_fogBlock, "" for non-fog scenes).

Effect vs a fresh upstream build (same env): 80+ scenes smaller, total -86 KB; the deform-hook
terser shift on non-fog Standard scenes is now offset (the ex-boundary scenes are ~1 KB
smaller). Fog scenes pay the dynamic-fog chunk-wrapper overhead (~+0.3 KB), the same tradeoff
PBR makes; scene3's ceiling is bumped 54 -> 54.5 to cover it (user-approved). Full visual
parity unchanged (418 passed; scene3 fog MAD 0.000); only the 3 machine-sensitive Havok
scenes fail as usual.

Regenerates the tracked per-scene bundle baseline (lab/public/bundle/manifest/<scene>.json)
for the 84 scenes whose raw size or runtime chunks moved on this branch, and adds scene231's
manifest, per docs/lite/architecture/38-bundle-size-tooling.md ("Commit the regenerated files
for any scene whose size or runtime chunks moved"). Removes the accidentally-committed
aggregate lab/public/bundle/manifest.json — a gitignored generated artifact that PR BabylonJS#294
replaced with the per-scene files and that must never be committed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PatrickRyanMS PatrickRyanMS requested a review from sebavan June 29, 2026 21:38
@bjsplat

bjsplat commented Jun 29, 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 873e78f3..285a0a39 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
@@ -5331,6 +5331,7 @@ export interface StandardMaterialProps extends Material {
     specularTexture: Texture2D | null;
     stencil?: StencilState;
     useLightmapAsShadowmap: boolean;
+    uvOffset?: [number, number];
     uvScale: [number, number];
 }

@PatrickRyanMS PatrickRyanMS self-assigned this Jun 29, 2026
@PatrickRyanMS PatrickRyanMS added the enhancement New feature or request label Jun 29, 2026
@PatrickRyanMS PatrickRyanMS requested a review from RaananW June 29, 2026 22:01
@sebavan sebavan requested review from Popov72 and removed request for RaananW June 29, 2026 22:01
@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Bundle Size Changes

Decreases

Package Current Master Change
Scene 102 — Physics Raycast Filtering
scene102
58 KB 60 KB -2 KB
Scene 116 — Shadow Depth Materials
scene116
75 KB 77 KB -2 KB
Scene 141 — ESM Material Casters
scene141
122 KB 124 KB -2 KB
Scene 222 — Composite Gizmos
scene222
110 KB 112 KB -2 KB
Scene 261 — Temporal Anti-Aliasing
scene261
53 KB 55 KB -2 KB
Scene 2 — Sphere
scene2
46 KB 47 KB -1 KB
Scene 4 — Shadows
scene4
72 KB 73 KB -1 KB
Scene 15 — SpotLights + Ground
scene15
46 KB 47 KB -1 KB
Scene 16 — Thin Instances
scene16
48 KB 49 KB -1 KB
Scene 17 — PBR + Std TI
scene17
85 KB 86 KB -1 KB
Scene 18 — PCF Shadows
scene18
60 KB 61 KB -1 KB
Scene 22 — PBR Shadows
scene22
97 KB 98 KB -1 KB
Scene 24 — Hill Valley
scene24
58 KB 59 KB -1 KB
Scene 25 — KTX Texture
scene25
51 KB 52 KB -1 KB
Scene 36 — Basis Universal Texture
scene36
51 KB 52 KB -1 KB
Scene 38 — Procedural Builders
scene38
60 KB 61 KB -1 KB
Scene 40 — Physics
scene40
49 KB 50 KB -1 KB
Scene 41 — Physics Shape Debug Viewer
scene41
92 KB 93 KB -1 KB
Scene 42 — Physics Clone Pre-Step
scene42
50 KB 51 KB -1 KB
Scene 43 — Parametric Proximity Path
scene43
57 KB 58 KB -1 KB
Scene 44 — Physics Sleeping Towers
scene44
49 KB 50 KB -1 KB
Scene 45 — Physics Collision Filtering
scene45
50 KB 51 KB -1 KB
Scene 46 — Physics Constraints
scene46
53 KB 54 KB -1 KB
Scene 47 — Physics Heightfield
scene47
91 KB 92 KB -1 KB
Scene 48 — Physics Center of Mass
scene48
53 KB 54 KB -1 KB
Scene 49 — Physics Shape Queries
scene49
92 KB 93 KB -1 KB
Scene 52 — HUD on 3D
scene52
56 KB 57 KB -1 KB
Scene 53 — Depth-Hosted Sprites Mixed With 3D
scene53
57 KB 58 KB -1 KB
Scene 54 — Facing Billboards
scene54
59 KB 60 KB -1 KB
Scene 56 — Axis-Locked Billboards
scene56
59 KB 60 KB -1 KB
Scene 57 — Cutout Billboards
scene57
59 KB 60 KB -1 KB
Scene 59 — Billboard Sprite Animation
scene59
62 KB 63 KB -1 KB
Scene 75 — Effect RTT Sphere
scene75
49 KB 50 KB -1 KB
Scene 84 — NME Fragment Screen
scene84
84 KB 85 KB -1 KB
Scene 90 — CSG Operations
scene90
58 KB 59 KB -1 KB
Scene 91 — CSG2 Operations
scene91
58 KB 59 KB -1 KB
Scene 94 — Billboard Custom Shader (params tint)
scene94
63 KB 64 KB -1 KB
Scene 95 — Billboard Custom Shader (palette remap)
scene95
64 KB 65 KB -1 KB
Scene 98 — Billboard Additive Blend
scene98
59 KB 60 KB -1 KB
Scene 100 — Physics Collision Event
scene100
49 KB 50 KB -1 KB
Scene 101 — Physics Trigger Volume
scene101
53 KB 54 KB -1 KB
Scene 103 — Thin-Instance Raycast Picking
scene103
61 KB 62 KB -1 KB
Scene 104 — Physics Character Controller
scene104
101 KB 102 KB -1 KB
Scene 105 — Character Controller + Moving Platform
scene105
101 KB 102 KB -1 KB
Scene 106 — Prestep × Motion Types
scene106
50 KB 51 KB -1 KB
Scene 110 — RTT with material override
scene110
50 KB 51 KB -1 KB
Scene 111 — Light Selection Stress Test
scene111
134 KB 135 KB -1 KB
Scene 113 — Picking Precision
scene113
62 KB 63 KB -1 KB
Scene 115 — Alien Picking Frame 100
scene115
125 KB 126 KB -1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
82 KB 83 KB -1 KB
Scene 142 — Post-process Viewports
scene142
60 KB 61 KB -1 KB
Scene 145 — Geometry Renderer Task
scene145
88 KB 89 KB -1 KB
Scene 150 — Manual X Slide Animation
scene150
54 KB 55 KB -1 KB
Scene 151 — Manual Transform Animation
scene151
54 KB 55 KB -1 KB
Scene 154 - Step Time Animation
scene154
55 KB 56 KB -1 KB
Scene 155 — Manual Weighted Animation Blend
scene155
57 KB 58 KB -1 KB
Scene 156 — Manual Cross-Fade Animation
scene156
58 KB 59 KB -1 KB
Scene 170 - Navigation Basic
scene170
51 KB 52 KB -1 KB
Scene 171 - Navigation Crowd Path
scene171
95 KB 96 KB -1 KB
Scene 172 - Navigation Obstacles
scene172
59 KB 60 KB -1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
61 KB 62 KB -1 KB
Scene 174 - Navigation Off-Mesh Connections
scene174
96 KB 97 KB -1 KB
Scene 175 - Navigation Raycast
scene175
94 KB 95 KB -1 KB
Scene 200 - LWR Demo (HPM off, FO off)
scene200
46 KB 47 KB -1 KB
Scene 201 - LWR Demo (HPM on, FO on)
scene201
48 KB 49 KB -1 KB
Scene 202 - LWR Point Light
scene202
48 KB 49 KB -1 KB
Scene 203 - LWR Spot Light
scene203
49 KB 50 KB -1 KB
Scene 204 - LWR Thin Instances
scene204
50 KB 51 KB -1 KB
Scene 205 - LWR Facing Billboards
scene205
61 KB 62 KB -1 KB
Scene 206 - LWR Cutout Billboards
scene206
61 KB 62 KB -1 KB
Scene 207 - LWR Directional Shadows
scene207
59 KB 60 KB -1 KB
Scene 209 — LWR Physics
scene209
53 KB 54 KB -1 KB
Scene 214 — Cascaded Shadow Maps
scene214
67 KB 68 KB -1 KB
Scene 217 — Material Plugin (BlackAndWhite)
scene217
77 KB 78 KB -1 KB
Scene 221 — Pointer Drags
scene221
99 KB 100 KB -1 KB
Scene 223 — Camera + Light Gizmos
scene223
63 KB 64 KB -1 KB
Scene 224 — Bounding Box Gizmo
scene224
81 KB 82 KB -1 KB
Scene 225 — Geospatial Camera
scene225
57 KB 58 KB -1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
47 KB 48 KB -1 KB
Scene 228 — Multi-Canvas (Different Scenes)
scene228
49 KB 50 KB -1 KB
Scene 252 — StandardMaterial Morph Target
scene252
48 KB 49 KB -1 KB

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

@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260629.11 - merge @ 9eee93c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants