@babylonjs/lite 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/index.js +512 -512
  2. package/dist/index.js.map +1 -1
  3. package/index.d.ts +829 -28
  4. package/lib/audio/analyzer.js +65 -0
  5. package/lib/audio/analyzer.js.map +1 -0
  6. package/lib/audio/audio-bus.js +38 -0
  7. package/lib/audio/audio-bus.js.map +1 -0
  8. package/lib/audio/audio-engine.js +188 -0
  9. package/lib/audio/audio-engine.js.map +1 -0
  10. package/lib/audio/audio-fetch.js +18 -0
  11. package/lib/audio/audio-fetch.js.map +1 -0
  12. package/lib/audio/audio-param.js +96 -0
  13. package/lib/audio/audio-param.js.map +1 -0
  14. package/lib/audio/audio-signal.js +46 -0
  15. package/lib/audio/audio-signal.js.map +1 -0
  16. package/lib/audio/bus.js +33 -0
  17. package/lib/audio/bus.js.map +1 -0
  18. package/lib/audio/host-types.js +2 -0
  19. package/lib/audio/host-types.js.map +1 -0
  20. package/lib/audio/index.js +12 -0
  21. package/lib/audio/index.js.map +1 -0
  22. package/lib/audio/sound-buffer.js +59 -0
  23. package/lib/audio/sound-buffer.js.map +1 -0
  24. package/lib/audio/sound-source.js +57 -0
  25. package/lib/audio/sound-source.js.map +1 -0
  26. package/lib/audio/sound-sub-graph.js +72 -0
  27. package/lib/audio/sound-sub-graph.js.map +1 -0
  28. package/lib/audio/spatial.js +466 -0
  29. package/lib/audio/spatial.js.map +1 -0
  30. package/lib/audio/static-sound.js +313 -0
  31. package/lib/audio/static-sound.js.map +1 -0
  32. package/lib/audio/stereo.js +40 -0
  33. package/lib/audio/stereo.js.map +1 -0
  34. package/lib/audio/streaming-sound.js +377 -0
  35. package/lib/audio/streaming-sound.js.map +1 -0
  36. package/lib/audio/unmute-ui.js +72 -0
  37. package/lib/audio/unmute-ui.js.map +1 -0
  38. package/lib/audio/visualizer.js +101 -0
  39. package/lib/audio/visualizer.js.map +1 -0
  40. package/lib/camera/geospatial-camera-controls.js +22 -0
  41. package/lib/camera/geospatial-camera-controls.js.map +1 -1
  42. package/lib/camera/geospatial-camera-fly.js +2 -1
  43. package/lib/camera/geospatial-camera-fly.js.map +1 -1
  44. package/lib/effect/effect-renderer.js +1 -1
  45. package/lib/effect/effect-renderer.js.map +1 -1
  46. package/lib/engine/engine.js +1 -1
  47. package/lib/index.js +15 -1
  48. package/lib/index.js.map +1 -1
  49. package/lib/light/types.js.map +1 -1
  50. package/lib/loader-gltf/animation-pointer-basecolor.js +25 -0
  51. package/lib/loader-gltf/animation-pointer-basecolor.js.map +1 -0
  52. package/lib/loader-gltf/animation-pointer-ext.js +244 -0
  53. package/lib/loader-gltf/animation-pointer-ext.js.map +1 -0
  54. package/lib/loader-gltf/animation-pointer-lights.js +46 -0
  55. package/lib/loader-gltf/animation-pointer-lights.js.map +1 -0
  56. package/lib/loader-gltf/animation-pointer.js +4 -1
  57. package/lib/loader-gltf/animation-pointer.js.map +1 -1
  58. package/lib/loader-gltf/gltf-animation.js +5 -3
  59. package/lib/loader-gltf/gltf-animation.js.map +1 -1
  60. package/lib/loader-gltf/gltf-color-normalize.js +10 -1
  61. package/lib/loader-gltf/gltf-color-normalize.js.map +1 -1
  62. package/lib/loader-gltf/gltf-feature-animation-pointer.js +67 -47
  63. package/lib/loader-gltf/gltf-feature-animation-pointer.js.map +1 -1
  64. package/lib/loader-gltf/gltf-feature-lights-punctual.js +51 -9
  65. package/lib/loader-gltf/gltf-feature-lights-punctual.js.map +1 -1
  66. package/lib/loader-gltf/gltf-feature-primitive.js +20 -0
  67. package/lib/loader-gltf/gltf-feature-primitive.js.map +1 -0
  68. package/lib/loader-gltf/gltf-feature-registry.js +25 -0
  69. package/lib/loader-gltf/gltf-feature-registry.js.map +1 -1
  70. package/lib/loader-gltf/gltf-feature-skeleton.js +18 -3
  71. package/lib/loader-gltf/gltf-feature-skeleton.js.map +1 -1
  72. package/lib/loader-gltf/gltf-interleave.js +3 -2
  73. package/lib/loader-gltf/gltf-interleave.js.map +1 -1
  74. package/lib/loader-gltf/gltf-light-pointer-state.js +18 -0
  75. package/lib/loader-gltf/gltf-light-pointer-state.js.map +1 -0
  76. package/lib/loader-gltf/gltf-parser.js +7 -1
  77. package/lib/loader-gltf/gltf-parser.js.map +1 -1
  78. package/lib/loader-gltf/gltf-pbr-builder-ext.js +1 -1
  79. package/lib/loader-gltf/gltf-pbr-builder-ext.js.map +1 -1
  80. package/lib/loader-gltf/gltf-pbr-builder.js +1 -1
  81. package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
  82. package/lib/loader-gltf/gltf-sampler-denorm.js +20 -0
  83. package/lib/loader-gltf/gltf-sampler-denorm.js.map +1 -0
  84. package/lib/loader-gltf/gltf-sampler-desc.js +11 -2
  85. package/lib/loader-gltf/gltf-sampler-desc.js.map +1 -1
  86. package/lib/loader-gltf/gltf-uv-denorm.js +28 -0
  87. package/lib/loader-gltf/gltf-uv-denorm.js.map +1 -0
  88. package/lib/loader-gltf/load-gltf.js +15 -6
  89. package/lib/loader-gltf/load-gltf.js.map +1 -1
  90. package/lib/material/material-rebuild.js +4 -0
  91. package/lib/material/material-rebuild.js.map +1 -1
  92. package/lib/material/mesh-features.js +8 -1
  93. package/lib/material/mesh-features.js.map +1 -1
  94. package/lib/material/pbr/fragments/reflectance-fragment.js +1 -1
  95. package/lib/material/pbr/fragments/reflectance-fragment.js.map +1 -1
  96. package/lib/material/pbr/fragments/refraction-rtt-fragment.js +1 -1
  97. package/lib/material/pbr/fragments/refraction-rtt-fragment.js.map +1 -1
  98. package/lib/material/pbr/pbr-pipeline.js +7 -3
  99. package/lib/material/pbr/pbr-pipeline.js.map +1 -1
  100. package/lib/material/pbr/pbr-primitive-resolver.js +34 -0
  101. package/lib/material/pbr/pbr-primitive-resolver.js.map +1 -0
  102. package/lib/material/pbr/pbr-renderable.js +1 -1
  103. package/lib/material/pbr/pbr-renderable.js.map +1 -1
  104. package/lib/material/shader/shader-material.js +9 -5
  105. package/lib/material/shader/shader-material.js.map +1 -1
  106. package/lib/material/shader/shader-thin-instance.js +1 -1
  107. package/lib/material/shader/shader-thin-instance.js.map +1 -1
  108. package/lib/material/standard/standard-renderable.js +1 -1
  109. package/lib/material/standard/standard-renderable.js.map +1 -1
  110. package/lib/mesh/mesh-dispose.js +1 -0
  111. package/lib/mesh/mesh-dispose.js.map +1 -1
  112. package/lib/mesh/thin-instance-cull-binding.js +15 -6
  113. package/lib/mesh/thin-instance-cull-binding.js.map +1 -1
  114. package/lib/post-process/taa.js +193 -0
  115. package/lib/post-process/taa.js.map +1 -0
  116. package/lib/scene/scene-core.js +1 -0
  117. package/lib/scene/scene-core.js.map +1 -1
  118. package/lib/scene/scene-material-swap.js +2 -0
  119. package/lib/scene/scene-material-swap.js.map +1 -1
  120. package/lib/shadow/csm-shadow-task-hooks.js +67 -9
  121. package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
  122. package/lib/sprite/billboard-custom-shader.js +32 -32
  123. package/lib/sprite/billboard-custom-shader.js.map +1 -1
  124. package/lib/sprite/billboard-pipeline.js +54 -56
  125. package/lib/sprite/billboard-pipeline.js.map +1 -1
  126. package/lib/sprite/custom-shader-core.js +1 -1
  127. package/lib/sprite/custom-shader-core.js.map +1 -1
  128. package/lib/sprite/shared/sprite-atlas.js +2 -2
  129. package/lib/sprite/shared/sprite-atlas.js.map +1 -1
  130. package/lib/sprite/sprite-2d-coverage-gamma.js +58 -0
  131. package/lib/sprite/sprite-2d-coverage-gamma.js.map +1 -0
  132. package/lib/sprite/sprite-2d-uvscroll.js +39 -0
  133. package/lib/sprite/sprite-2d-uvscroll.js.map +1 -0
  134. package/lib/sprite/sprite-2d.js +6 -36
  135. package/lib/sprite/sprite-2d.js.map +1 -1
  136. package/lib/sprite/sprite-coverage-gamma-hook.js +10 -0
  137. package/lib/sprite/sprite-coverage-gamma-hook.js.map +1 -0
  138. package/lib/sprite/sprite-custom-shader.js +2 -2
  139. package/lib/sprite/sprite-custom-shader.js.map +1 -1
  140. package/lib/sprite/sprite-pipeline.js +61 -73
  141. package/lib/sprite/sprite-pipeline.js.map +1 -1
  142. package/lib/sprite/sprite-renderable.js +5 -5
  143. package/lib/sprite/sprite-renderable.js.map +1 -1
  144. package/lib/sprite/sprite-renderer.js +4 -4
  145. package/lib/sprite/sprite-renderer.js.map +1 -1
  146. package/lib/sprite/sprite-scene.js +1 -1
  147. package/lib/sprite/sprite-scene.js.map +1 -1
  148. package/lib/text/_gpu/text-pipeline.js +1 -1
  149. package/lib/text/_gpu/text-pipeline.js.map +1 -1
  150. package/lib/text/text-renderer.js +3 -1
  151. package/lib/text/text-renderer.js.map +1 -1
  152. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"scene-core.js","sources":["../../../src/scene/scene-core.ts"],"sourcesContent":["import type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport { _vis, isRenderingContextRegistered, registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { SurfaceContext } from \"../engine/surface.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { LightBase } from \"../light/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { disposeMeshGpu } from \"../mesh/mesh-dispose.js\";\nimport { registerMeshScene, unregisterMeshScene, enqueueMaterialSwap } from \"./mesh-scene-registry.js\";\nimport { processMaterialSwaps } from \"./scene-material-swap.js\";\nimport type { AnimationGroup } from \"../animation/animation-group.js\";\nimport type { ShadowGenerator } from \"../shadow/shadow-generator.js\";\nimport type { FogConfig } from \"../material/standard/standard-material.js\";\nimport type { Renderable, PrePassRenderable, SceneUniformUpdater, MeshGroupBuilder } from \"../render/renderable.js\";\nimport type { TransformNode } from \"./transform-node.js\";\nimport type { SceneNode } from \"./scene-node.js\";\nimport type { EnvironmentTextures } from \"../loader-env/load-env.js\";\nimport type { FrameGraph } from \"../frame-graph/frame-graph.js\";\nimport { createFrameGraph, _appendTask } from \"../frame-graph/frame-graph.js\";\nimport { createRenderTask } from \"../frame-graph/render-task.js\";\nimport { createRenderTarget } from \"../engine/render-target.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\nimport type { SceneLightGpuState } from \"../render/lights-ubo.js\";\nimport type { ClusteredLightContainer } from \"../light/clustered.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\n\n/** Image processing configuration. */\nexport interface ImageProcessingConfig {\n exposure: number;\n contrast: number;\n toneMappingEnabled: boolean;\n /** \"standard\" (BJS TONEMAPPING_STANDARD, default) or \"aces\" (BJS TONEMAPPING_ACES). */\n toneMappingType?: \"standard\" | \"aces\";\n}\n\n/** A clipping plane expressed as the coefficients `[a, b, c, d]` of `a·x + b·y + c·z + d`. */\nexport type ClipPlane = readonly [number, number, number, number];\n\n/** Top-level scene context — pure state, no attached methods. */\nexport interface SceneContext extends RenderingContext {\n /** Surface this scene renders into. Set at scene-creation time and immutable\n * afterwards — the default render task is sized and MSAA-matched to this surface,\n * and `registerScene` attaches the scene to it. For the engine's primary surface\n * (the common single-canvas case) this is the engine itself. The owning engine is\n * reachable via `scene.surface.engine`. */\n readonly surface: SurfaceContext;\n clearColor: GPUColorDict;\n camera: Camera | null;\n lights: LightBase[];\n imageProcessing: ImageProcessingConfig;\n\n /** All meshes added to the scene (standard + PBR). */\n meshes: Mesh[];\n\n /** Animation groups loaded from glTF or created manually. */\n animationGroups: AnimationGroup[];\n\n /** Fog configuration. Null = no fog. */\n fog: FogConfig | null;\n\n /** Scene clip plane as (normal.x, normal.y, normal.z, d). Matches Babylon.js Plane `dot(worldPosition, plane) > 0` discard semantics. */\n clipPlane: ClipPlane | null;\n\n /** Shadow generators registered on this scene. */\n shadowGenerators: ShadowGenerator[];\n\n /** Background material primaryColor (linear RGB). Default from Babylon createDefaultEnvironment. */\n environmentPrimaryColor?: [number, number, number];\n\n /** Environment cubemap Y rotation in radians. */\n envRotationY?: number;\n\n /** Fixed delta time in ms for deterministic animation. 0 = use real rAF delta. */\n fixedDeltaMs: number;\n\n /** All renderables in this scene. The active frame-graph tasks bucket them\n * (opaque / direct / transparent) at bind time based on `isTransparent`, `_direct`, and `_transmissive`. */\n /** @internal */\n _renderables: Renderable[];\n /** @internal Pre-pass work (shadow maps, compute, etc.). */\n _prePasses: PrePassRenderable[];\n /** GaussianSplatting meshes attached to this scene. Populated by\n * `attachGaussianSplattingMesh`. Scene-core stays GS-agnostic apart from\n * this opaque registry (used by `gpu-picker` to iterate GS meshes without\n * scanning `_renderables`). */\n /** @internal */\n _gsMeshes: GaussianSplattingMesh[];\n /** @internal Scene uniform updaters (one per shared UBO). */\n _uniformUpdaters: SceneUniformUpdater[];\n /** @internal Opt-in feature writers for the SceneUniforms UBO (fog, clip plane, env SH).\n * Populated lazily via the scene-ubo-extras seam; run by the render task. */\n _sceneUboContributors?: ((data: Float32Array, scene: SceneContext) => void)[];\n /** @internal Per-frame callbacks run before rendering (animation, physics, etc.). */\n _beforeRender: ((deltaMs: number) => void)[];\n /** @internal Deferred builders — registered by loaders/factories, run once at startEngine(). */\n _deferredBuilders: (() => void | Promise<void>)[];\n /** @internal Mesh group registry — maps builder to its mesh list (internal bookkeeping). */\n _groups: Map<MeshGroupBuilder, Mesh[]>;\n\n // ─── Dispose infrastructure ────────────────────────────────\n /** @internal Shared cleanup callbacks (scene UBOs, lights UBOs, etc.). Registered by builders. */\n _disposables: (() => void)[];\n /** @internal Per-mesh cleanup callbacks (mesh UBOs, bind groups). For material swap + dispose. */\n _meshDisposables: Map<Mesh, (() => void)[]>;\n /** @internal Meshes whose material was changed via setter — drained before each render frame. */\n _materialSwapQueue: Mesh[];\n /** @internal Monotonic counter bumped when the renderable list changes (add/remove/rebuild). */\n _renderableVersion: number;\n /** True once the initial deferred build (buildScene) has run. Meshes added after\n * this point are materialized via the per-frame swap drain rather than the\n * boot-only deferred-builder path. */\n /** @internal */\n _built: boolean;\n\n // ─── Stashed internal state (typed to avoid `as any` casts) ────\n /** @internal */\n _envTextures?: EnvironmentTextures;\n /** @internal Scene-owned shared LightsUniforms UBO state (group 0 binding 1). */\n _lightGpuState?: SceneLightGpuState;\n\n /** Frame graph driving this scene's rendering. Created eagerly by\n * `createSceneContext` with a default `RenderTask` that mirrors\n * `_renderables` into the swapchain. User code may add additional tasks\n * (offscreen RTTs, post-FX, UI overlays, etc.). */\n /** @internal */\n _frameGraph: FrameGraph;\n\n /** @internal Optional clustered point-light container. Only populated by the clustered-light extension API. */\n _clusteredLightContainer?: ClusteredLightContainer;\n /** @internal Updates clustered light cells for the camera used by the current render pass. */\n _clusteredLightUpdater?: (camera: Camera | null | undefined, targetWidth: number, targetHeight: number) => void;\n}\n\n/** Options passed to the scene-context factory. */\nexport interface SceneContextOptions {\n defaultRenderTask?: boolean;\n}\n\n/** Create an empty scene context bound to the given `surface`. The default render task\n * is built against the surface's format, MSAA configuration, and swapchain RT — the\n * scene is permanently bound to that surface. Pass `engine` directly (since\n * `EngineContext extends SurfaceContext`) for the common single-canvas case, or pass\n * an auxiliary surface created via `createSurface`. */\nexport function createSceneContext(surface: SurfaceContext, options?: SceneContextOptions): SceneContext {\n const eng = surface.engine;\n\n // Closures below capture `ctx` by-reference via this object.\n const ctxLocal: Omit<SceneContext, \"_frameGraph\"> = {\n surface,\n clearColor: { r: 0.2, g: 0.2, b: 0.3, a: 1.0 },\n camera: null,\n lights: [],\n meshes: [],\n animationGroups: [],\n fog: null,\n clipPlane: null,\n shadowGenerators: [],\n imageProcessing: { exposure: 1.0, contrast: 1.0, toneMappingEnabled: false },\n _renderables: [],\n _prePasses: [],\n _gsMeshes: [],\n _uniformUpdaters: [],\n fixedDeltaMs: 0,\n _beforeRender: [],\n _deferredBuilders: [],\n _groups: new Map(),\n _disposables: [],\n _meshDisposables: new Map(),\n _materialSwapQueue: [],\n _renderableVersion: 0,\n _built: false,\n _drawCallsPre: 0,\n\n _update(): void {\n // When the engine was created with `useFloatingOrigin: true`, mark\n // the active camera so `getViewMatrix` knows to zero its\n // translation column (the GPU view × world product is then the\n // eye-relative result the LWR offset trick produces). For non-LWR\n // engines `eng.useFloatingOrigin` is false and this is a single\n // boolean check per frame — the inner branch is dead.\n if (eng.useFloatingOrigin && ctx.camera && !ctx.camera._useFloatingOrigin) {\n ctx.camera._useFloatingOrigin = true;\n ctx.camera._viewVer = -1;\n ctx.camera._vpVer = -1;\n }\n const d = ctx.fixedDeltaMs > 0 ? ctx.fixedDeltaMs : eng._currentDelta;\n const encoder = eng._currentEncoder;\n let draws = 0;\n for (const cb of ctx._beforeRender) {\n cb(d);\n }\n if (ctx._materialSwapQueue.length > 0) {\n processMaterialSwaps(ctx);\n }\n for (const pp of ctx._prePasses) {\n draws += pp.execute(encoder, eng);\n }\n for (const u of ctx._uniformUpdaters) {\n u.update(eng);\n }\n ctx._drawCallsPre = draws;\n },\n _record(): number {\n return ctx._frameGraph.execute();\n },\n _resize(): void {\n // Canvas backing-store changed: rebuild the frame graph so canvas-sized\n // render targets get re-allocated at the new pixel size before the next record.\n ctx._frameGraph.build();\n },\n };\n\n const ctx = ctxLocal as SceneContext;\n // Eagerly attach the frame graph + a default swapchain render-pass task. The\n // graph drives all GPU work for this scene; user code can add more tasks\n // (offscreen RTTs, post-FX, UI overlays) before/after.\n const fg = createFrameGraph(eng);\n ctx._frameGraph = fg;\n if (options?.defaultRenderTask !== false) {\n // MSAA: render into an MSAA colour RT (which owns depth) and resolve into the\n // single-sample scRT. No MSAA: render straight into the colour-only\n // scRT with a task-owned single-sample depth buffer it builds/clears/frees.\n // All three reads (format / msaaSamples / scRT) come from the bound `surface`.\n const msaa = surface.msaaSamples > 1;\n const rt = msaa\n ? createRenderTarget({ lbl: \"scene-color\", format: surface.format, dFormat: \"depth24plus-stencil8\", samples: surface.msaaSamples, size: surface })\n : surface.scRT;\n const depth = msaa ? undefined : createRenderTarget({ lbl: \"scene-depth\", dFormat: \"depth24plus-stencil8\", samples: 1, size: surface });\n _appendTask(fg, createRenderTask({ name: \"scene\", rt, rst: msaa ? surface.scRT : undefined, depth, clrColor: ctx.clearColor }, eng, ctx));\n }\n ctx._disposables.push(() => fg.dispose());\n return ctx;\n}\n\n/** Register a callback to run before each rendered frame. */\nexport function onBeforeRender(scene: SceneContext, cb: (deltaMs: number) => void): void {\n (scene as SceneContext)._beforeRender.unshift(cb);\n}\n\n/** Register a callback to run when `disposeScene` is called. Used to tie\n * user-owned GPU resources (e.g. a `SpriteRenderer`) to the scene's lifetime. */\nexport function onSceneDispose(scene: SceneContext, cb: () => void): void {\n (scene as SceneContext)._disposables.push(cb);\n}\n\n/** Get the scene's frame graph. Always non-null — created in `createSceneContext`. */\nexport function getFrameGraph(scene: SceneContext): FrameGraph {\n return (scene as SceneContext)._frameGraph;\n}\n\nexport interface DeferredSceneRenderables {\n renderables: readonly Renderable[];\n dispose?: () => void;\n}\n\n/** @internal Register optional scene-hosted render work without teaching `addToScene` about the feature. */\nexport function addDeferredSceneRenderables(\n scene: SceneContext,\n build: (engine: EngineContext, scene: SceneContext) => DeferredSceneRenderables | Promise<DeferredSceneRenderables>\n): void {\n const ctx = scene as SceneContext;\n ctx._deferredBuilders.push(async () => {\n const built = await build(ctx.surface.engine, ctx);\n ctx._renderables.push(...built.renderables);\n if (built.dispose) {\n ctx._disposables.push(built.dispose);\n }\n });\n}\n\n/**\n * Adds an entity (mesh, light, camera, transform node, shadow generator, or asset container)\n * to the scene, dispatching on its type. Asset containers are unpacked and each contained\n * entity added recursively. Optional scene-hosted systems such as depth-hosted sprites\n * expose their own opt-in add functions so mesh-only scenes do not pay feature-specific\n * routing bytes here.\n * @param scene - The owning scene (pillar 4b: entities never reference the scene themselves).\n * @param entity - The entity (or asset container) to add.\n */\nexport function addToScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void {\n const ctx = scene as SceneContext;\n // AssetContainer from loadGltf / loadBabylon — process each field present\n if (\"entities\" in entity) {\n const result = entity as AssetContainer;\n for (const e of result.entities) {\n addToScene(scene, e);\n }\n if (result.clearColor) {\n ctx.clearColor = result.clearColor;\n }\n if (result.camera && !ctx.camera) {\n ctx.camera = result.camera;\n }\n if (result.animationGroups?.length) {\n const engine = ctx.surface.engine;\n const groups = result.animationGroups;\n ctx.animationGroups.push(...groups);\n ctx._beforeRender.push((deltaMs: number) => {\n for (const g of groups) {\n if (!g._stopped && g._ctrl) {\n g._ctrl.tick(deltaMs, engine);\n }\n }\n });\n }\n return;\n }\n if (\"_gpu\" in entity && \"material\" in entity) {\n const mesh = entity as unknown as Mesh;\n ctx.meshes.push(mesh);\n registerMeshScene(ctx, mesh);\n const build = mesh.material ? (mesh.material as unknown as { _buildGroup?: MeshGroupBuilder })._buildGroup : undefined;\n if (build) {\n let group = ctx._groups.get(build);\n if (!group) {\n group = [];\n ctx._groups.set(build, group);\n ctx._deferredBuilders.push(async () => {\n const result = await build(ctx, group!);\n ctx._renderables.push(...result.renderables);\n if (result.updater) {\n ctx._uniformUpdaters.push(result.updater);\n }\n });\n }\n group.push(mesh);\n // Added after the initial build: the deferred builder for this group has\n // already run (and only runs at boot), so materialize this mesh's renderable\n // through the per-frame material-swap drain instead.\n if (ctx._built) {\n enqueueMaterialSwap(ctx, mesh);\n }\n }\n } else if (\"lightType\" in entity) {\n ctx.lights.push(entity as LightBase);\n }\n // Recurse into children of meshes, lights, cameras — set parent links\n const kids = (entity as unknown as SceneNode).children;\n if (kids?.length) {\n for (const child of kids) {\n (child as unknown as SceneNode).parent = entity as unknown as SceneNode;\n addToScene(scene, child);\n }\n }\n}\n\n/** Release all GPU resources owned by this scene. */\nexport function disposeScene(scene: SceneContext): void {\n const ctx = scene as SceneContext;\n unregisterRenderingContext(ctx.surface, ctx);\n for (const fn of ctx._disposables) {\n fn();\n }\n for (const fns of ctx._meshDisposables.values()) {\n for (const fn of fns) {\n fn();\n }\n }\n ctx._meshDisposables.clear();\n for (const mesh of ctx.meshes) {\n // Free the mesh's shared GPU buffers only when this was its LAST owning scene.\n if (unregisterMeshScene(ctx, mesh)) {\n disposeMeshGpu(mesh);\n }\n }\n ctx.meshes.length = 0;\n ctx._renderables.length = 0;\n ctx._prePasses.length = 0;\n ctx._gsMeshes.length = 0;\n ctx._uniformUpdaters.length = 0;\n ctx._beforeRender.length = 0;\n ctx._deferredBuilders.length = 0;\n ctx._disposables.length = 0;\n ctx._materialSwapQueue.length = 0;\n ctx.lights.length = 0;\n ctx.animationGroups.length = 0;\n ctx.shadowGenerators.length = 0;\n ctx.camera = null;\n}\n\n/** @internal Run all deferred builders (called by registerScene's boot step before the first frame). */\nexport async function buildScene(scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n while (ctx._deferredBuilders.length > 0) {\n const builders = [...ctx._deferredBuilders];\n ctx._deferredBuilders = [];\n await Promise.all(builders.map(async (b) => b()));\n }\n ctx._materialSwapQueue.length = 0;\n ctx._renderableVersion++;\n ctx._built = true;\n}\n\n/**\n * Register a scene with the engine. Builds deferred work, sorts renderables by order,\n * and adds the scene to its bound surface's render list in overlay order. The scene is\n * always attached to `scene.surface` (which equals the engine itself in the\n * single-canvas case).\n */\nexport async function registerScene(scene: SceneContext): Promise<void> {\n const ctx = scene;\n const surface = ctx.surface;\n if (isRenderingContextRegistered(surface, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if (surface._renderingContexts.length > 0) {\n const overlay = await import(\"./swapchain-overlay.js\");\n overlay.configureSwapchainOverlayScene(surface, ctx);\n }\n registerRenderingContext(surface, ctx);\n}\n\n/**\n * Register a scene with the engine and install the scene-owned shadow frame-graph task.\n * Use only for scenes that generate shadow maps. Like {@link registerScene}, the scene\n * is attached to `scene.surface` (and its owning engine is `scene.surface.engine`).\n */\nexport async function registerSceneWithShadowSupport(scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n const surface = ctx.surface;\n if (isRenderingContextRegistered(surface, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await ensureShadowTask(surface.engine, ctx);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if (surface._renderingContexts.length > 0) {\n const overlay = await import(\"./swapchain-overlay.js\");\n overlay.configureSwapchainOverlayScene(surface, ctx);\n }\n registerRenderingContext(surface, ctx);\n}\n\nconst byOrder = (a: Renderable, b: Renderable): number => a.order - b.order;\n\nasync function ensureShadowTask(engine: EngineContext, scene: SceneContext): Promise<void> {\n const { createShadowTask } = await import(\"../frame-graph/shadow-task.js\");\n scene._frameGraph._tasks.unshift(createShadowTask(engine, scene));\n}\n\n/** Remove a previously-registered scene. Idempotent. Does not dispose scene resources.\n * The scene is always removed from `scene.surface`. */\nexport function unregisterScene(scene: SceneContext): void {\n unregisterRenderingContext(scene.surface, scene as SceneContext);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene-core.js","sources":["../../../src/scene/scene-core.ts"],"sourcesContent":["import type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport { _vis, isRenderingContextRegistered, registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { SurfaceContext } from \"../engine/surface.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { LightBase } from \"../light/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { disposeMeshGpu } from \"../mesh/mesh-dispose.js\";\nimport { registerMeshScene, unregisterMeshScene, enqueueMaterialSwap } from \"./mesh-scene-registry.js\";\nimport { processMaterialSwaps } from \"./scene-material-swap.js\";\nimport type { AnimationGroup } from \"../animation/animation-group.js\";\nimport type { ShadowGenerator } from \"../shadow/shadow-generator.js\";\nimport type { FogConfig } from \"../material/standard/standard-material.js\";\nimport type { Renderable, PrePassRenderable, SceneUniformUpdater, MeshGroupBuilder } from \"../render/renderable.js\";\nimport type { TransformNode } from \"./transform-node.js\";\nimport type { SceneNode } from \"./scene-node.js\";\nimport type { EnvironmentTextures } from \"../loader-env/load-env.js\";\nimport type { FrameGraph } from \"../frame-graph/frame-graph.js\";\nimport { createFrameGraph, _appendTask } from \"../frame-graph/frame-graph.js\";\nimport { createRenderTask } from \"../frame-graph/render-task.js\";\nimport { createRenderTarget } from \"../engine/render-target.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\nimport type { SceneLightGpuState } from \"../render/lights-ubo.js\";\nimport type { ClusteredLightContainer } from \"../light/clustered.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\n\n/** Image processing configuration. */\nexport interface ImageProcessingConfig {\n exposure: number;\n contrast: number;\n toneMappingEnabled: boolean;\n /** \"standard\" (BJS TONEMAPPING_STANDARD, default) or \"aces\" (BJS TONEMAPPING_ACES). */\n toneMappingType?: \"standard\" | \"aces\";\n}\n\n/** A clipping plane expressed as the coefficients `[a, b, c, d]` of `a·x + b·y + c·z + d`. */\nexport type ClipPlane = readonly [number, number, number, number];\n\n/** Top-level scene context — pure state, no attached methods. */\nexport interface SceneContext extends RenderingContext {\n /** Surface this scene renders into. Set at scene-creation time and immutable\n * afterwards — the default render task is sized and MSAA-matched to this surface,\n * and `registerScene` attaches the scene to it. For the engine's primary surface\n * (the common single-canvas case) this is the engine itself. The owning engine is\n * reachable via `scene.surface.engine`. */\n readonly surface: SurfaceContext;\n clearColor: GPUColorDict;\n camera: Camera | null;\n lights: LightBase[];\n imageProcessing: ImageProcessingConfig;\n\n /** All meshes added to the scene (standard + PBR). */\n meshes: Mesh[];\n\n /** Animation groups loaded from glTF or created manually. */\n animationGroups: AnimationGroup[];\n\n /** Fog configuration. Null = no fog. */\n fog: FogConfig | null;\n\n /** Scene clip plane as (normal.x, normal.y, normal.z, d). Matches Babylon.js Plane `dot(worldPosition, plane) > 0` discard semantics. */\n clipPlane: ClipPlane | null;\n\n /** Shadow generators registered on this scene. */\n shadowGenerators: ShadowGenerator[];\n\n /** Background material primaryColor (linear RGB). Default from Babylon createDefaultEnvironment. */\n environmentPrimaryColor?: [number, number, number];\n\n /** Environment cubemap Y rotation in radians. */\n envRotationY?: number;\n\n /** Fixed delta time in ms for deterministic animation. 0 = use real rAF delta. */\n fixedDeltaMs: number;\n\n /** All renderables in this scene. The active frame-graph tasks bucket them\n * (opaque / direct / transparent) at bind time based on `isTransparent`, `_direct`, and `_transmissive`. */\n /** @internal */\n _renderables: Renderable[];\n /** @internal Pre-pass work (shadow maps, compute, etc.). */\n _prePasses: PrePassRenderable[];\n /** GaussianSplatting meshes attached to this scene. Populated by\n * `attachGaussianSplattingMesh`. Scene-core stays GS-agnostic apart from\n * this opaque registry (used by `gpu-picker` to iterate GS meshes without\n * scanning `_renderables`). */\n /** @internal */\n _gsMeshes: GaussianSplattingMesh[];\n /** @internal Scene uniform updaters (one per shared UBO). */\n _uniformUpdaters: SceneUniformUpdater[];\n /** @internal Opt-in feature writers for the SceneUniforms UBO (fog, clip plane, env SH).\n * Populated lazily via the scene-ubo-extras seam; run by the render task. */\n _sceneUboContributors?: ((data: Float32Array, scene: SceneContext) => void)[];\n /** @internal Per-frame callbacks run before rendering (animation, physics, etc.). */\n _beforeRender: ((deltaMs: number) => void)[];\n /** @internal Deferred builders — registered by loaders/factories, run once at startEngine(). */\n _deferredBuilders: (() => void | Promise<void>)[];\n /** @internal Mesh group registry — maps builder to its mesh list (internal bookkeeping). */\n _groups: Map<MeshGroupBuilder, Mesh[]>;\n\n // ─── Dispose infrastructure ────────────────────────────────\n /** @internal Shared cleanup callbacks (scene UBOs, lights UBOs, etc.). Registered by builders. */\n _disposables: (() => void)[];\n /** @internal Per-mesh cleanup callbacks (mesh UBOs, bind groups). For material swap + dispose. */\n _meshDisposables: Map<Mesh, (() => void)[]>;\n /** @internal Meshes whose material was changed via setter — drained before each render frame. */\n _materialSwapQueue: Mesh[];\n /** @internal Monotonic counter bumped when the renderable list changes (add/remove/rebuild). */\n _renderableVersion: number;\n /** @internal Monotonic counter bumped ONLY when a material's renderables are rebuilt/swapped (material\n * swap drain or `rebuildMaterial`) — NOT on a geometry resize (which bumps `_renderableVersion` alone).\n * Lets consumers that cache material-view-derived GPU state (e.g. the CSM shadow tasks' no-color material\n * views) cheaply re-record on a geometry-only edit and only fully rebuild when a caster's material UBOs\n * were actually destroyed/recreated (which would otherwise leave their cached views dangling). */\n _materialEpoch: number;\n /** True once the initial deferred build (buildScene) has run. Meshes added after\n * this point are materialized via the per-frame swap drain rather than the\n * boot-only deferred-builder path. */\n /** @internal */\n _built: boolean;\n\n // ─── Stashed internal state (typed to avoid `as any` casts) ────\n /** @internal */\n _envTextures?: EnvironmentTextures;\n /** @internal Scene-owned shared LightsUniforms UBO state (group 0 binding 1). */\n _lightGpuState?: SceneLightGpuState;\n\n /** Frame graph driving this scene's rendering. Created eagerly by\n * `createSceneContext` with a default `RenderTask` that mirrors\n * `_renderables` into the swapchain. User code may add additional tasks\n * (offscreen RTTs, post-FX, UI overlays, etc.). */\n /** @internal */\n _frameGraph: FrameGraph;\n\n /** @internal Optional clustered point-light container. Only populated by the clustered-light extension API. */\n _clusteredLightContainer?: ClusteredLightContainer;\n /** @internal Updates clustered light cells for the camera used by the current render pass. */\n _clusteredLightUpdater?: (camera: Camera | null | undefined, targetWidth: number, targetHeight: number) => void;\n}\n\n/** Options passed to the scene-context factory. */\nexport interface SceneContextOptions {\n defaultRenderTask?: boolean;\n}\n\n/** Create an empty scene context bound to the given `surface`. The default render task\n * is built against the surface's format, MSAA configuration, and swapchain RT — the\n * scene is permanently bound to that surface. Pass `engine` directly (since\n * `EngineContext extends SurfaceContext`) for the common single-canvas case, or pass\n * an auxiliary surface created via `createSurface`. */\nexport function createSceneContext(surface: SurfaceContext, options?: SceneContextOptions): SceneContext {\n const eng = surface.engine;\n\n // Closures below capture `ctx` by-reference via this object.\n const ctxLocal: Omit<SceneContext, \"_frameGraph\"> = {\n surface,\n clearColor: { r: 0.2, g: 0.2, b: 0.3, a: 1.0 },\n camera: null,\n lights: [],\n meshes: [],\n animationGroups: [],\n fog: null,\n clipPlane: null,\n shadowGenerators: [],\n imageProcessing: { exposure: 1.0, contrast: 1.0, toneMappingEnabled: false },\n _renderables: [],\n _prePasses: [],\n _gsMeshes: [],\n _uniformUpdaters: [],\n fixedDeltaMs: 0,\n _beforeRender: [],\n _deferredBuilders: [],\n _groups: new Map(),\n _disposables: [],\n _meshDisposables: new Map(),\n _materialSwapQueue: [],\n _renderableVersion: 0,\n _materialEpoch: 0,\n _built: false,\n _drawCallsPre: 0,\n\n _update(): void {\n // When the engine was created with `useFloatingOrigin: true`, mark\n // the active camera so `getViewMatrix` knows to zero its\n // translation column (the GPU view × world product is then the\n // eye-relative result the LWR offset trick produces). For non-LWR\n // engines `eng.useFloatingOrigin` is false and this is a single\n // boolean check per frame — the inner branch is dead.\n if (eng.useFloatingOrigin && ctx.camera && !ctx.camera._useFloatingOrigin) {\n ctx.camera._useFloatingOrigin = true;\n ctx.camera._viewVer = -1;\n ctx.camera._vpVer = -1;\n }\n const d = ctx.fixedDeltaMs > 0 ? ctx.fixedDeltaMs : eng._currentDelta;\n const encoder = eng._currentEncoder;\n let draws = 0;\n for (const cb of ctx._beforeRender) {\n cb(d);\n }\n if (ctx._materialSwapQueue.length > 0) {\n processMaterialSwaps(ctx);\n }\n for (const pp of ctx._prePasses) {\n draws += pp.execute(encoder, eng);\n }\n for (const u of ctx._uniformUpdaters) {\n u.update(eng);\n }\n ctx._drawCallsPre = draws;\n },\n _record(): number {\n return ctx._frameGraph.execute();\n },\n _resize(): void {\n // Canvas backing-store changed: rebuild the frame graph so canvas-sized\n // render targets get re-allocated at the new pixel size before the next record.\n ctx._frameGraph.build();\n },\n };\n\n const ctx = ctxLocal as SceneContext;\n // Eagerly attach the frame graph + a default swapchain render-pass task. The\n // graph drives all GPU work for this scene; user code can add more tasks\n // (offscreen RTTs, post-FX, UI overlays) before/after.\n const fg = createFrameGraph(eng);\n ctx._frameGraph = fg;\n if (options?.defaultRenderTask !== false) {\n // MSAA: render into an MSAA colour RT (which owns depth) and resolve into the\n // single-sample scRT. No MSAA: render straight into the colour-only\n // scRT with a task-owned single-sample depth buffer it builds/clears/frees.\n // All three reads (format / msaaSamples / scRT) come from the bound `surface`.\n const msaa = surface.msaaSamples > 1;\n const rt = msaa\n ? createRenderTarget({ lbl: \"scene-color\", format: surface.format, dFormat: \"depth24plus-stencil8\", samples: surface.msaaSamples, size: surface })\n : surface.scRT;\n const depth = msaa ? undefined : createRenderTarget({ lbl: \"scene-depth\", dFormat: \"depth24plus-stencil8\", samples: 1, size: surface });\n _appendTask(fg, createRenderTask({ name: \"scene\", rt, rst: msaa ? surface.scRT : undefined, depth, clrColor: ctx.clearColor }, eng, ctx));\n }\n ctx._disposables.push(() => fg.dispose());\n return ctx;\n}\n\n/** Register a callback to run before each rendered frame. */\nexport function onBeforeRender(scene: SceneContext, cb: (deltaMs: number) => void): void {\n (scene as SceneContext)._beforeRender.unshift(cb);\n}\n\n/** Register a callback to run when `disposeScene` is called. Used to tie\n * user-owned GPU resources (e.g. a `SpriteRenderer`) to the scene's lifetime. */\nexport function onSceneDispose(scene: SceneContext, cb: () => void): void {\n (scene as SceneContext)._disposables.push(cb);\n}\n\n/** Get the scene's frame graph. Always non-null — created in `createSceneContext`. */\nexport function getFrameGraph(scene: SceneContext): FrameGraph {\n return (scene as SceneContext)._frameGraph;\n}\n\nexport interface DeferredSceneRenderables {\n renderables: readonly Renderable[];\n dispose?: () => void;\n}\n\n/** @internal Register optional scene-hosted render work without teaching `addToScene` about the feature. */\nexport function addDeferredSceneRenderables(\n scene: SceneContext,\n build: (engine: EngineContext, scene: SceneContext) => DeferredSceneRenderables | Promise<DeferredSceneRenderables>\n): void {\n const ctx = scene as SceneContext;\n ctx._deferredBuilders.push(async () => {\n const built = await build(ctx.surface.engine, ctx);\n ctx._renderables.push(...built.renderables);\n if (built.dispose) {\n ctx._disposables.push(built.dispose);\n }\n });\n}\n\n/**\n * Adds an entity (mesh, light, camera, transform node, shadow generator, or asset container)\n * to the scene, dispatching on its type. Asset containers are unpacked and each contained\n * entity added recursively. Optional scene-hosted systems such as depth-hosted sprites\n * expose their own opt-in add functions so mesh-only scenes do not pay feature-specific\n * routing bytes here.\n * @param scene - The owning scene (pillar 4b: entities never reference the scene themselves).\n * @param entity - The entity (or asset container) to add.\n */\nexport function addToScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void {\n const ctx = scene as SceneContext;\n // AssetContainer from loadGltf / loadBabylon — process each field present\n if (\"entities\" in entity) {\n const result = entity as AssetContainer;\n for (const e of result.entities) {\n addToScene(scene, e);\n }\n if (result.clearColor) {\n ctx.clearColor = result.clearColor;\n }\n if (result.camera && !ctx.camera) {\n ctx.camera = result.camera;\n }\n if (result.animationGroups?.length) {\n const engine = ctx.surface.engine;\n const groups = result.animationGroups;\n ctx.animationGroups.push(...groups);\n ctx._beforeRender.push((deltaMs: number) => {\n for (const g of groups) {\n if (!g._stopped && g._ctrl) {\n g._ctrl.tick(deltaMs, engine);\n }\n }\n });\n }\n return;\n }\n if (\"_gpu\" in entity && \"material\" in entity) {\n const mesh = entity as unknown as Mesh;\n ctx.meshes.push(mesh);\n registerMeshScene(ctx, mesh);\n const build = mesh.material ? (mesh.material as unknown as { _buildGroup?: MeshGroupBuilder })._buildGroup : undefined;\n if (build) {\n let group = ctx._groups.get(build);\n if (!group) {\n group = [];\n ctx._groups.set(build, group);\n ctx._deferredBuilders.push(async () => {\n const result = await build(ctx, group!);\n ctx._renderables.push(...result.renderables);\n if (result.updater) {\n ctx._uniformUpdaters.push(result.updater);\n }\n });\n }\n group.push(mesh);\n // Added after the initial build: the deferred builder for this group has\n // already run (and only runs at boot), so materialize this mesh's renderable\n // through the per-frame material-swap drain instead.\n if (ctx._built) {\n enqueueMaterialSwap(ctx, mesh);\n }\n }\n } else if (\"lightType\" in entity) {\n ctx.lights.push(entity as LightBase);\n }\n // Recurse into children of meshes, lights, cameras — set parent links\n const kids = (entity as unknown as SceneNode).children;\n if (kids?.length) {\n for (const child of kids) {\n (child as unknown as SceneNode).parent = entity as unknown as SceneNode;\n addToScene(scene, child);\n }\n }\n}\n\n/** Release all GPU resources owned by this scene. */\nexport function disposeScene(scene: SceneContext): void {\n const ctx = scene as SceneContext;\n unregisterRenderingContext(ctx.surface, ctx);\n for (const fn of ctx._disposables) {\n fn();\n }\n for (const fns of ctx._meshDisposables.values()) {\n for (const fn of fns) {\n fn();\n }\n }\n ctx._meshDisposables.clear();\n for (const mesh of ctx.meshes) {\n // Free the mesh's shared GPU buffers only when this was its LAST owning scene.\n if (unregisterMeshScene(ctx, mesh)) {\n disposeMeshGpu(mesh);\n }\n }\n ctx.meshes.length = 0;\n ctx._renderables.length = 0;\n ctx._prePasses.length = 0;\n ctx._gsMeshes.length = 0;\n ctx._uniformUpdaters.length = 0;\n ctx._beforeRender.length = 0;\n ctx._deferredBuilders.length = 0;\n ctx._disposables.length = 0;\n ctx._materialSwapQueue.length = 0;\n ctx.lights.length = 0;\n ctx.animationGroups.length = 0;\n ctx.shadowGenerators.length = 0;\n ctx.camera = null;\n}\n\n/** @internal Run all deferred builders (called by registerScene's boot step before the first frame). */\nexport async function buildScene(scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n while (ctx._deferredBuilders.length > 0) {\n const builders = [...ctx._deferredBuilders];\n ctx._deferredBuilders = [];\n await Promise.all(builders.map(async (b) => b()));\n }\n ctx._materialSwapQueue.length = 0;\n ctx._renderableVersion++;\n ctx._built = true;\n}\n\n/**\n * Register a scene with the engine. Builds deferred work, sorts renderables by order,\n * and adds the scene to its bound surface's render list in overlay order. The scene is\n * always attached to `scene.surface` (which equals the engine itself in the\n * single-canvas case).\n */\nexport async function registerScene(scene: SceneContext): Promise<void> {\n const ctx = scene;\n const surface = ctx.surface;\n if (isRenderingContextRegistered(surface, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if (surface._renderingContexts.length > 0) {\n const overlay = await import(\"./swapchain-overlay.js\");\n overlay.configureSwapchainOverlayScene(surface, ctx);\n }\n registerRenderingContext(surface, ctx);\n}\n\n/**\n * Register a scene with the engine and install the scene-owned shadow frame-graph task.\n * Use only for scenes that generate shadow maps. Like {@link registerScene}, the scene\n * is attached to `scene.surface` (and its owning engine is `scene.surface.engine`).\n */\nexport async function registerSceneWithShadowSupport(scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n const surface = ctx.surface;\n if (isRenderingContextRegistered(surface, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await ensureShadowTask(surface.engine, ctx);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if (surface._renderingContexts.length > 0) {\n const overlay = await import(\"./swapchain-overlay.js\");\n overlay.configureSwapchainOverlayScene(surface, ctx);\n }\n registerRenderingContext(surface, ctx);\n}\n\nconst byOrder = (a: Renderable, b: Renderable): number => a.order - b.order;\n\nasync function ensureShadowTask(engine: EngineContext, scene: SceneContext): Promise<void> {\n const { createShadowTask } = await import(\"../frame-graph/shadow-task.js\");\n scene._frameGraph._tasks.unshift(createShadowTask(engine, scene));\n}\n\n/** Remove a previously-registered scene. Idempotent. Does not dispose scene resources.\n * The scene is always removed from `scene.surface`. */\nexport function unregisterScene(scene: SceneContext): void {\n unregisterRenderingContext(scene.surface, scene as SceneContext);\n}\n"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ function processMaterialSwaps(scene) {
27
27
  if (!rebuild) {
28
28
  continue;
29
29
  }
30
+ mat._csmGen = (mat._csmGen ?? 0) + 1;
30
31
  const renderable = rebuild(scene, mesh);
31
32
  let i = scene._renderables.length;
32
33
  while (i > 0 && scene._renderables[i - 1].order > renderable.order) {
@@ -36,6 +37,7 @@ function processMaterialSwaps(scene) {
36
37
  }
37
38
  q.length = 0;
38
39
  scene._renderableVersion++;
40
+ scene._materialEpoch++;
39
41
  }
40
42
 
41
43
  export { processMaterialSwaps };
@@ -1 +1 @@
1
- {"version":3,"file":"scene-material-swap.js","sources":["../../../src/scene/scene-material-swap.ts"],"sourcesContent":["import type { SceneContext } from \"./scene-core.js\";\n\n/** @internal Drain _materialSwapQueue: dispose old resources and rebuild renderables. */\nexport function processMaterialSwaps(scene: SceneContext): void {\n const q = scene._materialSwapQueue;\n if (q.length === 0) {\n return;\n }\n const device = scene.surface.engine._device;\n for (const mesh of q) {\n const old = scene._meshDisposables.get(mesh);\n if (old) {\n scene._meshDisposables.delete(mesh);\n // These disposables free the OLD renderable's GPU resources (per-mesh/material UBOs, the\n // GPU-cull state buffers, texture releases). They must NOT run synchronously: the old buffers\n // may still be referenced by a frame already submitted to the GPU this tick, and destroying\n // them now hits the validation error \"Buffer used in submit while destroyed\" (seen when a\n // plugin / shadow-receiver variant change swaps a planted mesh's material — e.g. planting a\n // fern or agave). The new renderable is rebuilt below and replaces the old one, so nothing\n // records the old resources again; defer the teardown until the GPU has drained the\n // currently-submitted work (onSubmittedWorkDone). Mirrors resizeMeshGeometry.\n void device.queue\n .onSubmittedWorkDone()\n .then(() => {\n try {\n for (const fn of old) {\n fn();\n }\n } catch {\n // Device may have been lost/disposed before the deferred teardown ran.\n }\n })\n .catch(() => {});\n }\n\n const mat = mesh.material;\n const builder = mat?._buildGroup;\n if (!builder) {\n continue;\n }\n const rebuild = builder._rebuildSingle;\n if (!rebuild) {\n continue;\n }\n const renderable = rebuild(scene, mesh);\n // Insert by `order` so the renderable list stays sorted (frame-graph\n // tasks bucket opaque/direct/transparent at bind time).\n let i = scene._renderables.length;\n while (i > 0 && scene._renderables[i - 1]!.order > renderable.order) {\n i--;\n }\n scene._renderables.splice(i, 0, renderable);\n }\n q.length = 0;\n scene._renderableVersion++;\n}\n"],"names":[],"mappings":"AAGO,SAAS,qBAAqB,KAAA,EAA2B;AAC5D,EAAA,MAAM,IAAI,KAAA,CAAM,kBAAA;AAChB,EAAA,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AAChB,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,OAAA;AACpC,EAAA,KAAA,MAAW,QAAQ,CAAA,EAAG;AAClB,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,GAAA,EAAK;AACL,MAAA,KAAA,CAAM,gBAAA,CAAiB,OAAO,IAAI,CAAA;AASlC,MAAA,KAAK,MAAA,CAAO,KAAA,CACP,mBAAA,EAAoB,CACpB,KAAK,MAAM;AACR,QAAA,IAAI;AACA,UAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AAClB,YAAA,EAAA,EAAG;AAAA,UACP;AAAA,QACJ,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACJ,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACvB;AAEA,IAAA,MAAM,MAAM,IAAA,CAAK,QAAA;AACjB,IAAA,MAAM,UAAU,GAAA,EAAK,WAAA;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,UAAU,OAAA,CAAQ,cAAA;AACxB,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAGtC,IAAA,IAAI,CAAA,GAAI,MAAM,YAAA,CAAa,MAAA;AAC3B,IAAA,OAAO,CAAA,GAAI,KAAK,KAAA,CAAM,YAAA,CAAa,IAAI,CAAC,CAAA,CAAG,KAAA,GAAQ,UAAA,CAAW,KAAA,EAAO;AACjE,MAAA,CAAA,EAAA;AAAA,IACJ;AACA,IAAA,KAAA,CAAM,YAAA,CAAa,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,UAAU,CAAA;AAAA,EAC9C;AACA,EAAA,CAAA,CAAE,MAAA,GAAS,CAAA;AACX,EAAA,KAAA,CAAM,kBAAA,EAAA;AACV;;;;"}
1
+ {"version":3,"file":"scene-material-swap.js","sources":["../../../src/scene/scene-material-swap.ts"],"sourcesContent":["import type { SceneContext } from \"./scene-core.js\";\n\n/** @internal Drain _materialSwapQueue: dispose old resources and rebuild renderables. */\nexport function processMaterialSwaps(scene: SceneContext): void {\n const q = scene._materialSwapQueue;\n if (q.length === 0) {\n return;\n }\n const device = scene.surface.engine._device;\n for (const mesh of q) {\n const old = scene._meshDisposables.get(mesh);\n if (old) {\n scene._meshDisposables.delete(mesh);\n // These disposables free the OLD renderable's GPU resources (per-mesh/material UBOs, the\n // GPU-cull state buffers, texture releases). They must NOT run synchronously: the old buffers\n // may still be referenced by a frame already submitted to the GPU this tick, and destroying\n // them now hits the validation error \"Buffer used in submit while destroyed\" (seen when a\n // plugin / shadow-receiver variant change swaps a planted mesh's material — e.g. planting a\n // fern or agave). The new renderable is rebuilt below and replaces the old one, so nothing\n // records the old resources again; defer the teardown until the GPU has drained the\n // currently-submitted work (onSubmittedWorkDone). Mirrors resizeMeshGeometry.\n void device.queue\n .onSubmittedWorkDone()\n .then(() => {\n try {\n for (const fn of old) {\n fn();\n }\n } catch {\n // Device may have been lost/disposed before the deferred teardown ran.\n }\n })\n .catch(() => {});\n }\n\n const mat = mesh.material;\n const builder = mat?._buildGroup;\n if (!builder) {\n continue;\n }\n const rebuild = builder._rebuildSingle;\n if (!rebuild) {\n continue;\n }\n // Per-material generation: the CSM caster-view cache keys off THIS (which material was rebuilt), not the\n // global _materialEpoch (which also bumps when an unrelated material is swapped), so swapping a non-caster\n // material doesn't force a full shadow rebuild. See ensureCsmShadowTaskState.\n (mat as { _csmGen?: number })._csmGen = ((mat as { _csmGen?: number })._csmGen ?? 0) + 1;\n const renderable = rebuild(scene, mesh);\n // Insert by `order` so the renderable list stays sorted (frame-graph\n // tasks bucket opaque/direct/transparent at bind time).\n let i = scene._renderables.length;\n while (i > 0 && scene._renderables[i - 1]!.order > renderable.order) {\n i--;\n }\n scene._renderables.splice(i, 0, renderable);\n }\n q.length = 0;\n scene._renderableVersion++;\n scene._materialEpoch++; // a caster's material UBOs were rebuilt → CSM-style view caches must fully rebuild\n}\n"],"names":[],"mappings":"AAGO,SAAS,qBAAqB,KAAA,EAA2B;AAC5D,EAAA,MAAM,IAAI,KAAA,CAAM,kBAAA;AAChB,EAAA,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AAChB,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,OAAA;AACpC,EAAA,KAAA,MAAW,QAAQ,CAAA,EAAG;AAClB,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,GAAA,EAAK;AACL,MAAA,KAAA,CAAM,gBAAA,CAAiB,OAAO,IAAI,CAAA;AASlC,MAAA,KAAK,MAAA,CAAO,KAAA,CACP,mBAAA,EAAoB,CACpB,KAAK,MAAM;AACR,QAAA,IAAI;AACA,UAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AAClB,YAAA,EAAA,EAAG;AAAA,UACP;AAAA,QACJ,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACJ,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACvB;AAEA,IAAA,MAAM,MAAM,IAAA,CAAK,QAAA;AACjB,IAAA,MAAM,UAAU,GAAA,EAAK,WAAA;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,UAAU,OAAA,CAAQ,cAAA;AACxB,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA;AAAA,IACJ;AAIA,IAAC,GAAA,CAA6B,OAAA,GAAA,CAAY,GAAA,CAA6B,OAAA,IAAW,CAAA,IAAK,CAAA;AACvF,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAGtC,IAAA,IAAI,CAAA,GAAI,MAAM,YAAA,CAAa,MAAA;AAC3B,IAAA,OAAO,CAAA,GAAI,KAAK,KAAA,CAAM,YAAA,CAAa,IAAI,CAAC,CAAA,CAAG,KAAA,GAAQ,UAAA,CAAW,KAAA,EAAO;AACjE,MAAA,CAAA,EAAA;AAAA,IACJ;AACA,IAAA,KAAA,CAAM,YAAA,CAAa,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,UAAU,CAAA;AAAA,EAC9C;AACA,EAAA,CAAA,CAAE,MAAA,GAAS,CAAA;AACX,EAAA,KAAA,CAAM,kBAAA,EAAA;AACN,EAAA,KAAA,CAAM,cAAA,EAAA;AACV;;;;"}
@@ -1,4 +1,4 @@
1
- import { createRenderTask } from '../frame-graph/render-task.js';
1
+ import { removeMeshFromTask, createRenderTask } from '../frame-graph/render-task.js';
2
2
  import { getViewProjectionMatrix } from '../camera/camera.js';
3
3
  import { mat4Invert } from '../math/mat4-invert.js';
4
4
  import { createShadowCamera, casterVersionSum, updateShadowCameraBase, buildLightViewMatrix, multiply4x4 } from './shadow-base.js';
@@ -11,6 +11,50 @@ function ensureCsmShadowTaskState(engine, scene, sg, cfg, casterMeshes, existing
11
11
  if (existing._casterMeshes === casterMeshes && existing._renderableVersion === scene._renderableVersion) {
12
12
  return existing;
13
13
  }
14
+ if (existing._casterMeshes === casterMeshes && existing._materialEpoch === scene._materialEpoch) {
15
+ existing._renderableVersion = scene._renderableVersion;
16
+ return existing;
17
+ }
18
+ let casterMatChanged = false;
19
+ for (const m of casterMeshes) {
20
+ const mat = m.material;
21
+ if (!mat) {
22
+ continue;
23
+ }
24
+ const stored = existing._casterMatGens.get(mat);
25
+ if (stored !== void 0 && stored !== (mat._csmGen ?? 0)) {
26
+ casterMatChanged = true;
27
+ break;
28
+ }
29
+ }
30
+ if (!casterMatChanged) {
31
+ const prevSet = new Set(existing._casterMeshes);
32
+ const nextSet = new Set(casterMeshes);
33
+ const views = existing._materialViews;
34
+ const gens = existing._casterMatGens;
35
+ for (const m of existing._casterMeshes) {
36
+ if (!nextSet.has(m)) {
37
+ for (const t of existing._tasks) {
38
+ removeMeshFromTask(t, m);
39
+ }
40
+ }
41
+ }
42
+ for (const m of casterMeshes) {
43
+ if (!prevSet.has(m) && m.material) {
44
+ const view = getNoColorView(m.material, views);
45
+ for (const t of existing._tasks) {
46
+ t.addMesh(m, { material: view });
47
+ }
48
+ gens.set(m.material, m.material._csmGen ?? 0);
49
+ }
50
+ }
51
+ for (const t of existing._tasks) {
52
+ t._lastVersion = -1;
53
+ }
54
+ existing._casterMeshes = casterMeshes;
55
+ existing._renderableVersion = scene._renderableVersion;
56
+ return existing;
57
+ }
14
58
  const old = existing._task;
15
59
  void engine._device.queue.onSubmittedWorkDone().then(() => {
16
60
  try {
@@ -74,6 +118,12 @@ function ensureCsmShadowTaskState(engine, scene, sg, cfg, casterMeshes, existing
74
118
  }
75
119
  }
76
120
  };
121
+ const casterMatGens = /* @__PURE__ */ new Map();
122
+ for (const m of casterMeshes) {
123
+ if (m.material) {
124
+ casterMatGens.set(m.material, m.material._csmGen ?? 0);
125
+ }
126
+ }
77
127
  return {
78
128
  _task: compositeTask,
79
129
  _tasks: tasks,
@@ -85,7 +135,10 @@ function ensureCsmShadowTaskState(engine, scene, sg, cfg, casterMeshes, existing
85
135
  _lastCamVersion: -1,
86
136
  _uboData: new Float32Array(80),
87
137
  _casterMeshes: casterMeshes,
88
- _renderableVersion: scene._renderableVersion
138
+ _renderableVersion: scene._renderableVersion,
139
+ _materialEpoch: scene._materialEpoch,
140
+ _materialViews: materialViews,
141
+ _casterMatGens: casterMatGens
89
142
  };
90
143
  }
91
144
  function renderCsmShadowMap(engine, sg, state, cfg) {
@@ -265,16 +318,21 @@ function _computeCsmCascades(engine, camera, light, cfg, casterMeshes) {
265
318
  viewMinZ = Math.min(viewMinZ, cMinZ);
266
319
  viewMaxZ = Math.min(viewMaxZ, cMaxZ);
267
320
  }
268
- if (cfg._stabilizeCascades && stableRadius > 0) {
269
- const zq = Math.max(0.5, stableRadius / 128);
270
- viewMinZ = Math.floor(viewMinZ / zq) * zq;
271
- viewMaxZ = Math.ceil(viewMaxZ / zq) * zq;
272
- }
273
321
  }
274
322
  const proj0 = orthoOffCenterLH(minX, maxX, minY, maxY, viewMinZ, viewMaxZ);
275
323
  let transform = multiply4x4(proj0, view);
276
- const ox = transform[12] * (cfg._mapSize / 2);
277
- const oy = transform[13] * (cfg._mapSize / 2);
324
+ let aClipX = transform[12];
325
+ let aClipY = transform[13];
326
+ if (cfg._stabilizeCascades && stableRadius > 0) {
327
+ const texelWorld = 2 * stableRadius / cfg._mapSize;
328
+ const ax = Math.round(cx / texelWorld) * texelWorld;
329
+ const ay = Math.round(cy / texelWorld) * texelWorld;
330
+ const az = Math.round(cz / texelWorld) * texelWorld;
331
+ aClipX = transform[0] * ax + transform[4] * ay + transform[8] * az + transform[12];
332
+ aClipY = transform[1] * ax + transform[5] * ay + transform[9] * az + transform[13];
333
+ }
334
+ const ox = aClipX * (cfg._mapSize / 2);
335
+ const oy = aClipY * (cfg._mapSize / 2);
278
336
  const offX = (Math.round(ox) - ox) * (2 / cfg._mapSize);
279
337
  const offY = (Math.round(oy) - oy) * (2 / cfg._mapSize);
280
338
  const snap = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, offX, offY, 0, 1]);
@@ -1 +1 @@
1
- {"version":3,"file":"csm-shadow-task-hooks.js","sources":["../../../src/shadow/csm-shadow-task-hooks.ts"],"sourcesContent":["/** Internal CSM (cascaded shadow map) task hooks owned by CSM shadow generators.\n *\n * Mirrors `pcf-shadow-task-hooks.ts`, but renders N cascade layers of a depth\n * `texture_2d_array` and computes per-cascade frustum-split + orthographic-fit\n * matrices from the active camera. All CSM-only math (frustum-corner fit,\n * ortho-off-center, texel snap) lives here so plain ESM/PCF scenes never bundle\n * it. The light view matrix + 4×4 multiply are shared helpers (already used by\n * ESM/PCF) so reusing them adds zero bytes.\n */\n\nimport type { Camera } from \"../camera/camera.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createRenderTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { buildLightViewMatrix, casterVersionSum, createShadowCamera, multiply4x4, updateShadowCameraBase } from \"./shadow-base.js\";\nimport { getNoColorView, preloadPcfShadowTaskState } from \"./pcf-shadow-task-hooks.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\n\n/** CSM configuration captured by the generator and consumed by these hooks. */\nexport interface CsmConfig {\n /** @internal */\n _numCascades: number;\n /** @internal */\n _lambda: number;\n /** @internal */\n _cascadeBlendPercentage: number;\n /** @internal */\n _stabilizeCascades: boolean;\n /** @internal */\n _depthClamp: boolean;\n /** @internal */\n _shadowMaxZ: number | null;\n /** @internal */\n _bias: number;\n /** @internal */\n _darkness: number;\n /** @internal */\n _frustumEdgeFalloff: number;\n /** @internal */\n _mapSize: number;\n /** @internal */\n _forceRefreshEveryFrame: boolean;\n}\n\nexport interface CsmTaskState extends ShadowTaskInternalState {\n /** @internal */\n _tasks: RenderTask[];\n /** @internal */\n _cameras: Camera[];\n /** @internal */\n _scene: SceneContext;\n /** @internal */\n _cameraVersion: number;\n /** @internal */\n _lastCasterVersion: number;\n /** @internal */\n _lastLightVersion: number;\n /** @internal */\n _lastCamVersion: number;\n /** @internal */\n _uboData: Float32Array;\n /** @internal */\n _casterMeshes: readonly Mesh[];\n /** @internal Scene renderable version the cascade material views were built against. A material\n * swap (plugin/receiver variant change) rebuilds the swapped mesh's renderable + UBOs but leaves\n * this task's cached no-color material views pointing at the now-destroyed UBOs, so we rebuild when\n * it changes — not only when the caster SET changes. */\n _renderableVersion: number;\n}\n\nexport const preloadCsmShadowTaskState = preloadPcfShadowTaskState;\n\n/** Build (or reuse) the CSM task state: N per-layer depth render targets + cameras + tasks. */\nexport function ensureCsmShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n cfg: CsmConfig,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): CsmTaskState {\n const existing = existingState as CsmTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes && existing._renderableVersion === scene._renderableVersion) {\n return existing;\n }\n // The caster set OR a material changed (a material swap rebuilds a caster's renderable + UBOs but\n // leaves our cached no-color material views dangling at the destroyed UBOs — this is the\n // \"Buffer used in submit while destroyed\" flood seen when planting a shadow-casting fern/agave,\n // whose foliage material swaps variant on first render). Rebuild the cascade tasks below with the\n // casters' CURRENT materials and return the NEW state — the caller swaps to it, so the OLD task is\n // never recorded again. Its GPU buffers may still be referenced by a frame already submitted this\n // tick, so we must NOT dispose it synchronously; defer until the GPU drains the currently-submitted\n // work (onSubmittedWorkDone). Mirrors resizeMeshGeometry.\n const old = existing._task;\n void engine._device.queue\n .onSubmittedWorkDone()\n .then(() => {\n try {\n old.dispose();\n } catch {\n // Device may have been lost/disposed before the deferred dispose ran — nothing to free.\n }\n })\n .catch(() => {});\n }\n\n const materialViews = new Map<Material, MaterialView>();\n const n = cfg._numCascades;\n const tasks: RenderTask[] = [];\n const cameras: Camera[] = [];\n for (let i = 0; i < n; i++) {\n const layerView = sg._depthTexture.createView({ dimension: \"2d\", baseArrayLayer: i, arrayLayerCount: 1 });\n const rt: RenderTarget = {\n _descriptor: {\n size: { width: cfg._mapSize, height: cfg._mapSize },\n dFormat: \"depth32float\",\n _depthClearValue: 1,\n _depthCompare: \"less-equal\",\n samples: 1,\n },\n _colorTexture: null,\n _colorView: null,\n _depthTexture: sg._depthTexture,\n _depthView: layerView,\n _width: cfg._mapSize,\n _height: cfg._mapSize,\n _eager: true,\n _ownsDepthTexture: false, // borrowed: the shared CSM depth array is owned by the generator\n };\n const camera = createShadowCamera(sg);\n const task = createRenderTask({ name: `csm${i}`, rt, clr: true, cam: camera }, engine, scene);\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n task.addMesh(mesh, { material: getNoColorView(material, materialViews) });\n }\n }\n tasks.push(task);\n cameras.push(camera);\n }\n\n const compositeTask = {\n record(): void {\n for (const t of tasks) {\n t.record();\n }\n },\n execute(): number {\n let draws = 0;\n for (const t of tasks) {\n draws += t.execute?.() ?? 0;\n }\n return draws;\n },\n dispose(): void {\n for (const t of tasks) {\n t.dispose();\n }\n },\n };\n\n return {\n _task: compositeTask,\n _tasks: tasks,\n _cameras: cameras,\n _scene: scene,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _lastCamVersion: -1,\n _uboData: new Float32Array(80),\n _casterMeshes: casterMeshes,\n _renderableVersion: scene._renderableVersion,\n };\n}\n\n/** Render every cascade layer for this frame, recomputing splits/matrices from the active camera. */\nexport function renderCsmShadowMap(engine: EngineContext, sg: ShadowGenerator, state: CsmTaskState, cfg: CsmConfig): number {\n const casterMeshes = state._casterMeshes;\n const camera = state._scene.camera;\n if (!camera) {\n return 0;\n }\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n const camVersion = camera.worldMatrixVersion;\n if (!cfg._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion && camVersion === state._lastCamVersion) {\n return 0;\n }\n\n const cascades = _computeCsmCascades(engine, camera, sg._light as DirectionalLight, cfg, casterMeshes);\n\n _writeCsmUbo(state._uboData, cascades, cfg);\n sg._version++;\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, state._uboData as Float32Array<ArrayBuffer>);\n\n // Notify custom receivers (e.g. a ShaderMaterial that mirrors the cascade transforms into\n // its own uniforms) with this frame's freshly-computed receiver UBO. This fires inside the\n // shadow task — after the transforms are finalized but before the shadow map and main pass\n // render — so such receivers stay in lock-step with the depth map. Syncing from a\n // `onBeforeRender` callback instead would read the previous frame's transforms (a one-frame\n // lag that makes those shadows swim while the camera moves). The built-in standard/PBR/node\n // receivers don't need this: they bind `sg._shadowUBO` directly.\n const receiverCbs = sg._onReceiverData;\n if (receiverCbs) {\n for (let i = 0; i < receiverCbs.length; i++) {\n receiverCbs[i]!(state._uboData);\n }\n }\n\n state._cameraVersion++;\n for (let i = 0; i < cascades._transforms.length; i++) {\n const cam = state._cameras[i]!;\n cam.fov = 1;\n updateShadowCameraBase(cam, state._cameraVersion, cascades._near[i]!, cascades._far[i]!, cascades._views[i]!, _biasViewProjection(cascades._biased[i]!, cfg._bias));\n }\n\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n state._lastCamVersion = camVersion;\n return state._task.execute?.() ?? 0;\n}\n\n// ─── CSM math (isolated to this module) ─────────────────────────────\n\ninterface CsmCascades {\n /** @internal Unbiased receiver transform per cascade (col-major). */\n _transforms: Float32Array[];\n /** @internal Same as _transforms, used for the caster camera before bias. */\n _biased: Float32Array[];\n /** @internal Cascade light view matrix per cascade (col-major). */\n _views: Float32Array[];\n /** @internal Ortho near per cascade. */\n _near: number[];\n /** @internal Ortho far per cascade. */\n _far: number[];\n /** @internal Camera-view-space split distance per cascade. */\n _viewFrustumZ: number[];\n /** @internal Slice length per cascade. */\n _frustumLengths: number[];\n}\n\n/** Lite reverse-Z NDC frustum corners (near z=1, far z=0); xy each -1 or +1. */\nconst FRUSTUM_NDC: ReadonlyArray<readonly [number, number, number]> = [\n [-1, 1, 1],\n [1, 1, 1],\n [1, -1, 1],\n [-1, -1, 1],\n [-1, 1, 0],\n [1, 1, 0],\n [1, -1, 0],\n [-1, -1, 0],\n];\n\nfunction transformCoord(m: ArrayLike<number>, x: number, y: number, z: number): [number, number, number] {\n const X = m[0]! * x + m[4]! * y + m[8]! * z + m[12]!;\n const Y = m[1]! * x + m[5]! * y + m[9]! * z + m[13]!;\n const Z = m[2]! * x + m[6]! * y + m[10]! * z + m[14]!;\n const W = m[3]! * x + m[7]! * y + m[11]! * z + m[15]!;\n return [X / W, Y / W, Z / W];\n}\n\n/** Column-major OrthoOffCenterLH with half-z NDC (z: near→0, far→1). */\nfunction orthoOffCenterLH(l: number, r: number, b: number, t: number, n: number, f: number): Float32Array {\n const m = new Float32Array(16);\n m[0] = 2 / (r - l);\n m[5] = 2 / (t - b);\n m[10] = 1 / (f - n);\n m[12] = -(r + l) / (r - l);\n m[13] = -(t + b) / (t - b);\n m[14] = -n / (f - n);\n m[15] = 1;\n return m;\n}\n\nfunction _computeCsmCascades(engine: EngineContext, camera: Camera, light: DirectionalLight, cfg: CsmConfig, casterMeshes: readonly Mesh[]): CsmCascades {\n const near = camera.nearPlane;\n const far = camera.farPlane;\n const cameraRange = far - near;\n const shadowMaxZ = cfg._shadowMaxZ ?? far;\n const maxDistance = shadowMaxZ < far && shadowMaxZ >= near ? Math.min((shadowMaxZ - near) / (far - near), 1) : 1;\n const minDistance = 0;\n const minZ = near + minDistance * cameraRange;\n const maxZ = near + maxDistance * cameraRange;\n const range = maxZ - minZ;\n const ratio = maxZ / minZ;\n const n = cfg._numCascades;\n\n const breakDist: number[] = [];\n const viewFrustumZ: number[] = [];\n const frustumLengths: number[] = [];\n for (let i = 0; i < n; i++) {\n const p = (i + 1) / n;\n const log = minZ * ratio ** p;\n const uniform = minZ + range * p;\n const d = cfg._lambda * (log - uniform) + uniform;\n const prevBreak = i === 0 ? minDistance : breakDist[i - 1]!;\n breakDist[i] = (d - near) / cameraRange;\n viewFrustumZ[i] = d;\n frustumLengths[i] = (breakDist[i]! - prevBreak) * cameraRange;\n }\n\n // Light direction (normalized), avoiding a perfectly vertical degenerate case.\n let dx = light.direction.x;\n let dy = light.direction.y;\n let dz = light.direction.z;\n const dl = Math.hypot(dx, dy, dz) || 1;\n dx /= dl;\n dy /= dl;\n dz /= dl;\n if (Math.abs(dy) >= 1) {\n dz = 1e-13;\n }\n\n const aspect = engine.canvas.width / engine.canvas.height;\n const vp = getViewProjectionMatrix(camera, aspect) as unknown as ArrayLike<number>;\n const inv = mat4Invert(vp as never);\n const invViewProj: ArrayLike<number> = (inv as unknown as ArrayLike<number>) ?? vp;\n\n const aabb = _castersWorldAabb(casterMeshes);\n\n const transforms: Float32Array[] = [];\n const views: Float32Array[] = [];\n const nearOut: number[] = [];\n const farOut: number[] = [];\n\n for (let c = 0; c < n; c++) {\n const prevSplit = c === 0 ? 0 : breakDist[c - 1]!;\n const split = breakDist[c]!;\n\n // World-space frustum corners of this slice.\n const corners: [number, number, number][] = [];\n for (let k = 0; k < 8; k++) {\n const ndc = FRUSTUM_NDC[k]!;\n corners.push(transformCoord(invViewProj, ndc[0], ndc[1], ndc[2]));\n }\n for (let k = 0; k < 4; k++) {\n const nearC = corners[k]!;\n const farC = corners[k + 4]!;\n const rx = farC[0] - nearC[0];\n const ry = farC[1] - nearC[1];\n const rz = farC[2] - nearC[2];\n corners[k + 4] = [nearC[0] + rx * split, nearC[1] + ry * split, nearC[2] + rz * split];\n corners[k] = [nearC[0] + rx * prevSplit, nearC[1] + ry * prevSplit, nearC[2] + rz * prevSplit];\n }\n\n // Centroid.\n let cx = 0,\n cy = 0,\n cz = 0;\n for (const p of corners) {\n cx += p[0];\n cy += p[1];\n cz += p[2];\n }\n cx /= 8;\n cy /= 8;\n cz /= 8;\n\n let minX: number, maxX: number, minY: number, maxY: number, minEz: number, maxEz: number;\n let stableRadius = 0;\n if (cfg._stabilizeCascades) {\n let radius = 0;\n for (const p of corners) {\n radius = Math.max(radius, Math.hypot(p[0] - cx, p[1] - cy, p[2] - cz));\n }\n radius = Math.ceil(radius * 16) / 16;\n stableRadius = radius;\n minX = minY = minEz = -radius;\n maxX = maxY = maxEz = radius;\n } else {\n // Temp light view centred on the centroid to fit a tight AABB.\n const tmpView = buildLightViewMatrix(dx, dy, dz, cx, cy, cz);\n minX = minY = minEz = Infinity;\n maxX = maxY = maxEz = -Infinity;\n for (const p of corners) {\n const lp = transformCoord(tmpView, p[0], p[1], p[2]);\n minX = Math.min(minX, lp[0]);\n maxX = Math.max(maxX, lp[0]);\n minY = Math.min(minY, lp[1]);\n maxY = Math.max(maxY, lp[1]);\n minEz = Math.min(minEz, lp[2]);\n maxEz = Math.max(maxEz, lp[2]);\n }\n }\n\n // Shadow camera sits behind the slice along the light direction.\n const eyeX = cx + dx * minEz;\n const eyeY = cy + dy * minEz;\n const eyeZ = cz + dz * minEz;\n const view = buildLightViewMatrix(dx, dy, dz, eyeX, eyeY, eyeZ);\n\n let viewMinZ = 0;\n let viewMaxZ = maxEz - minEz;\n\n // Tighten Z to the caster bounding box in cascade view space (depthClamp = false behaviour:\n // keep all casters inside the frustum so no GPU depth-clip feature is required).\n if (aabb) {\n let cMinZ = Infinity;\n let cMaxZ = -Infinity;\n for (let k = 0; k < 8; k++) {\n const wx = k & 1 ? aabb._max[0] : aabb._min[0];\n const wy = k & 2 ? aabb._max[1] : aabb._min[1];\n const wz = k & 4 ? aabb._max[2] : aabb._min[2];\n const lz = view[2]! * wx + view[6]! * wy + view[10]! * wz + view[14]!;\n cMinZ = Math.min(cMinZ, lz);\n cMaxZ = Math.max(cMaxZ, lz);\n }\n if (cMinZ <= viewMaxZ) {\n viewMinZ = Math.min(viewMinZ, cMinZ);\n viewMaxZ = Math.min(viewMaxZ, cMaxZ);\n }\n\n // Stabilize Z: with stabilizeCascades the XY fit is a fixed bounding sphere (eye + extents\n // are stable), but the caster-AABB tighten above moves the near/far planes whenever a caster moves\n if (cfg._stabilizeCascades && stableRadius > 0) {\n const zq = Math.max(0.5, stableRadius / 128);\n viewMinZ = Math.floor(viewMinZ / zq) * zq;\n viewMaxZ = Math.ceil(viewMaxZ / zq) * zq;\n }\n }\n\n const proj0 = orthoOffCenterLH(minX, maxX, minY, maxY, viewMinZ, viewMaxZ);\n let transform = multiply4x4(proj0, view);\n\n // Texel-snap: round the world origin to a shadow-map texel (always applied in BJS).\n const ox = transform[12]! * (cfg._mapSize / 2);\n const oy = transform[13]! * (cfg._mapSize / 2);\n const offX = (Math.round(ox) - ox) * (2 / cfg._mapSize);\n const offY = (Math.round(oy) - oy) * (2 / cfg._mapSize);\n const snap = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, offX, offY, 0, 1]);\n const proj = multiply4x4(snap, proj0);\n transform = multiply4x4(proj, view);\n\n transforms.push(transform);\n views.push(view);\n nearOut.push(viewMinZ);\n farOut.push(viewMaxZ);\n }\n\n return {\n _transforms: transforms,\n _biased: transforms.map((t) => new Float32Array(t)),\n _views: views,\n _near: nearOut,\n _far: farOut,\n _viewFrustumZ: viewFrustumZ,\n _frustumLengths: frustumLengths,\n };\n}\n\nfunction _castersWorldAabb(casterMeshes: readonly Mesh[]): { _min: [number, number, number]; _max: [number, number, number] } | null {\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity,\n maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (const mesh of casterMeshes) {\n // Thin-instanced casters are drawn at `finalWorld = mesh.world * instanceMatrix` (see\n // thin-instance-fragment.ts), so a single `mesh.worldMatrix × boundMin/Max` box ignores the per-instance\n // spread entirely — one prototype-sized box wrecks the cascade Z-fit (an off-world herd collapsed every\n // shadow). Bound the caster by the union of every drawn instance instead, using the SAME composition the\n // shader uses.\n const ti = mesh.thinInstances;\n if (ti && ti.count > 0 && ti.matrices) {\n const a = _thinInstanceWorldAabb(mesh, ti);\n if (a) {\n minX = Math.min(minX, a._min[0]);\n maxX = Math.max(maxX, a._max[0]);\n minY = Math.min(minY, a._min[1]);\n maxY = Math.max(maxY, a._max[1]);\n minZ = Math.min(minZ, a._min[2]);\n maxZ = Math.max(maxZ, a._max[2]);\n }\n continue;\n }\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let k = 0; k < 8; k++) {\n const lx = k & 1 ? bmax[0]! : bmin[0]!;\n const ly = k & 2 ? bmax[1]! : bmin[1]!;\n const lz = k & 4 ? bmax[2]! : bmin[2]!;\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]!;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]!;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]!;\n minX = Math.min(minX, wx);\n maxX = Math.max(maxX, wx);\n minY = Math.min(minY, wy);\n maxY = Math.max(maxY, wy);\n minZ = Math.min(minZ, wz);\n maxZ = Math.max(maxZ, wz);\n }\n }\n if (!Number.isFinite(minX)) {\n return null;\n }\n return { _min: [minX, minY, minZ], _max: [maxX, maxY, maxZ] };\n}\n\ninterface ThinCasterAabb {\n _min: [number, number, number];\n _max: [number, number, number];\n}\n\n/** Per-mesh cache of a thin-instanced caster's world AABB, keyed on BOTH the instance-matrix version and the\n * prototype mesh's `worldMatrixVersion` — the drawn world transform is `mesh.world * instanceMatrix`, so the\n * AABB must invalidate when EITHER changes (a rebake, or the prototype moving/reparenting). Lazily allocated\n * so this module keeps zero import-time side effects and stays tree-shakable. */\nlet _thinCasterAabbCache: WeakMap<Mesh, { _version: number; _worldVersion: number; _aabb: ThinCasterAabb | null }> | null = null;\nfunction _getThinCasterAabbCache(): WeakMap<Mesh, { _version: number; _worldVersion: number; _aabb: ThinCasterAabb | null }> {\n if (!_thinCasterAabbCache) {\n _thinCasterAabbCache = new WeakMap();\n }\n return _thinCasterAabbCache;\n}\n\n/** World AABB of a thin-instanced caster. Matches the shader's `finalWorld = mesh.world * instanceMatrix`\n * exactly: each local bound corner is transformed by the per-instance matrix, then by the prototype mesh\n * world matrix. Parked/degenerate instances (zero linear part — drawn as zero-area, used to hide an unused\n * tail) are skipped so a tail parked far off-world can't balloon the box. */\nfunction _thinInstanceWorldAabb(mesh: Mesh, ti: NonNullable<Mesh[\"thinInstances\"]>): ThinCasterAabb | null {\n const cache = _getThinCasterAabbCache();\n // The drawn transform is `mesh.world * instanceMatrix`, so the AABB depends on BOTH the instance matrices\n // and the prototype world matrix — invalidate when either version changes.\n const worldVersion = mesh.worldMatrixVersion;\n const cached = cache.get(mesh);\n if (cached && cached._version === ti._version && cached._worldVersion === worldVersion) {\n return cached._aabb;\n }\n // Hoist the prototype world matrix once (worldMatrix is a getter) — it is constant across all instances.\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n const mats = ti.matrices;\n const count = Math.min(ti.count, (mats.length / 16) | 0);\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity,\n maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < count; i++) {\n const o = i * 16;\n // Skip parked instances (zero 3×3 linear part → zero-area triangles that rasterize to nothing).\n const lin =\n Math.abs(mats[o]!) +\n Math.abs(mats[o + 1]!) +\n Math.abs(mats[o + 2]!) +\n Math.abs(mats[o + 4]!) +\n Math.abs(mats[o + 5]!) +\n Math.abs(mats[o + 6]!) +\n Math.abs(mats[o + 8]!) +\n Math.abs(mats[o + 9]!) +\n Math.abs(mats[o + 10]!);\n if (lin < 1e-9) {\n continue;\n }\n for (let k = 0; k < 8; k++) {\n const lx = k & 1 ? bmax[0]! : bmin[0]!;\n const ly = k & 2 ? bmax[1]! : bmin[1]!;\n const lz = k & 4 ? bmax[2]! : bmin[2]!;\n // 1) instance-local: ip = instanceMatrix * localCorner\n const ix = mats[o]! * lx + mats[o + 4]! * ly + mats[o + 8]! * lz + mats[o + 12]!;\n const iy = mats[o + 1]! * lx + mats[o + 5]! * ly + mats[o + 9]! * lz + mats[o + 13]!;\n const iz = mats[o + 2]! * lx + mats[o + 6]! * ly + mats[o + 10]! * lz + mats[o + 14]!;\n // 2) world: wp = mesh.world * ip (matches finalWorld = mesh.world * instanceMatrix)\n const wx = world[0]! * ix + world[4]! * iy + world[8]! * iz + world[12]!;\n const wy = world[1]! * ix + world[5]! * iy + world[9]! * iz + world[13]!;\n const wz = world[2]! * ix + world[6]! * iy + world[10]! * iz + world[14]!;\n if (wx < minX) {\n minX = wx;\n }\n if (wx > maxX) {\n maxX = wx;\n }\n if (wy < minY) {\n minY = wy;\n }\n if (wy > maxY) {\n maxY = wy;\n }\n if (wz < minZ) {\n minZ = wz;\n }\n if (wz > maxZ) {\n maxZ = wz;\n }\n }\n }\n const aabb: ThinCasterAabb | null = Number.isFinite(minX) ? { _min: [minX, minY, minZ], _max: [maxX, maxY, maxZ] } : null;\n cache.set(mesh, { _version: ti._version, _worldVersion: worldVersion, _aabb: aabb });\n return aabb;\n}\n\nfunction _writeCsmUbo(out: Float32Array, cascades: CsmCascades, cfg: CsmConfig): void {\n out.fill(0);\n const n = cascades._transforms.length;\n for (let i = 0; i < n; i++) {\n out.set(cascades._transforms[i]!, i * 16);\n }\n for (let i = 0; i < n; i++) {\n out[64 + i] = cascades._viewFrustumZ[i]!;\n out[68 + i] = cascades._frustumLengths[i]!;\n }\n out[72] = cfg._darkness;\n out[73] = cfg._mapSize;\n out[74] = 1 / cfg._mapSize;\n out[75] = cfg._frustumEdgeFalloff;\n out[76] = n;\n out[77] = cfg._cascadeBlendPercentage === 0 ? 10000 : 1 / cfg._cascadeBlendPercentage;\n}\n\nfunction _biasViewProjection(viewProj: Float32Array, bias: number): Float32Array {\n const biased = new Float32Array(viewProj);\n const b = bias * 0.5;\n for (let col = 0; col < 4; col++) {\n const z = 2 + col * 4;\n const w = 3 + col * 4;\n biased[z] = biased[z]! + b * biased[w]!;\n }\n return biased;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"csm-shadow-task-hooks.js","sources":["../../../src/shadow/csm-shadow-task-hooks.ts"],"sourcesContent":["/** Internal CSM (cascaded shadow map) task hooks owned by CSM shadow generators.\n *\n * Mirrors `pcf-shadow-task-hooks.ts`, but renders N cascade layers of a depth\n * `texture_2d_array` and computes per-cascade frustum-split + orthographic-fit\n * matrices from the active camera. All CSM-only math (frustum-corner fit,\n * ortho-off-center, texel snap) lives here so plain ESM/PCF scenes never bundle\n * it. The light view matrix + 4×4 multiply are shared helpers (already used by\n * ESM/PCF) so reusing them adds zero bytes.\n */\n\nimport type { Camera } from \"../camera/camera.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createRenderTask, removeMeshFromTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { buildLightViewMatrix, casterVersionSum, createShadowCamera, multiply4x4, updateShadowCameraBase } from \"./shadow-base.js\";\nimport { getNoColorView, preloadPcfShadowTaskState } from \"./pcf-shadow-task-hooks.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\n\n/** CSM configuration captured by the generator and consumed by these hooks. */\nexport interface CsmConfig {\n /** @internal */\n _numCascades: number;\n /** @internal */\n _lambda: number;\n /** @internal */\n _cascadeBlendPercentage: number;\n /** @internal */\n _stabilizeCascades: boolean;\n /** @internal */\n _depthClamp: boolean;\n /** @internal */\n _shadowMaxZ: number | null;\n /** @internal */\n _bias: number;\n /** @internal */\n _darkness: number;\n /** @internal */\n _frustumEdgeFalloff: number;\n /** @internal */\n _mapSize: number;\n /** @internal */\n _forceRefreshEveryFrame: boolean;\n}\n\nexport interface CsmTaskState extends ShadowTaskInternalState {\n /** @internal */\n _tasks: RenderTask[];\n /** @internal */\n _cameras: Camera[];\n /** @internal */\n _scene: SceneContext;\n /** @internal */\n _cameraVersion: number;\n /** @internal */\n _lastCasterVersion: number;\n /** @internal */\n _lastLightVersion: number;\n /** @internal */\n _lastCamVersion: number;\n /** @internal */\n _uboData: Float32Array;\n /** @internal */\n _casterMeshes: readonly Mesh[];\n /** @internal Scene renderable version the cascade material views were built against. A material\n * swap (plugin/receiver variant change) rebuilds the swapped mesh's renderable + UBOs but leaves\n * this task's cached no-color material views pointing at the now-destroyed UBOs, so we rebuild when\n * the MATERIAL EPOCH changes — not on every renderable-version bump (a geometry resize bumps the\n * renderable version without touching materials, and is handled by a cheap re-record instead). */\n _renderableVersion: number;\n /** @internal Scene material epoch the cascade material views were built against (see `_renderableVersion`). */\n _materialEpoch: number;\n /** @internal Cached per-material no-color depth views, reused when a caster is added incrementally so a pure\n * caster-set change updates the existing cascade tasks instead of rebuilding and re-resolving every caster\n * (which leaked ~casters×cascades UBO handles each time the caster list was re-supplied). */\n _materialViews: Map<Material, MaterialView>;\n /** @internal Per-caster-material generation (`_csmGen`) snapshot at build. The incremental path is taken only\n * while every current caster's material gen is unchanged — i.e. no CASTER material was rebuilt (which would\n * leave its cached no-color view dangling). This is precise, unlike the global `_materialEpoch` which also\n * bumps for swaps of unrelated (non-caster) materials. */\n _casterMatGens: Map<Material, number>;\n}\n\nexport const preloadCsmShadowTaskState = preloadPcfShadowTaskState;\n\n/** Build (or reuse) the CSM task state: N per-layer depth render targets + cameras + tasks. */\nexport function ensureCsmShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n cfg: CsmConfig,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): CsmTaskState {\n const existing = existingState as CsmTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes && existing._renderableVersion === scene._renderableVersion) {\n return existing;\n }\n // The caster set is unchanged and NO material was rebuilt/swapped since these tasks were built (the\n // material epoch matches): the only thing that changed is geometry (e.g. resizeMeshGeometry reallocated\n // a caster's GPU buffers, bumping the renderable version). The cascade tasks' cached no-color material\n // views are still valid — only the bundles need refreshing to pick up the new buffer handles, which the\n // shadow scheduler's execute() already does (it re-records when the renderable version moves). So adopt\n // the new state markers and REUSE the existing tasks instead of recreating them — recreating tasks every\n // geometry edit re-compiles pipelines + churns bind-groups/bundles for the whole caster set (multi-MB,\n // never returned by the GPU allocator). Only a real material change (epoch bump) needs a full rebuild,\n // because that destroys the caster UBOs the cached views point at.\n if (existing._casterMeshes === casterMeshes && existing._materialEpoch === scene._materialEpoch) {\n existing._renderableVersion = scene._renderableVersion;\n return existing;\n }\n // The caster SET changed (different array). Decide INCREMENTAL vs full rebuild by whether any CURRENT\n // caster's OWN material was rebuilt since we built (its cached no-color view would dangle) — tracked via\n // a precise per-material gen, NOT the global `_materialEpoch` (which also bumps when an UNRELATED, non-\n // caster material is swapped, e.g. a lit scene mesh added near a caster set re-supply). If NO caster\n // material changed, update the cascade tasks IN PLACE: keep the unchanged casters' resolved depth packets\n // (so nothing is destroyed — no \"buffer used in submit while destroyed\" — and nothing leaks — the old\n // code re-resolved EVERY caster into fresh per-cascade UBO packets and never freed the prior ones,\n // leaking ~casters×cascades handles every time the caster list was re-supplied, which a consumer may do\n // per frame). Only add the new casters / drop departed ones (a regenerated caster's old packet is freed\n // by removeFromScene when its mesh is disposed; a persistent caster simply keeps its packet).\n let casterMatChanged = false;\n for (const m of casterMeshes) {\n const mat = m.material;\n if (!mat) {\n continue;\n }\n const stored = existing._casterMatGens.get(mat);\n if (stored !== undefined && stored !== ((mat as { _csmGen?: number })._csmGen ?? 0)) {\n casterMatChanged = true;\n break;\n }\n }\n if (!casterMatChanged) {\n const prevSet = new Set(existing._casterMeshes);\n const nextSet = new Set(casterMeshes);\n const views = existing._materialViews;\n const gens = existing._casterMatGens;\n for (const m of existing._casterMeshes) {\n if (!nextSet.has(m)) {\n for (const t of existing._tasks) {\n removeMeshFromTask(t, m);\n }\n }\n }\n for (const m of casterMeshes) {\n if (!prevSet.has(m) && m.material) {\n const view = getNoColorView(m.material, views);\n for (const t of existing._tasks) {\n t.addMesh(m, { material: view });\n }\n gens.set(m.material, (m.material as { _csmGen?: number })._csmGen ?? 0);\n }\n }\n // Force each cascade to re-resolve its newly-added pending casters + re-bucket its binding lists.\n for (const t of existing._tasks) {\n t._lastVersion = -1;\n }\n existing._casterMeshes = casterMeshes;\n existing._renderableVersion = scene._renderableVersion;\n return existing;\n }\n // A CASTER material was actually rebuilt (a material swap rebuilds its renderable + UBOs but\n // leaves our cached no-color material views dangling at the destroyed UBOs — the\n // \"Buffer used in submit while destroyed\" flood seen when a caster's material swaps variant on first\n // render). Rebuild the cascade tasks below with the casters' CURRENT materials and return the NEW\n // state — the caller swaps to it, so the OLD task is\n // never recorded again. Its GPU buffers may still be referenced by a frame already submitted this\n // tick, so we must NOT dispose it synchronously; defer until the GPU drains the currently-submitted\n // work (onSubmittedWorkDone). Mirrors resizeMeshGeometry.\n const old = existing._task;\n void engine._device.queue\n .onSubmittedWorkDone()\n .then(() => {\n try {\n old.dispose();\n } catch {\n // Device may have been lost/disposed before the deferred dispose ran — nothing to free.\n }\n })\n .catch(() => {});\n }\n\n const materialViews = new Map<Material, MaterialView>();\n const n = cfg._numCascades;\n const tasks: RenderTask[] = [];\n const cameras: Camera[] = [];\n for (let i = 0; i < n; i++) {\n const layerView = sg._depthTexture.createView({ dimension: \"2d\", baseArrayLayer: i, arrayLayerCount: 1 });\n const rt: RenderTarget = {\n _descriptor: {\n size: { width: cfg._mapSize, height: cfg._mapSize },\n dFormat: \"depth32float\",\n _depthClearValue: 1,\n _depthCompare: \"less-equal\",\n samples: 1,\n },\n _colorTexture: null,\n _colorView: null,\n _depthTexture: sg._depthTexture,\n _depthView: layerView,\n _width: cfg._mapSize,\n _height: cfg._mapSize,\n _eager: true,\n _ownsDepthTexture: false, // borrowed: the shared CSM depth array is owned by the generator\n };\n const camera = createShadowCamera(sg);\n const task = createRenderTask({ name: `csm${i}`, rt, clr: true, cam: camera }, engine, scene);\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n task.addMesh(mesh, { material: getNoColorView(material, materialViews) });\n }\n }\n tasks.push(task);\n cameras.push(camera);\n }\n\n const compositeTask = {\n record(): void {\n for (const t of tasks) {\n t.record();\n }\n },\n execute(): number {\n let draws = 0;\n for (const t of tasks) {\n draws += t.execute?.() ?? 0;\n }\n return draws;\n },\n dispose(): void {\n for (const t of tasks) {\n t.dispose();\n }\n },\n };\n\n // Snapshot each caster material's gen so the next caster-set change can tell whether a CASTER material was\n // rebuilt (→ full rebuild) or only the set changed (→ incremental, keeping unchanged casters' packets).\n const casterMatGens = new Map<Material, number>();\n for (const m of casterMeshes) {\n if (m.material) {\n casterMatGens.set(m.material, (m.material as { _csmGen?: number })._csmGen ?? 0);\n }\n }\n return {\n _task: compositeTask,\n _tasks: tasks,\n _cameras: cameras,\n _scene: scene,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _lastCamVersion: -1,\n _uboData: new Float32Array(80),\n _casterMeshes: casterMeshes,\n _renderableVersion: scene._renderableVersion,\n _materialEpoch: scene._materialEpoch,\n _materialViews: materialViews,\n _casterMatGens: casterMatGens,\n };\n}\n\n/** Render every cascade layer for this frame, recomputing splits/matrices from the active camera. */\nexport function renderCsmShadowMap(engine: EngineContext, sg: ShadowGenerator, state: CsmTaskState, cfg: CsmConfig): number {\n const casterMeshes = state._casterMeshes;\n const camera = state._scene.camera;\n if (!camera) {\n return 0;\n }\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n const camVersion = camera.worldMatrixVersion;\n if (!cfg._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion && camVersion === state._lastCamVersion) {\n return 0;\n }\n\n const cascades = _computeCsmCascades(engine, camera, sg._light as DirectionalLight, cfg, casterMeshes);\n\n _writeCsmUbo(state._uboData, cascades, cfg);\n sg._version++;\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, state._uboData as Float32Array<ArrayBuffer>);\n\n // Notify custom receivers (e.g. a ShaderMaterial that mirrors the cascade transforms into\n // its own uniforms) with this frame's freshly-computed receiver UBO. This fires inside the\n // shadow task — after the transforms are finalized but before the shadow map and main pass\n // render — so such receivers stay in lock-step with the depth map. Syncing from a\n // `onBeforeRender` callback instead would read the previous frame's transforms (a one-frame\n // lag that makes those shadows swim while the camera moves). The built-in standard/PBR/node\n // receivers don't need this: they bind `sg._shadowUBO` directly.\n const receiverCbs = sg._onReceiverData;\n if (receiverCbs) {\n for (let i = 0; i < receiverCbs.length; i++) {\n receiverCbs[i]!(state._uboData);\n }\n }\n\n state._cameraVersion++;\n for (let i = 0; i < cascades._transforms.length; i++) {\n const cam = state._cameras[i]!;\n cam.fov = 1;\n updateShadowCameraBase(cam, state._cameraVersion, cascades._near[i]!, cascades._far[i]!, cascades._views[i]!, _biasViewProjection(cascades._biased[i]!, cfg._bias));\n }\n\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n state._lastCamVersion = camVersion;\n return state._task.execute?.() ?? 0;\n}\n\n// ─── CSM math (isolated to this module) ─────────────────────────────\n\ninterface CsmCascades {\n /** @internal Unbiased receiver transform per cascade (col-major). */\n _transforms: Float32Array[];\n /** @internal Same as _transforms, used for the caster camera before bias. */\n _biased: Float32Array[];\n /** @internal Cascade light view matrix per cascade (col-major). */\n _views: Float32Array[];\n /** @internal Ortho near per cascade. */\n _near: number[];\n /** @internal Ortho far per cascade. */\n _far: number[];\n /** @internal Camera-view-space split distance per cascade. */\n _viewFrustumZ: number[];\n /** @internal Slice length per cascade. */\n _frustumLengths: number[];\n}\n\n/** Lite reverse-Z NDC frustum corners (near z=1, far z=0); xy each -1 or +1. */\nconst FRUSTUM_NDC: ReadonlyArray<readonly [number, number, number]> = [\n [-1, 1, 1],\n [1, 1, 1],\n [1, -1, 1],\n [-1, -1, 1],\n [-1, 1, 0],\n [1, 1, 0],\n [1, -1, 0],\n [-1, -1, 0],\n];\n\nfunction transformCoord(m: ArrayLike<number>, x: number, y: number, z: number): [number, number, number] {\n const X = m[0]! * x + m[4]! * y + m[8]! * z + m[12]!;\n const Y = m[1]! * x + m[5]! * y + m[9]! * z + m[13]!;\n const Z = m[2]! * x + m[6]! * y + m[10]! * z + m[14]!;\n const W = m[3]! * x + m[7]! * y + m[11]! * z + m[15]!;\n return [X / W, Y / W, Z / W];\n}\n\n/** Column-major OrthoOffCenterLH with half-z NDC (z: near→0, far→1). */\nfunction orthoOffCenterLH(l: number, r: number, b: number, t: number, n: number, f: number): Float32Array {\n const m = new Float32Array(16);\n m[0] = 2 / (r - l);\n m[5] = 2 / (t - b);\n m[10] = 1 / (f - n);\n m[12] = -(r + l) / (r - l);\n m[13] = -(t + b) / (t - b);\n m[14] = -n / (f - n);\n m[15] = 1;\n return m;\n}\n\nfunction _computeCsmCascades(engine: EngineContext, camera: Camera, light: DirectionalLight, cfg: CsmConfig, casterMeshes: readonly Mesh[]): CsmCascades {\n const near = camera.nearPlane;\n const far = camera.farPlane;\n const cameraRange = far - near;\n const shadowMaxZ = cfg._shadowMaxZ ?? far;\n const maxDistance = shadowMaxZ < far && shadowMaxZ >= near ? Math.min((shadowMaxZ - near) / (far - near), 1) : 1;\n const minDistance = 0;\n const minZ = near + minDistance * cameraRange;\n const maxZ = near + maxDistance * cameraRange;\n const range = maxZ - minZ;\n const ratio = maxZ / minZ;\n const n = cfg._numCascades;\n\n const breakDist: number[] = [];\n const viewFrustumZ: number[] = [];\n const frustumLengths: number[] = [];\n for (let i = 0; i < n; i++) {\n const p = (i + 1) / n;\n const log = minZ * ratio ** p;\n const uniform = minZ + range * p;\n const d = cfg._lambda * (log - uniform) + uniform;\n const prevBreak = i === 0 ? minDistance : breakDist[i - 1]!;\n breakDist[i] = (d - near) / cameraRange;\n viewFrustumZ[i] = d;\n frustumLengths[i] = (breakDist[i]! - prevBreak) * cameraRange;\n }\n\n // Light direction (normalized), avoiding a perfectly vertical degenerate case.\n let dx = light.direction.x;\n let dy = light.direction.y;\n let dz = light.direction.z;\n const dl = Math.hypot(dx, dy, dz) || 1;\n dx /= dl;\n dy /= dl;\n dz /= dl;\n if (Math.abs(dy) >= 1) {\n dz = 1e-13;\n }\n\n const aspect = engine.canvas.width / engine.canvas.height;\n const vp = getViewProjectionMatrix(camera, aspect) as unknown as ArrayLike<number>;\n const inv = mat4Invert(vp as never);\n const invViewProj: ArrayLike<number> = (inv as unknown as ArrayLike<number>) ?? vp;\n\n const aabb = _castersWorldAabb(casterMeshes);\n\n const transforms: Float32Array[] = [];\n const views: Float32Array[] = [];\n const nearOut: number[] = [];\n const farOut: number[] = [];\n\n for (let c = 0; c < n; c++) {\n const prevSplit = c === 0 ? 0 : breakDist[c - 1]!;\n const split = breakDist[c]!;\n\n // World-space frustum corners of this slice.\n const corners: [number, number, number][] = [];\n for (let k = 0; k < 8; k++) {\n const ndc = FRUSTUM_NDC[k]!;\n corners.push(transformCoord(invViewProj, ndc[0], ndc[1], ndc[2]));\n }\n for (let k = 0; k < 4; k++) {\n const nearC = corners[k]!;\n const farC = corners[k + 4]!;\n const rx = farC[0] - nearC[0];\n const ry = farC[1] - nearC[1];\n const rz = farC[2] - nearC[2];\n corners[k + 4] = [nearC[0] + rx * split, nearC[1] + ry * split, nearC[2] + rz * split];\n corners[k] = [nearC[0] + rx * prevSplit, nearC[1] + ry * prevSplit, nearC[2] + rz * prevSplit];\n }\n\n // Centroid.\n let cx = 0,\n cy = 0,\n cz = 0;\n for (const p of corners) {\n cx += p[0];\n cy += p[1];\n cz += p[2];\n }\n cx /= 8;\n cy /= 8;\n cz /= 8;\n\n let minX: number, maxX: number, minY: number, maxY: number, minEz: number, maxEz: number;\n let stableRadius = 0;\n if (cfg._stabilizeCascades) {\n let radius = 0;\n for (const p of corners) {\n radius = Math.max(radius, Math.hypot(p[0] - cx, p[1] - cy, p[2] - cz));\n }\n radius = Math.ceil(radius * 16) / 16;\n stableRadius = radius;\n minX = minY = minEz = -radius;\n maxX = maxY = maxEz = radius;\n } else {\n // Temp light view centred on the centroid to fit a tight AABB.\n const tmpView = buildLightViewMatrix(dx, dy, dz, cx, cy, cz);\n minX = minY = minEz = Infinity;\n maxX = maxY = maxEz = -Infinity;\n for (const p of corners) {\n const lp = transformCoord(tmpView, p[0], p[1], p[2]);\n minX = Math.min(minX, lp[0]);\n maxX = Math.max(maxX, lp[0]);\n minY = Math.min(minY, lp[1]);\n maxY = Math.max(maxY, lp[1]);\n minEz = Math.min(minEz, lp[2]);\n maxEz = Math.max(maxEz, lp[2]);\n }\n }\n\n // Shadow camera sits behind the slice along the light direction.\n const eyeX = cx + dx * minEz;\n const eyeY = cy + dy * minEz;\n const eyeZ = cz + dz * minEz;\n const view = buildLightViewMatrix(dx, dy, dz, eyeX, eyeY, eyeZ);\n\n let viewMinZ = 0;\n let viewMaxZ = maxEz - minEz;\n\n // Tighten Z to the caster bounding box in cascade view space (depthClamp = false behaviour:\n // keep all casters inside the frustum so no GPU depth-clip feature is required).\n if (aabb) {\n let cMinZ = Infinity;\n let cMaxZ = -Infinity;\n for (let k = 0; k < 8; k++) {\n const wx = k & 1 ? aabb._max[0] : aabb._min[0];\n const wy = k & 2 ? aabb._max[1] : aabb._min[1];\n const wz = k & 4 ? aabb._max[2] : aabb._min[2];\n const lz = view[2]! * wx + view[6]! * wy + view[10]! * wz + view[14]!;\n cMinZ = Math.min(cMinZ, lz);\n cMaxZ = Math.max(cMaxZ, lz);\n }\n if (cMinZ <= viewMaxZ) {\n viewMinZ = Math.min(viewMinZ, cMinZ);\n viewMaxZ = Math.min(viewMaxZ, cMaxZ);\n }\n\n // Z is intentionally NOT quantized here. The caster-AABB fit (cMinZ/cMaxZ) is C0-continuous in the\n // light direction — each is a min/max of linear functions of the light vector, so it has kinks but no\n // jumps — meaning the near/far drift SMOOTHLY as the light rotates. A constant NDC depth bias maps to a\n // WORLD bias of bias·(far−near), and the stored depths are likewise normalised by (far−near); the old\n // `zq = max(0.5, radius/128)` floor/ceil snapped that range to a grid, so both the effective bias AND\n // the stored depth STEPPED at each quantum boundary as the light direction changed — appearing as\n // self-shadow acne that VIBRATES. Removing the quantize makes those steps a sub-millimetre, imperceptible\n // drift, and still covers the moving-caster case it was added for (the range drifts, it never pops).\n }\n\n const proj0 = orthoOffCenterLH(minX, maxX, minY, maxY, viewMinZ, viewMaxZ);\n let transform = multiply4x4(proj0, view);\n\n // Texel-snap: lock the shadow grid to world space so it does not crawl as the camera moves, by rounding a\n // fixed WORLD anchor onto the shadow-map texel grid. BJS anchors the WORLD ORIGIN. With a STILL camera and\n // a slowly ROTATING light that is the cause of the visible \"vibration\": the eye is recentred on the cascade\n // centre every frame, so the snap residual is the anchor's offset from the centre measured along the light\n // axes — and the world origin's offset from the centre is large (≈ the cascade's distance from origin), so\n // its projection sweeps many texels per degree of light rotation and Math.round trips a full-texel correction\n // again and again → the whole map pops/boils. We instead anchor the world-grid point NEAREST the cascade\n // centre (cell = one texel in world units): it is still a fixed world point (a translating camera only ever\n // sees whole-cell anchor switches, ≤ a sub-texel grid wiggle that PCF hides), but its offset from the centre\n // is < 1 texel, so a full light rotation sweeps it < 1 texel → effectively no rotation pop. Non-stabilized\n // path keeps the origin anchor (no stableRadius → no texel-world size to build the world grid from).\n let aClipX = transform[12]!;\n let aClipY = transform[13]!;\n if (cfg._stabilizeCascades && stableRadius > 0) {\n const texelWorld = (2 * stableRadius) / cfg._mapSize;\n const ax = Math.round(cx / texelWorld) * texelWorld;\n const ay = Math.round(cy / texelWorld) * texelWorld;\n const az = Math.round(cz / texelWorld) * texelWorld;\n aClipX = transform[0]! * ax + transform[4]! * ay + transform[8]! * az + transform[12]!;\n aClipY = transform[1]! * ax + transform[5]! * ay + transform[9]! * az + transform[13]!;\n }\n const ox = aClipX * (cfg._mapSize / 2);\n const oy = aClipY * (cfg._mapSize / 2);\n const offX = (Math.round(ox) - ox) * (2 / cfg._mapSize);\n const offY = (Math.round(oy) - oy) * (2 / cfg._mapSize);\n const snap = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, offX, offY, 0, 1]);\n const proj = multiply4x4(snap, proj0);\n transform = multiply4x4(proj, view);\n\n transforms.push(transform);\n views.push(view);\n nearOut.push(viewMinZ);\n farOut.push(viewMaxZ);\n }\n\n return {\n _transforms: transforms,\n _biased: transforms.map((t) => new Float32Array(t)),\n _views: views,\n _near: nearOut,\n _far: farOut,\n _viewFrustumZ: viewFrustumZ,\n _frustumLengths: frustumLengths,\n };\n}\n\nfunction _castersWorldAabb(casterMeshes: readonly Mesh[]): { _min: [number, number, number]; _max: [number, number, number] } | null {\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity,\n maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (const mesh of casterMeshes) {\n // Thin-instanced casters are drawn at `finalWorld = mesh.world * instanceMatrix` (see\n // thin-instance-fragment.ts), so a single `mesh.worldMatrix × boundMin/Max` box ignores the per-instance\n // spread entirely — one prototype-sized box wrecks the cascade Z-fit (an off-world herd collapsed every\n // shadow). Bound the caster by the union of every drawn instance instead, using the SAME composition the\n // shader uses.\n const ti = mesh.thinInstances;\n if (ti && ti.count > 0 && ti.matrices) {\n const a = _thinInstanceWorldAabb(mesh, ti);\n if (a) {\n minX = Math.min(minX, a._min[0]);\n maxX = Math.max(maxX, a._max[0]);\n minY = Math.min(minY, a._min[1]);\n maxY = Math.max(maxY, a._max[1]);\n minZ = Math.min(minZ, a._min[2]);\n maxZ = Math.max(maxZ, a._max[2]);\n }\n continue;\n }\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let k = 0; k < 8; k++) {\n const lx = k & 1 ? bmax[0]! : bmin[0]!;\n const ly = k & 2 ? bmax[1]! : bmin[1]!;\n const lz = k & 4 ? bmax[2]! : bmin[2]!;\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]!;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]!;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]!;\n minX = Math.min(minX, wx);\n maxX = Math.max(maxX, wx);\n minY = Math.min(minY, wy);\n maxY = Math.max(maxY, wy);\n minZ = Math.min(minZ, wz);\n maxZ = Math.max(maxZ, wz);\n }\n }\n if (!Number.isFinite(minX)) {\n return null;\n }\n return { _min: [minX, minY, minZ], _max: [maxX, maxY, maxZ] };\n}\n\ninterface ThinCasterAabb {\n _min: [number, number, number];\n _max: [number, number, number];\n}\n\n/** Per-mesh cache of a thin-instanced caster's world AABB, keyed on BOTH the instance-matrix version and the\n * prototype mesh's `worldMatrixVersion` — the drawn world transform is `mesh.world * instanceMatrix`, so the\n * AABB must invalidate when EITHER changes (a rebake, or the prototype moving/reparenting). Lazily allocated\n * so this module keeps zero import-time side effects and stays tree-shakable. */\nlet _thinCasterAabbCache: WeakMap<Mesh, { _version: number; _worldVersion: number; _aabb: ThinCasterAabb | null }> | null = null;\nfunction _getThinCasterAabbCache(): WeakMap<Mesh, { _version: number; _worldVersion: number; _aabb: ThinCasterAabb | null }> {\n if (!_thinCasterAabbCache) {\n _thinCasterAabbCache = new WeakMap();\n }\n return _thinCasterAabbCache;\n}\n\n/** World AABB of a thin-instanced caster. Matches the shader's `finalWorld = mesh.world * instanceMatrix`\n * exactly: each local bound corner is transformed by the per-instance matrix, then by the prototype mesh\n * world matrix. Parked/degenerate instances (zero linear part — drawn as zero-area, used to hide an unused\n * tail) are skipped so a tail parked far off-world can't balloon the box. */\nfunction _thinInstanceWorldAabb(mesh: Mesh, ti: NonNullable<Mesh[\"thinInstances\"]>): ThinCasterAabb | null {\n const cache = _getThinCasterAabbCache();\n // The drawn transform is `mesh.world * instanceMatrix`, so the AABB depends on BOTH the instance matrices\n // and the prototype world matrix — invalidate when either version changes.\n const worldVersion = mesh.worldMatrixVersion;\n const cached = cache.get(mesh);\n if (cached && cached._version === ti._version && cached._worldVersion === worldVersion) {\n return cached._aabb;\n }\n // Hoist the prototype world matrix once (worldMatrix is a getter) — it is constant across all instances.\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n const mats = ti.matrices;\n const count = Math.min(ti.count, (mats.length / 16) | 0);\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity,\n maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < count; i++) {\n const o = i * 16;\n // Skip parked instances (zero 3×3 linear part → zero-area triangles that rasterize to nothing).\n const lin =\n Math.abs(mats[o]!) +\n Math.abs(mats[o + 1]!) +\n Math.abs(mats[o + 2]!) +\n Math.abs(mats[o + 4]!) +\n Math.abs(mats[o + 5]!) +\n Math.abs(mats[o + 6]!) +\n Math.abs(mats[o + 8]!) +\n Math.abs(mats[o + 9]!) +\n Math.abs(mats[o + 10]!);\n if (lin < 1e-9) {\n continue;\n }\n for (let k = 0; k < 8; k++) {\n const lx = k & 1 ? bmax[0]! : bmin[0]!;\n const ly = k & 2 ? bmax[1]! : bmin[1]!;\n const lz = k & 4 ? bmax[2]! : bmin[2]!;\n // 1) instance-local: ip = instanceMatrix * localCorner\n const ix = mats[o]! * lx + mats[o + 4]! * ly + mats[o + 8]! * lz + mats[o + 12]!;\n const iy = mats[o + 1]! * lx + mats[o + 5]! * ly + mats[o + 9]! * lz + mats[o + 13]!;\n const iz = mats[o + 2]! * lx + mats[o + 6]! * ly + mats[o + 10]! * lz + mats[o + 14]!;\n // 2) world: wp = mesh.world * ip (matches finalWorld = mesh.world * instanceMatrix)\n const wx = world[0]! * ix + world[4]! * iy + world[8]! * iz + world[12]!;\n const wy = world[1]! * ix + world[5]! * iy + world[9]! * iz + world[13]!;\n const wz = world[2]! * ix + world[6]! * iy + world[10]! * iz + world[14]!;\n if (wx < minX) {\n minX = wx;\n }\n if (wx > maxX) {\n maxX = wx;\n }\n if (wy < minY) {\n minY = wy;\n }\n if (wy > maxY) {\n maxY = wy;\n }\n if (wz < minZ) {\n minZ = wz;\n }\n if (wz > maxZ) {\n maxZ = wz;\n }\n }\n }\n const aabb: ThinCasterAabb | null = Number.isFinite(minX) ? { _min: [minX, minY, minZ], _max: [maxX, maxY, maxZ] } : null;\n cache.set(mesh, { _version: ti._version, _worldVersion: worldVersion, _aabb: aabb });\n return aabb;\n}\n\nfunction _writeCsmUbo(out: Float32Array, cascades: CsmCascades, cfg: CsmConfig): void {\n out.fill(0);\n const n = cascades._transforms.length;\n for (let i = 0; i < n; i++) {\n out.set(cascades._transforms[i]!, i * 16);\n }\n for (let i = 0; i < n; i++) {\n out[64 + i] = cascades._viewFrustumZ[i]!;\n out[68 + i] = cascades._frustumLengths[i]!;\n }\n out[72] = cfg._darkness;\n out[73] = cfg._mapSize;\n out[74] = 1 / cfg._mapSize;\n out[75] = cfg._frustumEdgeFalloff;\n out[76] = n;\n out[77] = cfg._cascadeBlendPercentage === 0 ? 10000 : 1 / cfg._cascadeBlendPercentage;\n}\n\nfunction _biasViewProjection(viewProj: Float32Array, bias: number): Float32Array {\n const biased = new Float32Array(viewProj);\n const b = bias * 0.5;\n for (let col = 0; col < 4; col++) {\n const z = 2 + col * 4;\n const w = 3 + col * 4;\n biased[z] = biased[z]! + b * biased[w]!;\n }\n return biased;\n}\n"],"names":[],"mappings":"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"}