@babylonjs/lite 1.11.0 → 1.12.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.
- package/CHANGELOG.md +22 -0
- package/dist/index.js +444 -368
- package/dist/index.js.map +1 -1
- package/index.d.ts +191 -4
- package/lib/audio/index.js +1 -0
- package/lib/audio/index.js.map +1 -1
- package/lib/audio/media-stream-output.js +44 -0
- package/lib/audio/media-stream-output.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/frame-graph/render-task.js +1 -1
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/frame-graph/shadow-inputs.js +10 -1
- package/lib/frame-graph/shadow-inputs.js.map +1 -1
- package/lib/frame-graph/transmission.js +1 -16
- package/lib/frame-graph/transmission.js.map +1 -1
- package/lib/index.js +5 -3
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-json-asset.js +1 -1
- package/lib/loader-gltf/gltf-json-asset.js.map +1 -1
- package/lib/loader-gltf/gltf-multi-buffer.js +2 -10
- package/lib/loader-gltf/gltf-multi-buffer.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder-ext.js +4 -18
- package/lib/loader-gltf/gltf-pbr-builder-ext.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder.js +17 -14
- package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
- package/lib/loader-gltf/gltf-sampler-desc.js +3 -16
- package/lib/loader-gltf/gltf-sampler-desc.js.map +1 -1
- package/lib/material/node/blocks/ambient-occlusion-block.js +1 -4
- package/lib/material/node/blocks/ambient-occlusion-block.js.map +1 -1
- package/lib/material/node/blocks/biplanar-block.js +3 -6
- package/lib/material/node/blocks/biplanar-block.js.map +1 -1
- package/lib/material/node/blocks/image-source.js +2 -5
- package/lib/material/node/blocks/image-source.js.map +1 -1
- package/lib/material/node/blocks/input-block.js +5 -26
- package/lib/material/node/blocks/input-block.js.map +1 -1
- package/lib/material/node/blocks/pbr-mr-helper-full.js +5 -8
- package/lib/material/node/blocks/pbr-mr-helper-full.js.map +1 -1
- package/lib/material/node/blocks/reflection-texture-block.js +1 -4
- package/lib/material/node/blocks/reflection-texture-block.js.map +1 -1
- package/lib/material/node/blocks/texture-block.js +2 -5
- package/lib/material/node/blocks/texture-block.js.map +1 -1
- package/lib/material/node/blocks/triplanar-block.js +3 -6
- package/lib/material/node/blocks/triplanar-block.js.map +1 -1
- package/lib/material/node/node-emitter.js +24 -1
- package/lib/material/node/node-emitter.js.map +1 -1
- package/lib/material/node/node-geometry-renderable.js +2 -2
- package/lib/material/node/node-material.js +1 -22
- package/lib/material/node/node-material.js.map +1 -1
- package/lib/material/node/node-types.js.map +1 -1
- package/lib/material/pbr/fragments/shadow-only-fragment.js +68 -0
- package/lib/material/pbr/fragments/shadow-only-fragment.js.map +1 -0
- package/lib/material/pbr/pbr-flag-bits.js.map +1 -1
- package/lib/material/pbr/pbr-material.js.map +1 -1
- package/lib/material/pbr/pbr-renderable.js +3 -0
- package/lib/material/pbr/pbr-renderable.js.map +1 -1
- package/lib/material/pbr/pbr-template.js +1 -0
- package/lib/material/pbr/pbr-template.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js +2 -8
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js.map +1 -1
- package/lib/mesh/mesh-dispose.js +2 -0
- package/lib/mesh/mesh-dispose.js.map +1 -1
- package/lib/mesh/mesh.js +2 -8
- package/lib/mesh/mesh.js.map +1 -1
- package/lib/mesh/thin-instance-cull-binding.js +54 -3
- package/lib/mesh/thin-instance-cull-binding.js.map +1 -1
- package/lib/mesh/thin-instance-gpu-culling.js +241 -24
- package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
- package/lib/mesh/thin-instance.js +112 -1
- package/lib/mesh/thin-instance.js.map +1 -1
- package/lib/picking/gpu-picker.js +4 -2
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/picking/picking-pipeline.js +1 -1
- package/lib/picking/picking-pipeline.js.map +1 -1
- package/lib/picking/picking-shader.js +38 -16
- package/lib/picking/picking-shader.js.map +1 -1
- package/lib/scene/scene-core.js +3 -0
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/scene/scene-node.js +2 -6
- package/lib/scene/scene-node.js.map +1 -1
- package/lib/scene/transform-node.js +3 -0
- package/lib/scene/transform-node.js.map +1 -1
- package/lib/scene/world-matrix-state.js +7 -1
- package/lib/scene/world-matrix-state.js.map +1 -1
- package/lib/shadow/csm-directional-shadow-generator.js +22 -1
- package/lib/shadow/csm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/csm-shadow-task-hooks.js +19 -11
- package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
- package/lib/shadow/esm-directional-shadow-generator.js +2 -51
- package/lib/shadow/esm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/pcf-directional-shadow-generator.js +2 -48
- package/lib/shadow/pcf-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/shadow-base.js +48 -1
- package/lib/shadow/shadow-base.js.map +1 -1
- package/lib/text/text-renderable.js +2 -10
- package/lib/text/text-renderable.js.map +1 -1
- package/lib/texture/texture-array.js +96 -0
- package/lib/texture/texture-array.js.map +1 -0
- package/package.json +3 -3
package/index.d.ts
CHANGED
|
@@ -594,6 +594,14 @@ export declare interface ArcRotateInterpolationOptions {
|
|
|
594
594
|
interpolationFactor?: number;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
/** Per-layer upload options for `uploadImageToArrayLayer()` / `loadImageToArrayLayer()`. */
|
|
598
|
+
export declare interface ArrayLayerUploadOptions {
|
|
599
|
+
/** Flip Y during upload. Default true (matches Babylon.js convention). */
|
|
600
|
+
invertY?: boolean;
|
|
601
|
+
/** Treat the destination as premultiplied-alpha. Default false (straight RGBA). */
|
|
602
|
+
premultiplyAlpha?: boolean;
|
|
603
|
+
}
|
|
604
|
+
|
|
597
605
|
/**
|
|
598
606
|
* Result returned by loadGltf / loadBabylon.
|
|
599
607
|
* Pass directly to addToScene() — it handles all fields automatically.
|
|
@@ -853,6 +861,11 @@ export declare interface AudioEngine {
|
|
|
853
861
|
/** Fires on every qualifying user gesture (click), not just the first. */
|
|
854
862
|
readonly onUserGesture: AudioSignal<void>;
|
|
855
863
|
|
|
864
|
+
/** Pure-state handle for a MediaStream carrying the audio engine's final master mix. */
|
|
865
|
+
export declare interface AudioEngineMediaStream {
|
|
866
|
+
/** One live audio track containing the post-master engine output. */
|
|
867
|
+
readonly stream: MediaStream;
|
|
868
|
+
|
|
856
869
|
/** Options for {@link createAudioEngineAsync}. */
|
|
857
870
|
export declare interface AudioEngineOptions {
|
|
858
871
|
/**
|
|
@@ -1552,6 +1565,11 @@ export declare function clearSprite2DLayer(layer: Sprite2DLayer): void;
|
|
|
1552
1565
|
*/
|
|
1553
1566
|
export declare function clearSpriteAnimations(manager: SpriteAnimationManager): void;
|
|
1554
1567
|
|
|
1568
|
+
/** Dissolve a `setThinInstanceLodPartner` pairing: `fullMesh` culling reverts to its single-bucket output and
|
|
1569
|
+
* the former partner returns to independent rendering (drawing its own instance count again after the next
|
|
1570
|
+
* renderable rebuild; GPU culling auto-enabled by the pairing is switched back off). */
|
|
1571
|
+
export declare function clearThinInstanceLodPartner(fullMesh: Mesh): void;
|
|
1572
|
+
|
|
1555
1573
|
/** A clipping plane expressed as the coefficients `[a, b, c, d]` of `a·x + b·y + c·z + d`. */
|
|
1556
1574
|
export declare type ClipPlane = readonly [number, number, number, number];
|
|
1557
1575
|
|
|
@@ -1830,6 +1848,14 @@ export declare function createAudioBusAsync(engine: AudioEngine, name: string, o
|
|
|
1830
1848
|
*/
|
|
1831
1849
|
export declare function createAudioEngineAsync(options?: AudioEngineOptions): Promise<AudioEngine>;
|
|
1832
1850
|
|
|
1851
|
+
/**
|
|
1852
|
+
* Mirrors an engine's final master output into a MediaStream.
|
|
1853
|
+
*
|
|
1854
|
+
* Real-time Web Audio is required because OfflineAudioContext has no
|
|
1855
|
+
* MediaStream destination. The engine's audible destination remains connected.
|
|
1856
|
+
*/
|
|
1857
|
+
export declare function createAudioEngineMediaStream(engine: AudioEngine): AudioEngineMediaStream;
|
|
1858
|
+
|
|
1833
1859
|
/**
|
|
1834
1860
|
* Creates a real-time visualizer that taps the host's analyzer and draws to the
|
|
1835
1861
|
* given canvas. Enables the analyzer on the host if it is not already enabled.
|
|
@@ -2844,6 +2870,36 @@ export declare function createTextRenderable(data: TextData, options?: TextRende
|
|
|
2844
2870
|
* @returns A rendering context that can be registered with the engine. */
|
|
2845
2871
|
export declare function createTextRenderer(surface: SurfaceContext, opts: TextRendererOptions): TextRenderer;
|
|
2846
2872
|
|
|
2873
|
+
/**
|
|
2874
|
+
* Create an empty 2D texture array of `layers` same-size RGBA8 layers, ready to
|
|
2875
|
+
* be filled with `uploadImageToArrayLayer()` / `loadImageToArrayLayer()`.
|
|
2876
|
+
*
|
|
2877
|
+
* The texture is created with `TEXTURE_BINDING | COPY_DST | RENDER_ATTACHMENT`
|
|
2878
|
+
* usage — `copyExternalImageToTexture` (used by the upload helpers) requires
|
|
2879
|
+
* both `COPY_DST` and `RENDER_ATTACHMENT` on the destination, and the render
|
|
2880
|
+
* attachment is also what the mipmap-blit pass writes into.
|
|
2881
|
+
*
|
|
2882
|
+
* @param engine - Engine context.
|
|
2883
|
+
* @param width - Layer width in texels (\>= 1).
|
|
2884
|
+
* @param height - Layer height in texels (\>= 1).
|
|
2885
|
+
* @param layers - Number of array layers (\>= 1).
|
|
2886
|
+
* @param options - Sampler / format overrides.
|
|
2887
|
+
*/
|
|
2888
|
+
export declare function createTexture2DArray(engine: EngineContext, width: number, height: number, layers: number, options?: TextureArrayOptions): Texture2DArray;
|
|
2889
|
+
|
|
2890
|
+
/**
|
|
2891
|
+
* Create a 2D texture array and populate every layer from a list of image URLs
|
|
2892
|
+
* — one URL per layer, in order. All images must decode to the same dimensions
|
|
2893
|
+
* (the array's `width`/`height` are taken from the first). This is the
|
|
2894
|
+
* highest-level, most ergonomic entry point.
|
|
2895
|
+
*
|
|
2896
|
+
* @param engine - Engine context.
|
|
2897
|
+
* @param urls - One image URL per layer (`urls.length` \>= 1).
|
|
2898
|
+
* @param options - Sampler / format overrides.
|
|
2899
|
+
* @returns A promise resolving to the populated `Texture2DArray`.
|
|
2900
|
+
*/
|
|
2901
|
+
export declare function createTexture2DArrayFromUrls(engine: EngineContext, urls: readonly [string, ...string[]], options?: TextureArrayOptions): Promise<Texture2DArray>;
|
|
2902
|
+
|
|
2847
2903
|
/**
|
|
2848
2904
|
* Create a `Texture2D` from a tightly-packed RGBA8 byte buffer.
|
|
2849
2905
|
*
|
|
@@ -3228,6 +3284,12 @@ export declare function disposeAudioBus(bus: AudioBus): void;
|
|
|
3228
3284
|
*/
|
|
3229
3285
|
export declare function disposeAudioEngine(engine: AudioEngine): void;
|
|
3230
3286
|
|
|
3287
|
+
/**
|
|
3288
|
+
* Disconnects a media-stream tap and stops every track owned by its stream.
|
|
3289
|
+
* Safe to call more than once.
|
|
3290
|
+
*/
|
|
3291
|
+
export declare function disposeAudioEngineMediaStream(output: AudioEngineMediaStream): void;
|
|
3292
|
+
|
|
3231
3293
|
/**
|
|
3232
3294
|
* Stops the render loop and releases the visualizer. The underlying analyzer tap
|
|
3233
3295
|
* stays on the host (dispose the host to release it).
|
|
@@ -4279,6 +4341,18 @@ export declare function getClosestPoint(plugin: NavigationPlugin, position: Vec3
|
|
|
4279
4341
|
*/
|
|
4280
4342
|
export declare function getContainerMeshes(container: AssetContainer): Mesh[];
|
|
4281
4343
|
|
|
4344
|
+
/**
|
|
4345
|
+
* Returns the borrowed depth-array texture wrapper used by a custom CSM receiver.
|
|
4346
|
+
*
|
|
4347
|
+
* The wrapper shares the generator's texture and comparison sampler, is cached per
|
|
4348
|
+
* generator, and remains valid for the generator's lifetime. Callers must not dispose
|
|
4349
|
+
* or release it independently.
|
|
4350
|
+
*
|
|
4351
|
+
* @param sg - A cascaded-shadow generator from {@link createCsmDirectionalShadowGenerator}.
|
|
4352
|
+
* @returns A stable `Texture2D` with a 2d-array depth view.
|
|
4353
|
+
*/
|
|
4354
|
+
export declare function getCsmReceiverTexture(sg: ShadowGenerator): Texture2D;
|
|
4355
|
+
|
|
4282
4356
|
/** Returns the render-target aspect ratio adjusted for the camera's normalized viewport, or the raw ratio if none. */
|
|
4283
4357
|
export declare function getEffectiveAspectRatio(camera: Camera | null | undefined, targetWidth: number, targetHeight: number): number;
|
|
4284
4358
|
|
|
@@ -5088,6 +5162,20 @@ export declare function loadGltf(engine: EngineContext, source: string | ArrayBu
|
|
|
5088
5162
|
*/
|
|
5089
5163
|
export declare function loadHdrEnvironment(scene: SceneContext, url: string, options?: HdrLoadOptions): Promise<EnvironmentTextures>;
|
|
5090
5164
|
|
|
5165
|
+
/**
|
|
5166
|
+
* Fetch an image from `url`, decode it to an `ImageBitmap`, and upload it into
|
|
5167
|
+
* `layer` of a texture array. This is the optional URL-loading counterpart to
|
|
5168
|
+
* `uploadImageToArrayLayer()`; keeping it a separate function means apps that
|
|
5169
|
+
* already hold a decoded source never pull in the fetch/decode path.
|
|
5170
|
+
*
|
|
5171
|
+
* @param engine - Engine context.
|
|
5172
|
+
* @param tex - Target texture array (from `createTexture2DArray`).
|
|
5173
|
+
* @param layer - Destination layer index in `[0, tex.layers)`.
|
|
5174
|
+
* @param url - Image URL to fetch and decode.
|
|
5175
|
+
* @param opts - Flip-Y / premultiply overrides.
|
|
5176
|
+
*/
|
|
5177
|
+
export declare function loadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, url: string, opts?: ArrayLayerUploadOptions): Promise<void>;
|
|
5178
|
+
|
|
5091
5179
|
/** Fetch and decode a standalone KTX2 (Basis Universal) texture from a URL into a Texture2D, transcoded to the
|
|
5092
5180
|
* device's best GPU-compressed format (BC7/ETC2/ASTC) so it STAYS compressed in VRAM (a few times less than the
|
|
5093
5181
|
* uncompressed RGBA8 `loadTexture2D` always uploads). Mirrors `loadKtxTexture2D` (KTX1) for app textures that
|
|
@@ -5571,6 +5659,10 @@ declare interface NodeEmitContext {
|
|
|
5571
5659
|
readonly temp: (state: NodeBuildState, prefix?: string) => string;
|
|
5572
5660
|
/** Cast a typed expression to a target WGSL type when the shapes differ. */
|
|
5573
5661
|
readonly cast: (value: NodeExpr, target: NodeValueType) => NodeExpr;
|
|
5662
|
+
/** Sanitize a block/input name for use as a WGSL identifier. */
|
|
5663
|
+
readonly sanitize: (name: string) => string;
|
|
5664
|
+
/** Map Babylon.js connection-point flags to Lite's node value types. */
|
|
5665
|
+
readonly bjsTypeToNodeType: (type: number, source?: string) => NodeValueType;
|
|
5574
5666
|
/** Access the surrounding graph (so emitters can find upstream blocks). */
|
|
5575
5667
|
readonly graph: NodeGraph;
|
|
5576
5668
|
|
|
@@ -6080,7 +6172,27 @@ export declare interface PbrMaterialProps extends Material {
|
|
|
6080
6172
|
/** Linear-RGB tint applied to baseColor when `unlit` is true (i.e. glTF
|
|
6081
6173
|
* `baseColorFactor`). When omitted or [1,1,1], no tint is applied.
|
|
6082
6174
|
* Only bundled/bound when the unlit extension is active. */
|
|
6083
|
-
unlitColor?: [number, number, number];
|
|
6084
6175
|
/** Optional stencil-test state baked into the main-pass pipeline. Lets this material write the stencil buffer
|
|
6176
|
+
unlitColor?: [number, number, number];
|
|
6177
|
+
/** When true, the material is a shadow-only receiver: the surface is invisible
|
|
6178
|
+
* except where a shadow is cast on it, where it appears in `shadowOnlyColor` (or
|
|
6179
|
+
* black when omitted). Mirrors BJS `BackgroundMaterial.shadowOnly`. Requires
|
|
6180
|
+
* `receiveShadows` on the mesh and at least one shadow-casting light in the scene.
|
|
6181
|
+
* Implies alpha-blended rendering. Only bundled/bound when at least one mesh in
|
|
6182
|
+
* the scene uses it. */
|
|
6183
|
+
shadowOnly?: boolean;
|
|
6184
|
+
/** Linear-RGB color shown where the shadow falls when `shadowOnly` is true.
|
|
6185
|
+
* Defaults to black (`[0, 0, 0]`). */
|
|
6186
|
+
shadowOnlyColor?: [number, number, number];
|
|
6187
|
+
/** Maximum opacity at the darkest part of the shadow (when `shadowOnly` is true).
|
|
6188
|
+
* Range [0, 1]. Default 1.0 (fully opaque at full shadow). Lower values produce
|
|
6189
|
+
* a lighter, more transparent shadow. Mirrors the `shadowLevel` parameter on BJS
|
|
6190
|
+
* `BackgroundMaterial.shadowOnly`. */
|
|
6191
|
+
shadowOnlyOpacity?: number;
|
|
6192
|
+
/** Falloff sharpness for the shadow's soft edges (when `shadowOnly` is true).
|
|
6193
|
+
* Default 1.0 (the natural ESM/PCF falloff from the shadow generator). Higher
|
|
6194
|
+
* values steepen the falloff (saturating closer to the model silhouette), giving
|
|
6195
|
+
* crisper visible edges. Mathematically: `alpha = saturate((1 - shadowFactor) * falloff) * opacity`. */
|
|
6196
|
+
shadowOnlyFalloff?: number;
|
|
6085
6197
|
/** Optional stencil-test state baked into the main-pass pipeline. Lets this material write the stencil buffer
|
|
6086
6198
|
* where it draws (mask) or discard where another material wrote it. Default none. See `StencilState`. */
|
|
6087
6199
|
stencil?: StencilState;
|
|
6088
6200
|
}
|
|
@@ -6548,9 +6660,11 @@ export declare interface PickOptions {
|
|
|
6548
6660
|
*
|
|
6549
6661
|
* `fn shouldDiscardPick(input: PickDiscardInput) -> bool`
|
|
6550
6662
|
*
|
|
6551
|
-
* The input exposes only generic picker data: `worldPos`, `
|
|
6552
|
-
*
|
|
6553
|
-
*
|
|
6663
|
+
* The input exposes only generic picker data: `worldPos`, `fragmentCoord` (the selected pixel
|
|
6664
|
+
* centre in the original backing framebuffer), `pickId`, `thinInstanceIndex`,
|
|
6665
|
+
* `hasThinInstance`, and `instanceExtras` (the
|
|
6666
|
+
* original thin-instance matrix w lanes, zero for non-instanced meshes). Storage entries are
|
|
6667
|
+
* uploaded and bound by Lite for the current pick only. */
|
|
6554
6668
|
discard?: PickDiscardRule;
|
|
6555
6669
|
/** Dev-only diagnostics: logs the pick ray, pixel, pick id/depth and resolved mesh. */
|
|
6556
6670
|
debugLabel?: string;
|
|
@@ -8164,6 +8278,18 @@ export declare function setShaderUniform(material: ShaderMaterial, name: string,
|
|
|
8164
8278
|
/** Set a declared `vec3<f32>` uniform. Convenience wrapper over `setShaderUniform()`. */
|
|
8165
8279
|
export declare function setShaderVector3(material: ShaderMaterial, name: string, value: readonly [number, number, number]): void;
|
|
8166
8280
|
|
|
8281
|
+
/**
|
|
8282
|
+
* Cap the cascades a caster mesh renders into: the mesh casts only into cascade layers `0..maxCascade`
|
|
8283
|
+
* (0 = the nearest). Lets a scene keep small casters out of the far cascades, where their shadows are
|
|
8284
|
+
* sub-texel anyway — each excluded layer saves that caster's draw + pipeline switch per frame.
|
|
8285
|
+
*
|
|
8286
|
+
* Unset (the default) casts into every cascade. Pass `Infinity` to restore that.
|
|
8287
|
+
* The cap is read when a generator's caster set is (re)supplied through
|
|
8288
|
+
* {@link setShadowTaskCasterMeshes}; to change it for an already-registered caster, re-supply the
|
|
8289
|
+
* caster list (a new array) afterwards. Non-cascaded (single-map) generators ignore the cap.
|
|
8290
|
+
*/
|
|
8291
|
+
export declare function setShadowCasterMaxCascade(mesh: Mesh, maxCascade: number): void;
|
|
8292
|
+
|
|
8167
8293
|
/** Register scene-owned shadow caster inputs for a generator. */
|
|
8168
8294
|
export declare function setShadowTaskCasterMeshes(shadowGenerator: ShadowGenerator, casterMeshes: readonly Mesh[]): void;
|
|
8169
8295
|
|
|
@@ -8366,6 +8492,17 @@ export declare function setThinInstanceCullBoundsPad(mesh: Mesh, pad: number): v
|
|
|
8366
8492
|
* must have completed an initial full-capacity GPU synchronization. */
|
|
8367
8493
|
export declare function setThinInstanceDrawCount(mesh: Mesh, count: number): void;
|
|
8368
8494
|
|
|
8495
|
+
/** Pair a GPU-culled thin-instanced mesh with a lower-detail partner: when `fullMesh`'s compute cull runs,
|
|
8496
|
+
* in-frustum instances closer than `options.distance` keep drawing through `fullMesh` while farther ones are
|
|
8497
|
+
* compacted into a second bucket drawn by `lodMesh` instead. `lodMesh` must be a normal scene mesh sharing the
|
|
8498
|
+
* same thin-instance matrix layout (it may reference the same matrices array); while paired it draws ONLY the
|
|
8499
|
+
* far bucket — never its own instance count — so when culling is disabled, unavailable, or the instance count
|
|
8500
|
+
* is 0, `fullMesh` falls back to drawing ALL instances and `lodMesh` draws nothing. `options.band` dithers the
|
|
8501
|
+
* threshold per instance by ±band/2 via a deterministic hash of the instance index. Like
|
|
8502
|
+
* `enableThinInstanceGpuCulling`, call after `setThinInstances()` and before `registerScene()`;
|
|
8503
|
+
* `distance`/`band` may be re-set live by calling again with the same pair. */
|
|
8504
|
+
export declare function setThinInstanceLodPartner(fullMesh: Mesh, lodMesh: Mesh, options: ThinInstanceLodPartnerOptions): void;
|
|
8505
|
+
|
|
8369
8506
|
/** Update one instance's matrix. */
|
|
8370
8507
|
export declare function setThinInstanceMatrix(mesh: Mesh, index: number, matrix: Mat4): void;
|
|
8371
8508
|
|
|
@@ -9793,6 +9930,15 @@ export declare interface Texture2D {
|
|
|
9793
9930
|
* in-place row flipping is impractical) remain correct. */
|
|
9794
9931
|
invertY?: boolean;
|
|
9795
9932
|
|
|
9933
|
+
/** A 2D texture array handle. It is a `Texture2D` (so it drops straight into
|
|
9934
|
+
* `setEffectTexture` / material sampler bindings) whose `view` is created with
|
|
9935
|
+
* `dimension:"2d-array"`, plus a `layers` count. Bind it to a shader sampler
|
|
9936
|
+
* declared `viewDimension:"2d-array"` and sample it in WGSL as
|
|
9937
|
+
* `texture_2d_array<f32>`. */
|
|
9938
|
+
export declare interface Texture2DArray extends Texture2D {
|
|
9939
|
+
layers: number;
|
|
9940
|
+
}
|
|
9941
|
+
|
|
9796
9942
|
/** Sampler, format, and decode options for `loadTexture2D()`. */
|
|
9797
9943
|
export declare interface Texture2DOptions {
|
|
9798
9944
|
/** Generate mipmaps. Default true. */
|
|
@@ -9823,6 +9969,23 @@ export declare type Texture3D = Texture2D & {
|
|
|
9823
9969
|
depth: number;
|
|
9824
9970
|
};
|
|
9825
9971
|
|
|
9972
|
+
/** Sampler and format options for `createTexture2DArray()`. */
|
|
9973
|
+
export declare interface TextureArrayOptions {
|
|
9974
|
+
/** Generate a full mip chain for each layer on upload. Default true. */
|
|
9975
|
+
mipMaps?: boolean;
|
|
9976
|
+
/** Use sRGB format (rgba8unorm-srgb) so the hardware converts to linear on
|
|
9977
|
+
* sample. Use for color/albedo layers in PBR workflows. Default false. */
|
|
9978
|
+
srgb?: boolean;
|
|
9979
|
+
/** Address mode U. Default 'repeat'. */
|
|
9980
|
+
addressModeU?: GPUAddressMode;
|
|
9981
|
+
/** Address mode V. Default 'repeat'. */
|
|
9982
|
+
addressModeV?: GPUAddressMode;
|
|
9983
|
+
/** Min filter. Default 'linear'. */
|
|
9984
|
+
minFilter?: GPUFilterMode;
|
|
9985
|
+
/** Mag filter. Default 'linear'. */
|
|
9986
|
+
magFilter?: GPUFilterMode;
|
|
9987
|
+
}
|
|
9988
|
+
|
|
9826
9989
|
/** Thickness sub-feature. Controls how thick the material is at each point. */
|
|
9827
9990
|
export declare interface ThicknessProps {
|
|
9828
9991
|
/** Thickness map texture. R channel is sampled by default (matches
|
|
@@ -9849,6 +10012,14 @@ export declare interface ThinInstanceData {
|
|
|
9849
10012
|
count: number;
|
|
9850
10013
|
/** Optional per-instance RGBA colors (4 floats per instance). */
|
|
9851
10014
|
colors?: Float32Array | null;
|
|
9852
10015
|
|
|
10016
|
+
/** Options for `setThinInstanceLodPartner`. */
|
|
10017
|
+
export declare interface ThinInstanceLodPartnerOptions {
|
|
10018
|
+
/** Camera distance (world units) at which an in-frustum instance switches from `fullMesh` to the LOD partner. */
|
|
10019
|
+
distance: number;
|
|
10020
|
+
/** Width (world units) of a per-instance threshold dither window centered on `distance` (default 0 — hard cut). */
|
|
10021
|
+
band?: number;
|
|
10022
|
+
}
|
|
10023
|
+
|
|
9853
10024
|
/** Tint sub-feature. Controls absorption tint color for transmittance. */
|
|
9854
10025
|
export declare interface TintProps {
|
|
9855
10026
|
/** Tint color (linear RGB). Default [1,1,1]. */
|
|
@@ -10201,6 +10372,22 @@ export declare function updateTextData(data: TextData, update: TextDataUpdate):
|
|
|
10201
10372
|
*/
|
|
10202
10373
|
export declare function updateTexture2DFromPixels(engine: EngineContext, tex: Texture2D, data: Uint8Array, x?: number, y?: number, width?: number, height?: number): void;
|
|
10203
10374
|
|
|
10375
|
+
/**
|
|
10376
|
+
* Fill one layer of a texture array from an already-decoded external image
|
|
10377
|
+
* source — an `ImageBitmap`, `ImageData`, canvas (`HTMLCanvasElement` /
|
|
10378
|
+
* `OffscreenCanvas`), `HTMLImageElement`, `HTMLVideoElement`, or `VideoFrame`.
|
|
10379
|
+
* All of these are accepted directly by WebGPU's `copyExternalImageToTexture`,
|
|
10380
|
+
* so this is a single GPU copy with no per-source-type branching. If the array
|
|
10381
|
+
* was created with mipmaps, the layer's mip chain is regenerated after upload.
|
|
10382
|
+
*
|
|
10383
|
+
* @param engine - Engine context.
|
|
10384
|
+
* @param tex - Target texture array (from `createTexture2DArray`).
|
|
10385
|
+
* @param layer - Destination layer index in `[0, tex.layers)`.
|
|
10386
|
+
* @param source - Any WebGPU external-image source sized `tex.width`×`tex.height`.
|
|
10387
|
+
* @param opts - Flip-Y / premultiply overrides.
|
|
10388
|
+
*/
|
|
10389
|
+
export declare function uploadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, source: GPUCopyExternalImageSource, opts?: ArrayLayerUploadOptions): void;
|
|
10390
|
+
|
|
10204
10391
|
/** UtilityLayer handle. The `scene` field is a regular `SceneContext` — pass it
|
|
10205
10392
|
* to gizmo factories so their meshes are added there instead of the main
|
|
10206
10393
|
* scene. */
|
package/lib/audio/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createAudioEngineAsync, disposeAudioEngine, getMasterVolume, setMasterVolume, unlockAudioEngineAsync } from './audio-engine.js';
|
|
2
|
+
export { createAudioEngineMediaStream, disposeAudioEngineMediaStream } from './media-stream-output.js';
|
|
2
3
|
export { SoundState, createSoundAsync, disposeSound, pauseSound, playSound, resumeSound, setSoundVolume, stopSound } from './static-sound.js';
|
|
3
4
|
export { createStreamingSoundAsync, disposeStreamingSound, pauseStreamingSound, playStreamingSound, preloadStreamingInstanceAsync, preloadStreamingInstancesAsync, resumeStreamingSound, setStreamingSoundVolume, stopStreamingSound } from './streaming-sound.js';
|
|
4
5
|
export { createAudioBusAsync, disposeAudioBus, setBusVolume } from './audio-bus.js';
|
package/lib/audio/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function createAudioEngineMediaStream(engine) {
|
|
2
|
+
const context = engine._ctx;
|
|
3
|
+
if (engine._isOffline || typeof context.createMediaStreamDestination !== "function") {
|
|
4
|
+
throw new Error("Audio engine media streams require a real-time AudioContext.");
|
|
5
|
+
}
|
|
6
|
+
const source = engine._mainOut._gain;
|
|
7
|
+
const destination = context.createMediaStreamDestination();
|
|
8
|
+
source.connect(destination);
|
|
9
|
+
const output = {
|
|
10
|
+
stream: destination.stream,
|
|
11
|
+
_engine: engine,
|
|
12
|
+
_source: source,
|
|
13
|
+
_destination: destination,
|
|
14
|
+
_engineDisposer: () => {
|
|
15
|
+
output._registered = false;
|
|
16
|
+
disposeAudioEngineMediaStream(output);
|
|
17
|
+
},
|
|
18
|
+
_registered: true,
|
|
19
|
+
_disposed: false,
|
|
20
|
+
_dispose: () => disposeAudioEngineMediaStream(output)
|
|
21
|
+
};
|
|
22
|
+
engine._disposers.push(output._engineDisposer);
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
function disposeAudioEngineMediaStream(output) {
|
|
26
|
+
if (output._disposed) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
output._disposed = true;
|
|
30
|
+
if (output._registered) {
|
|
31
|
+
output._registered = false;
|
|
32
|
+
const disposerIndex = output._engine._disposers.indexOf(output._engineDisposer);
|
|
33
|
+
if (disposerIndex !== -1) {
|
|
34
|
+
output._engine._disposers.splice(disposerIndex, 1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
output._source.disconnect(output._destination);
|
|
38
|
+
for (const track of output.stream.getTracks()) {
|
|
39
|
+
track.stop();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { createAudioEngineMediaStream, disposeAudioEngineMediaStream };
|
|
44
|
+
//# sourceMappingURL=media-stream-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-stream-output.js","sources":["../../../src/audio/media-stream-output.ts"],"sourcesContent":["/**\n * Media-stream output — opt-in tap of the audio engine's final master mix.\n *\n * The tap mirrors the post-master signal into a MediaStream without changing\n * the normal speaker output. Consumers can use that stream for recording,\n * WebRTC, or other browser media pipelines, then dispose the tap independently.\n */\n\nimport type { AudioEngine } from \"./audio-engine.js\";\n\n/** Pure-state handle for a MediaStream carrying the audio engine's final master mix. */\nexport interface AudioEngineMediaStream {\n /** One live audio track containing the post-master engine output. */\n readonly stream: MediaStream;\n /** @internal */ readonly _engine: AudioEngine;\n /** @internal */ readonly _source: GainNode;\n /** @internal */ readonly _destination: MediaStreamAudioDestinationNode;\n /** @internal */ readonly _engineDisposer: () => void;\n /** @internal */ _registered: boolean;\n /** @internal */ _disposed: boolean;\n /** @internal */ _dispose(): void;\n}\n\n/**\n * Mirrors an engine's final master output into a MediaStream.\n *\n * Real-time Web Audio is required because OfflineAudioContext has no\n * MediaStream destination. The engine's audible destination remains connected.\n */\nexport function createAudioEngineMediaStream(engine: AudioEngine): AudioEngineMediaStream {\n const context = engine._ctx;\n if (engine._isOffline || typeof (context as AudioContext).createMediaStreamDestination !== \"function\") {\n throw new Error(\"Audio engine media streams require a real-time AudioContext.\");\n }\n\n const source = engine._mainOut._gain;\n const destination = (context as AudioContext).createMediaStreamDestination();\n source.connect(destination);\n\n const output: AudioEngineMediaStream = {\n stream: destination.stream,\n _engine: engine,\n _source: source,\n _destination: destination,\n _engineDisposer: () => {\n output._registered = false;\n disposeAudioEngineMediaStream(output);\n },\n _registered: true,\n _disposed: false,\n _dispose: () => disposeAudioEngineMediaStream(output),\n };\n\n engine._disposers.push(output._engineDisposer);\n return output;\n}\n\n/**\n * Disconnects a media-stream tap and stops every track owned by its stream.\n * Safe to call more than once.\n */\nexport function disposeAudioEngineMediaStream(output: AudioEngineMediaStream): void {\n if (output._disposed) {\n return;\n }\n\n output._disposed = true;\n if (output._registered) {\n output._registered = false;\n const disposerIndex = output._engine._disposers.indexOf(output._engineDisposer);\n if (disposerIndex !== -1) {\n output._engine._disposers.splice(disposerIndex, 1);\n }\n }\n output._source.disconnect(output._destination);\n for (const track of output.stream.getTracks()) {\n track.stop();\n }\n}\n"],"names":[],"mappings":"AA6BO,SAAS,6BAA6B,MAAA,EAA6C;AACtF,EAAA,MAAM,UAAU,MAAA,CAAO,IAAA;AACvB,EAAA,IAAI,MAAA,CAAO,UAAA,IAAc,OAAQ,OAAA,CAAyB,iCAAiC,UAAA,EAAY;AACnG,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAClF;AAEA,EAAA,MAAM,MAAA,GAAS,OAAO,QAAA,CAAS,KAAA;AAC/B,EAAA,MAAM,WAAA,GAAe,QAAyB,4BAAA,EAA6B;AAC3E,EAAA,MAAA,CAAO,QAAQ,WAAW,CAAA;AAE1B,EAAA,MAAM,MAAA,GAAiC;AAAA,IACnC,QAAQ,WAAA,CAAY,MAAA;AAAA,IACpB,OAAA,EAAS,MAAA;AAAA,IACT,OAAA,EAAS,MAAA;AAAA,IACT,YAAA,EAAc,WAAA;AAAA,IACd,iBAAiB,MAAM;AACnB,MAAA,MAAA,CAAO,WAAA,GAAc,KAAA;AACrB,MAAA,6BAAA,CAA8B,MAAM,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,WAAA,EAAa,IAAA;AAAA,IACb,SAAA,EAAW,KAAA;AAAA,IACX,QAAA,EAAU,MAAM,6BAAA,CAA8B,MAAM;AAAA,GACxD;AAEA,EAAA,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,MAAA,CAAO,eAAe,CAAA;AAC7C,EAAA,OAAO,MAAA;AACX;AAMO,SAAS,8BAA8B,MAAA,EAAsC;AAChF,EAAA,IAAI,OAAO,SAAA,EAAW;AAClB,IAAA;AAAA,EACJ;AAEA,EAAA,MAAA,CAAO,SAAA,GAAY,IAAA;AACnB,EAAA,IAAI,OAAO,WAAA,EAAa;AACpB,IAAA,MAAA,CAAO,WAAA,GAAc,KAAA;AACrB,IAAA,MAAM,gBAAgB,MAAA,CAAO,OAAA,CAAQ,UAAA,CAAW,OAAA,CAAQ,OAAO,eAAe,CAAA;AAC9E,IAAA,IAAI,kBAAkB,EAAA,EAAI;AACtB,MAAA,MAAA,CAAO,OAAA,CAAQ,UAAA,CAAW,MAAA,CAAO,aAAA,EAAe,CAAC,CAAA;AAAA,IACrD;AAAA,EACJ;AACA,EAAA,MAAA,CAAO,OAAA,CAAQ,UAAA,CAAW,MAAA,CAAO,YAAY,CAAA;AAC7C,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,SAAA,EAAU,EAAG;AAC3C,IAAA,KAAA,CAAM,IAAA,EAAK;AAAA,EACf;AACJ;;;;"}
|
package/lib/engine/engine.js
CHANGED
|
@@ -2,7 +2,7 @@ import { _setHpmAllocator } from '../math/_matrix-allocator.js';
|
|
|
2
2
|
import { isDomCanvas, _buildSurface, resizeSurface, _refreshScRT, setSurfaceSize } from './surface.js';
|
|
3
3
|
import { disposeGpuResourceRetirements } from './gpu-resource-retirement.js';
|
|
4
4
|
|
|
5
|
-
const VERSION = /* @__PURE__ */ (() => "1.
|
|
5
|
+
const VERSION = /* @__PURE__ */ (() => "1.12.0" )();
|
|
6
6
|
let _vis = 0;
|
|
7
7
|
function bumpVisibilityEpoch() {
|
|
8
8
|
_vis = _vis + 1 | 0;
|
|
@@ -392,5 +392,5 @@ function drawList(enc, list, engine) {
|
|
|
392
392
|
return draws;
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
-
export { _writePassSceneUBO, createRenderTask, removeMeshFromTask };
|
|
395
|
+
export { _writePassSceneUBO, createRenderTask, drawList, removeMeshFromTask };
|
|
396
396
|
//# sourceMappingURL=render-task.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-task.js","sources":["../../../src/frame-graph/render-task.ts"],"sourcesContent":["/**\n * RenderTask — a frame-graph task that records a single `RenderPass`,\n * binds the scene's `RenderTarget`, and draws renderables into it.\n *\n * - `record()` builds bucketed `DrawBinding` lists from `_renderables`\n * (opaque / direct / transparent), sorts opaque + direct by\n * `order`, then creates a `RenderPass` wired to the task's render target.\n * The pass owns its\n * `GPURenderPassDescriptor` and the per-pass-encoder body lives in a\n * closure passed to `setRenderPassExecuteFunc`.\n * - Before `RenderPass._execute()` begins the GPU pass: writes the scene UBO, refreshes lights, updates\n * per-binding UBOs, mirrors live `scene.clearColor` + `clr` onto the\n * render pass. Shared task execution then calls `_execute()`. The\n * `RenderPass` itself patches the swapchain view + clearColor + loadOp\n * and brackets the body with `beginRenderPass` / `end`.\n *\n * Renderable population:\n * - Explicit: push into `_renderables` directly, or `addMesh(mesh, opts)`\n * which builds a (mesh, material) Renderable at `record()` time.\n * - Auto scene mirror: when `_renderables` is empty at record() time, copy the\n * scene's renderables. Re-sync happens automatically when the scene's\n * `_renderableVersion` changes between frames (mesh add/remove, material swap).\n *\n * The engine `scRT` is just another `RenderTarget` here: a task that\n * targets it (`rt`) or resolves into it (`rst`) re-reads its per-frame color view\n * at execute time (the swap texture is re-acquired each frame). `clr: false`\n * switches color + depth `loadOp` to `\"load\"` so multiple scenes can share the\n * swapchain in one frame (e.g., a 3D scene + a UI overlay scene).\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { _vis } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { Renderable, DrawBinding, DrawUpdateContext, DrawUpdateBatch } from \"../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Material } from \"../material/material.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { buildRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { getViewMatrix } from \"../camera/camera.js\";\nimport { getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { _packSceneUniforms } from \"./scene-uniforms-pack.js\";\nimport { createEmptyUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { SCENE_UBO_BYTES } from \"../shader/scene-uniforms-size.js\";\nimport { ensureSceneLightState, refreshSceneLightsUBO } from \"../render/lights-ubo.js\";\nimport type { Task } from \"./task.js\";\n\n/** Configuration for `createRenderTask`: render target, clear state, optional camera override, and transmission settings. */\nexport interface RenderTaskConfig {\n name: string;\n /** TODO: rt should not live in this config long-term. Until texture\n * management is virtualized, callers must provide the concrete target; once\n * virtualized, the task should create/manage its own render target. */\n rt: RenderTarget;\n /** Optional single-sample resolve target. When `rt` is multisampled\n * (`sampleCount > 1`), the color attachment resolves into this target's\n * color texture at end-of-pass — letting an MSAA render feed a post-process\n * that requires a single-sample source, without an extra resolve pass.\n * Caller contract (not validated): must be single-sample with a color\n * format and size matching `rt`; WebGPU errors at pass-encode time if not.\n * Ignored when `rt` is single-sample. */\n rst?: RenderTarget;\n /** Optional separate depth/stencil attachment. The pass binds this target's\n * depth view instead of `rt`'s own, and uses its `depthStencilFormat` for\n * pipeline signature matching. The colour `rt` must omit `depthStencilFormat`\n * (so it allocates no internal depth) and match this target in size + sample\n * count. Two ownership modes, distinguished by `_eager`:\n * - `_eager` depth (e.g. a `GeometryRendererTask` output): the task neither\n * builds nor clears nor disposes it — it loads it (`loadOp: \"load\"`) and the\n * caller owns clearing. This is how scenes reuse a pre-rendered depth buffer.\n * - non-`_eager` depth: the task owns it — builds/rebuilds it in `record()`,\n * clears it (`loadOp: \"clear\"`), and disposes it. Used by the default\n * single-sample scene task, whose colour `rt` is the depth-less\n * engine `scRT`. */\n depth?: RenderTarget;\n /** Background clear color. May be mutated frame-to-frame. */\n clrColor?: GPUColorDict;\n /** When true, color `loadOp` is \"clear\"; when false, \"load\" (overlays previous\n * color content). Depth is always cleared when rt-owned and always loaded when\n * supplied via `depth`. */\n clr?: boolean;\n /** Per-pass camera override. Null/undefined uses `scene.camera`. */\n cam?: Camera | null;\n /** Use canvas dimensions, not render-target dimensions, for this pass's scene UBO aspect. */\n cs?: boolean;\n /** Scene-texture transmission settings. `copyCount: 0` copies before every transmissive draw.\n * `generateMipmaps: false` allocates only mip 0 for the refraction texture and skips mip generation.\n * `mipLevelCount` caps the generated chain when a material only samples low explicit LODs.\n * `grabDepth: true` also snapshots the task's DEPTH attachment at the same mid-pass grab (see\n * `TransmissionOptions.grabDepth`). */\n transmission?: { copyCount?: number; generateMipmaps?: boolean; mipLevelCount?: number; grabDepth?: boolean };\n /** @internal Skip clustered-light preparation for passes that never run forward lighting. */\n _skipClusteredLights?: boolean;\n}\n\n/** A frame-graph task that records a single `RenderPass`, binds the scene's `RenderTarget`, and draws renderables into it. */\nexport interface RenderTask extends Task {\n readonly name: string;\n /** Render tasks are scene-bound because they consume scene camera, lights, and renderables. */\n readonly scene: SceneContext;\n /** Live task configuration. Mutating `clr` or `clrColor` affects subsequent frames. */\n /** @internal */\n readonly _config: RenderTaskConfig;\n /** @internal */\n _autoFromScene: boolean;\n\n /** Source-of-truth renderables. Bucketed binding lists below are derived from\n * this list at `record()` (or re-sync when auto-filled and `_renderableVersion` changes). */\n /** @internal */\n _renderables: Renderable[];\n /** @internal */\n _opaqueBindings: DrawBinding[];\n /** @internal */\n _directBindings: DrawBinding[];\n /** @internal */\n _transparentBindings: DrawBinding[];\n /** Cached opaque render bundle. Invalidated by renderable list mutations\n * (`_lastVersion`) and the global visibility/resource epoch (`_lastVis`). */\n /** @internal */\n _opaqueBundles: GPURenderBundle[];\n /** @internal */\n _lastVersion: number;\n /** @internal */\n _lastVis: number;\n /** @internal True once `record()` has run — the task is \"live\" (GPU target allocated, material batch builders\n * present). A runtime `addMesh` after this resolves + re-buckets THIS task immediately (no frame-graph rebuild). */\n _recorded: boolean;\n\n /** @internal */\n _renderPassDescriptor: GPURenderPassDescriptor;\n /** @internal */\n _colorAttachment: GPURenderPassColorAttachment;\n /** @internal External depth source from `config.depth`. When unset,\n * the pass uses `config.rt._depthView`. */\n _depthSrc?: RenderTarget;\n /** @internal External depth/stencil `loadOp` (\"load\" when `config.depth` is\n * set). When unset, defaults to `\"clear\"`. */\n _depthLoadOp?: GPULoadOp;\n\n /** Per-task scene UBO + bind group. Created eagerly in createRenderTask\n * so renderables can reference `_sceneBG` at `bind()` time. Written each\n * frame by `_writePassSceneUBO`. Destroyed in `dispose()`. */\n /** @internal */\n _sceneUBO: GPUBuffer;\n /** @internal */\n _sceneBG: GPUBindGroup;\n /** @internal */\n _lightsUBO: GPUBuffer;\n /** @internal */\n _suData: Float32Array;\n /** @internal */\n _su: unknown[];\n /** Optional transmission-enabled execute path: copies the scene texture for refraction and draws transmissive\n * renderables. Present only when the task was configured with `transmission`. Returns the number of draw calls issued. */\n /** @internal */\n _executeWithTransmission?(sampleCount: number): number;\n /** @internal */\n _targetSignature: RenderTargetSignature;\n /** @internal Lazy feature work flushed after binding updates and before the render pass. */\n _updateBatches: DrawUpdateBatch[];\n\n /** Add a mesh to this task's explicit render list with an optional per-pass material override. Resolved via\n * `material._buildGroup._rebuildSingle`, so the mesh's material family must already have been registered with the\n * scene (its batch builder has run). BEFORE the first `record()` the add is QUEUED and drained at record() time;\n * AFTER (a live/runtime add) it is resolved + re-bucketed into THIS task immediately, so the mesh renders on the\n * next frame without a `frameGraph.build()` (which would re-allocate shared GPU resources across all tasks). */\n addMesh(mesh: Mesh, opts?: { material?: Material }): void;\n /** @internal */\n _pendingMeshes: { mesh: Mesh; material: Material }[];\n}\n\ninterface MutableDrawUpdateContext {\n targetWidth: number;\n targetHeight: number;\n _camera?: Camera | null;\n}\n\n/** Create a render pass task. GPU resources (target textures + descriptor)\n * are not allocated until `record()` runs (via `frameGraph.build()`).\n *\n * Swapchain-targeted tasks acquire the swap view per-frame at execute time. */\nexport function createRenderTask(config: RenderTaskConfig, engine: EngineContext, scene: SceneContext): RenderTask {\n const sc = scene as SceneContext;\n config.clrColor ??= { r: 0.2, g: 0.2, b: 0.3, a: 1.0 };\n config.clr ??= true;\n const desc = config.rt._descriptor;\n // Render upright: row 0 of the GPU texture is the top of the scene. Every\n // RT (offscreen or swapchain) renders without a projection Y-flip; pipelines\n // use the default ccw front face; downstream samplers see upright pixels.\n const targetSignature = {\n _colorFormat: desc.format,\n _depthStencilFormat: config.depth?._descriptor.dFormat ?? desc.dFormat,\n _depthCompare: desc._depthCompare,\n _sampleCount: desc.samples ?? 1,\n };\n\n const sceneBGL = getSceneBindGroupLayout(engine);\n const sceneUBO = createEmptyUniformBuffer(engine, SCENE_UBO_BYTES);\n const lightsUBO = ensureSceneLightState(engine, sc)._buffer;\n const sceneBG = engine._device.createBindGroup({\n layout: sceneBGL,\n entries: [\n { binding: 0, resource: { buffer: sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const updateContext: MutableDrawUpdateContext = { targetWidth: 0, targetHeight: 0 };\n const task: RenderTask = {\n name: config.name,\n _config: config,\n engine: engine,\n scene: sc,\n _passes: [],\n _autoFromScene: false,\n _renderables: [],\n _opaqueBindings: [],\n _directBindings: [],\n _transparentBindings: [],\n _opaqueBundles: [],\n _lastVersion: -1,\n _lastVis: 0,\n _recorded: false,\n _renderPassDescriptor: { colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _depthSrc: config.depth,\n _depthLoadOp: config.depth ? (config.depth._eager ? \"load\" : \"clear\") : undefined,\n _sceneUBO: sceneUBO,\n _sceneBG: sceneBG,\n _lightsUBO: lightsUBO,\n _suData: new F32(SCENE_UBO_BYTES / 4),\n _su: [],\n _targetSignature: targetSignature,\n _updateBatches: [],\n _pendingMeshes: [],\n addMesh(mesh, opts) {\n const material = opts?.material ?? mesh.material;\n if (!material) {\n return;\n }\n task._pendingMeshes.push({ mesh, material });\n if (task._recorded) {\n // Live (post-record) add: resolve + re-bucket THIS task now — buildBindings clears its bundle cache\n // so it re-records on the next execute. Deliberately NOT a frame-graph rebuild (that re-allocates the\n // shared scene UBO + every task's render target mid-frame and crashes the in-flight submit).\n resolvePendingMeshes(task, sc);\n // A live add makes the render list explicit (mirrors record(), where a pending mesh forces\n // _autoFromScene = false). Without this, an auto-mirroring task's next scene-version resync in\n // prepareRenderTaskPass would clear _renderables and drop the just-added mesh.\n task._autoFromScene = false;\n buildBindings(task, engine, targetSignature);\n }\n },\n record(): void {\n if (task._autoFromScene) {\n task._renderables.length = 0;\n }\n resolvePendingMeshes(task, sc);\n task._autoFromScene = task._renderables.length === 0;\n if (task._autoFromScene) {\n task._renderables.push(...sc._renderables);\n }\n // Read config.rt dynamically — transmission retargeting swaps it after\n // the task is created, and the engine scRT must never be rebuilt.\n const rt = config.rt;\n buildRenderTarget(rt, engine);\n if (config.rst && (rt._descriptor.samples ?? 1) > 1) {\n buildRenderTarget(config.rst, engine);\n }\n // A non-eager external depth (e.g. the default single-sample scene task's\n // depth, whose colour rt is the depth-less scRT) is task-managed:\n // build/rebuild it here. Eager depths (GeometryRendererTask outputs) are\n // pre-built and skipped by buildRenderTarget.\n if (config.depth && !config.depth._eager) {\n buildRenderTarget(config.depth, engine);\n }\n updateContext.targetWidth = rt._width;\n updateContext.targetHeight = rt._height;\n refreshTaskSceneBindGroup(task, engine);\n buildBindings(task, engine, targetSignature);\n buildRenderPassDescriptor(task, rt);\n task._recorded = true; // task is now live — a subsequent addMesh resolves + re-buckets immediately\n },\n execute(): number {\n return executePass(task, engine, targetSignature, updateContext);\n },\n dispose(): void {\n task._passes.length = 0;\n // disposeRenderTarget no-ops on the engine scRT and on eager\n // GeometryRendererTask depth outputs (both `_eager`), and on an undefined\n // rst/depth — so these can be passed unconditionally.\n disposeRenderTarget(config.rt);\n disposeRenderTarget(config.rst);\n disposeRenderTarget(config.depth);\n task._opaqueBindings.length = 0;\n task._directBindings.length = 0;\n task._transparentBindings.length = 0;\n task._renderables.length = 0;\n task._opaqueBundles.length = 0;\n task._sceneUBO.destroy();\n for (const batch of task._updateBatches) {\n batch.destroy();\n }\n task._updateBatches.length = 0;\n },\n };\n return task;\n}\n\n/** Remove a mesh from this task's renderable + binding lists. Idempotent. */\nexport function removeMeshFromTask(task: RenderTask, mesh: object): void {\n // Not a renderable-bearing task (e.g. a post/effect task that also carries `_config`): nothing to\n // remove. Guard keeps callers that scan all frame-graph tasks (removeFromScene) shape-safe.\n if (!task._renderables) {\n return;\n }\n let removed = false;\n for (let i = task._pendingMeshes.length - 1; i >= 0; i--) {\n if (task._pendingMeshes[i]!.mesh === mesh) {\n task._pendingMeshes.splice(i, 1);\n removed = true;\n }\n }\n for (let i = task._renderables.length - 1; i >= 0; i--) {\n if (task._renderables[i]!.mesh === mesh) {\n task._renderables.splice(i, 1);\n removed = true;\n }\n }\n for (const arr of [task._opaqueBindings, task._directBindings, task._transparentBindings]) {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (arr[i]!.renderable.mesh === mesh) {\n arr.splice(i, 1);\n removed = true;\n }\n }\n }\n if (removed) {\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction resolvePendingMeshes(task: RenderTask, sc: SceneContext): void {\n if (task._pendingMeshes.length === 0) {\n return;\n }\n for (const { mesh, material } of task._pendingMeshes) {\n const rebuild = material._buildGroup?._rebuildSingle;\n if (!rebuild) {\n throw new Error();\n }\n const renderable = rebuild(sc, mesh, material);\n if (!task._renderables.includes(renderable)) {\n task._renderables.push(renderable);\n }\n }\n task._pendingMeshes.length = 0;\n}\n\n/** Per-frame back-to-front sort for transparent bindings using the active camera. */\nfunction sortTransparentBindings(task: RenderTask, camera: Camera | null | undefined): void {\n const arr = task._transparentBindings;\n if (arr.length <= 1 || !camera) {\n return;\n }\n const v = getViewMatrix(camera);\n for (const b of arr) {\n const wc = b.renderable._worldCenter;\n b._sortDistance = wc ? wc[0]! * v[2]! + wc[1]! * v[6]! + wc[2]! * v[10]! + v[14]! : 0;\n }\n arr.sort((a, b) => b._sortDistance! - a._sortDistance! || a.renderable.order - b.renderable.order);\n}\n\n/** (Re)bucket task._renderables into bound lists. */\nfunction buildBindings(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature): void {\n const opaque = task._opaqueBindings;\n const direct = task._directBindings;\n const transparent = task._transparentBindings;\n opaque.length = 0;\n direct.length = 0;\n transparent.length = 0;\n for (const r of task._renderables) {\n const binding = r.bind(eng, targetSignature);\n for (const batch of binding._updateBatches ?? []) {\n if (!task._updateBatches.includes(batch)) {\n task._updateBatches.push(batch);\n }\n }\n if (r.isTransparent || r._transmissive) {\n transparent.push(binding);\n } else if (r._direct) {\n direct.push(binding);\n } else {\n opaque.push(binding);\n }\n }\n opaque.sort((a, b) => a.renderable.order - b.renderable.order);\n direct.sort((a, b) => a.renderable.order - b.renderable.order);\n task._opaqueBundles.length = 0;\n task._lastVersion = (task.scene as SceneContext)._renderableVersion;\n}\n\nfunction buildRenderPassDescriptor(task: RenderTask, rt: RenderTarget): void {\n const att = task._colorAttachment;\n att.view = rt._colorView!;\n // End-of-pass MSAA resolve into a caller-supplied single-sample target.\n // record() only builds the target's color view for an MSAA rt, so its\n // presence is the gate. The swapchain case is wired per-frame in\n // executePass (its view changes each frame); this custom view is stable.\n att.resolveTarget = task._config.rst?._colorView ?? undefined;\n task._renderPassDescriptor.colorAttachments = rt._colorView ? [att] : [];\n\n const depthSrc = task._depthSrc ?? rt;\n const depthView = depthSrc._depthView;\n let depthAttachment: GPURenderPassDepthStencilAttachment | undefined;\n if (depthView) {\n const dd = depthSrc._descriptor;\n const loadOp = task._depthLoadOp ?? \"clear\";\n depthAttachment = {\n view: depthView,\n depthClearValue: dd._depthClearValue ?? 0,\n depthLoadOp: loadOp,\n depthStoreOp: \"store\",\n };\n if (dd.dFormat?.includes(\"stencil\")) {\n depthAttachment.stencilClearValue = 0;\n depthAttachment.stencilLoadOp = loadOp;\n depthAttachment.stencilStoreOp = \"store\";\n }\n }\n\n task._renderPassDescriptor.depthStencilAttachment = depthAttachment;\n}\n\nfunction prepareRenderTaskPass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): void {\n const sc = task.scene as SceneContext;\n // Auto-resync when the source scene mutates.\n if (task._autoFromScene && task._lastVersion !== sc._renderableVersion) {\n task._renderables.length = 0;\n task._renderables.push(...sc._renderables);\n buildBindings(task, eng, targetSignature);\n }\n\n // Pre-pass work — runs before beginRenderPass. Updates the task-owned scene\n // UBO, scene-wide lights UBO, and per-binding UBOs. The scene bind group may\n // also need a refresh (lights buffer can be resized when glTF lights\n // extension raises MAX_LIGHTS after this task was first recorded).\n refreshTaskSceneBindGroup(task, eng);\n const camera = task._config.cam ?? sc.camera;\n if (!task._config._skipClusteredLights && targetSignature._colorFormat) {\n sc._clusteredLightUpdater?.(camera, context.targetWidth, context.targetHeight);\n }\n _writePassSceneUBO(task, eng, sc, camera);\n refreshSceneLightsUBO(eng, sc);\n // Expose the active camera to per-binding `update()` calls. Some renderables\n // (e.g. transparent billboard systems) need it to compute view-space sort\n // depths during their update.\n (context as MutableDrawUpdateContext)._camera = camera;\n for (const batch of task._updateBatches) {\n batch.reset();\n }\n updateBindings(task._opaqueBindings, context);\n updateBindings(task._directBindings, context);\n updateBindings(task._transparentBindings, context);\n for (const batch of task._updateBatches) {\n batch.flush(eng);\n }\n // Per-frame back-to-front sort for transparent bindings — must run AFTER\n // updateBindings so renderables that compute `_worldCenter` inside their\n // own `update()` (billboard systems) are seen with current values.\n sortTransparentBindings(task, camera);\n}\n\nfunction executePass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): number {\n const sc = task.scene;\n const sampleCount = targetSignature._sampleCount;\n prepareRenderTaskPass(task, eng, targetSignature, context);\n const att = task._colorAttachment;\n const cfg = task._config;\n if (cfg.rt._colorView) {\n // The engine scRT's color view is re-acquired every frame, so re-read\n // it here. Offscreen color views are stable between rebuilds — leaving att.view\n // untouched preserves an external override (swapchain-overlay shares the base\n // scene's MSAA color view). The resolve target (rst) is re-read each frame so an\n // `rst === scRT` picks up its fresh per-frame view.\n if (cfg.rt === eng.scRT) {\n att.view = cfg.rt._colorView;\n }\n att.resolveTarget = cfg.rst?._colorView ?? undefined;\n att.clearValue = task._autoFromScene ? sc.clearColor : cfg.clrColor!;\n att.loadOp = cfg.clr ? \"clear\" : \"load\";\n }\n if (task._executeWithTransmission) {\n return task._executeWithTransmission(sampleCount);\n }\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n const draws = executePassBody(task, pass);\n pass.end();\n return draws;\n}\n\n/** Body of the registered `RenderPass`. Receives the live render-pass encoder\n * and issues all draws (viewport/scissor, group(0) bind, opaque bundle replay,\n * then direct-draws non-transparent direct + transparent). Returns the draw count. */\nfunction executePassBody(task: RenderTask, pass: GPURenderPassEncoder): number {\n const eng = task.engine as EngineContext;\n const cfg = task._config;\n const rt = cfg.rt;\n const scene = task.scene as SceneContext;\n const opaqueBindings = task._opaqueBindings;\n const opaqueBundles = task._opaqueBundles;\n const sceneBG = task._sceneBG;\n\n const camera = cfg.cam ?? scene.camera;\n const v = camera?.viewport;\n if (v) {\n const rw = rt._width;\n const rh = rt._height;\n const x = Math.floor(v.x * rw);\n const y = Math.floor((1 - v.y - v.height) * rh);\n const w = Math.ceil((v.x + v.width) * rw) - x;\n const h = Math.ceil((1 - v.y) * rh) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n }\n // Scene bind group (group 0) is task-owned and identical for every draw in this pass.\n pass.setBindGroup(0, sceneBG);\n\n // Opaque: cached render bundle. Invalidated by scene mutation (_renderableVersion) or\n // the global visibility/resource epoch (_vis). The bundle records group(0) at its start.\n if (task._lastVersion !== scene._renderableVersion || task._lastVis !== _vis || opaqueBundles.length === 0) {\n const desc = rt._descriptor;\n const be = eng._device.createRenderBundleEncoder({\n colorFormats: desc.format ? [desc.format] : [],\n // Use the task's target signature, not the RT descriptor: a depth\n // override (config.depth) supplies the depth format externally, so\n // the cached opaque pipelines are built with it while the colour RT\n // carries no depthStencilFormat of its own. The bundle encoder's\n // attachment state must match those pipelines exactly.\n depthStencilFormat: task._targetSignature._depthStencilFormat,\n sampleCount: desc.samples ?? 1,\n });\n be.setBindGroup(0, sceneBG);\n drawList(be, opaqueBindings, eng);\n opaqueBundles[0] = be.finish();\n task._lastVersion = scene._renderableVersion;\n task._lastVis = _vis;\n }\n let draws = opaqueBindings.length;\n pass.executeBundles(opaqueBundles);\n // executeBundles invalidates pass bind-group state — rebind group 0 before further draws.\n pass.setBindGroup(0, sceneBG);\n draws += drawList(pass, task._directBindings, eng);\n draws += drawList(pass, task._transparentBindings, eng);\n return draws;\n}\n\nfunction refreshTaskSceneBindGroup(task: RenderTask, eng: EngineContext): void {\n const lightsUBO = ensureSceneLightState(eng, task.scene as SceneContext)._buffer;\n if (lightsUBO === task._lightsUBO) {\n return;\n }\n task._lightsUBO = lightsUBO;\n task._sceneBG = eng._device.createBindGroup({\n layout: getSceneBindGroupLayout(eng),\n entries: [\n { binding: 0, resource: { buffer: task._sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n}\n\n/** Write the canonical SceneUniforms struct to the task-owned scene UBO.\n * Bails before touching scratch/GPU when all inputs are unchanged.\n * @internal Exported for unit testing of the scene-UBO change-detection guard. */\nexport function _writePassSceneUBO(task: RenderTask, eng: EngineContext, scene: SceneContext, camera: Camera | null): void {\n if (!camera) {\n return;\n }\n\n const v = camera.viewport;\n const rt = task._config.rt;\n const aspect = (task._config.cs ? eng.canvas.width / eng.canvas.height : rt._width / rt._height) * (v ? v.width / v.height : 1);\n const fog = scene.fog;\n const img = scene.imageProcessing;\n const envRotationY = scene.envRotationY || 0;\n const wv = camera.worldMatrixVersion;\n // `envTextures` identity is tracked so an environment loaded (or swapped) AFTER the scene has reached\n // steady state invalidates this cache. Its spherical-harmonics irradiance and `lodGenerationScale` are\n // written into the scene UBO below (via `_packSceneUniforms` + the env-SH contributor); without tracking\n // it, a late env load would change none of the other guarded inputs, so the UBO would never be rewritten\n // and the model would keep zero irradiance (dark diffuse, specular-only \"mirror\" look).\n const envTextures = scene._envTextures;\n const s = task._su;\n if (s[0] === camera && s[1] === fog && s[2] === wv && s[3] === aspect && s[4] === envRotationY && s[5] === img.exposure && s[6] === img.contrast && s[7] === envTextures) {\n return;\n }\n s[0] = camera;\n s[1] = fog;\n s[2] = wv;\n s[3] = aspect;\n s[4] = envRotationY;\n s[5] = img.exposure;\n s[6] = img.contrast;\n s[7] = envTextures;\n\n const data = task._suData;\n _packSceneUniforms(data, eng, scene, camera, aspect);\n const contribs = scene._sceneUboContributors;\n if (contribs) {\n for (const c of contribs) {\n c(data, scene);\n }\n }\n eng._device.queue.writeBuffer(task._sceneUBO, 0, data as Float32Array<ArrayBuffer>);\n}\n\nfunction updateBindings(list: readonly DrawBinding[], context: DrawUpdateContext): void {\n for (const b of list) {\n b.update?.(context);\n }\n}\n\n/** Iterate DrawBindings, deduping setPipeline. */\nfunction drawList(enc: GPURenderPassEncoder | GPURenderBundleEncoder, list: readonly DrawBinding[], engine: EngineContext): number {\n let lp: GPURenderPipeline | null = null;\n let draws = 0;\n for (const b of list) {\n const mesh = b.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (b.pipeline !== lp) {\n enc.setPipeline(b.pipeline);\n lp = b.pipeline;\n }\n draws += b.draw(enc, engine);\n }\n return draws;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"render-task.js","sources":["../../../src/frame-graph/render-task.ts"],"sourcesContent":["/**\n * RenderTask — a frame-graph task that records a single `RenderPass`,\n * binds the scene's `RenderTarget`, and draws renderables into it.\n *\n * - `record()` builds bucketed `DrawBinding` lists from `_renderables`\n * (opaque / direct / transparent), sorts opaque + direct by\n * `order`, then creates a `RenderPass` wired to the task's render target.\n * The pass owns its\n * `GPURenderPassDescriptor` and the per-pass-encoder body lives in a\n * closure passed to `setRenderPassExecuteFunc`.\n * - Before `RenderPass._execute()` begins the GPU pass: writes the scene UBO, refreshes lights, updates\n * per-binding UBOs, mirrors live `scene.clearColor` + `clr` onto the\n * render pass. Shared task execution then calls `_execute()`. The\n * `RenderPass` itself patches the swapchain view + clearColor + loadOp\n * and brackets the body with `beginRenderPass` / `end`.\n *\n * Renderable population:\n * - Explicit: push into `_renderables` directly, or `addMesh(mesh, opts)`\n * which builds a (mesh, material) Renderable at `record()` time.\n * - Auto scene mirror: when `_renderables` is empty at record() time, copy the\n * scene's renderables. Re-sync happens automatically when the scene's\n * `_renderableVersion` changes between frames (mesh add/remove, material swap).\n *\n * The engine `scRT` is just another `RenderTarget` here: a task that\n * targets it (`rt`) or resolves into it (`rst`) re-reads its per-frame color view\n * at execute time (the swap texture is re-acquired each frame). `clr: false`\n * switches color + depth `loadOp` to `\"load\"` so multiple scenes can share the\n * swapchain in one frame (e.g., a 3D scene + a UI overlay scene).\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { _vis } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { Renderable, DrawBinding, DrawUpdateContext, DrawUpdateBatch } from \"../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Material } from \"../material/material.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { buildRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { getViewMatrix } from \"../camera/camera.js\";\nimport { getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { _packSceneUniforms } from \"./scene-uniforms-pack.js\";\nimport { createEmptyUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { SCENE_UBO_BYTES } from \"../shader/scene-uniforms-size.js\";\nimport { ensureSceneLightState, refreshSceneLightsUBO } from \"../render/lights-ubo.js\";\nimport type { Task } from \"./task.js\";\n\n/** Configuration for `createRenderTask`: render target, clear state, optional camera override, and transmission settings. */\nexport interface RenderTaskConfig {\n name: string;\n /** TODO: rt should not live in this config long-term. Until texture\n * management is virtualized, callers must provide the concrete target; once\n * virtualized, the task should create/manage its own render target. */\n rt: RenderTarget;\n /** Optional single-sample resolve target. When `rt` is multisampled\n * (`sampleCount > 1`), the color attachment resolves into this target's\n * color texture at end-of-pass — letting an MSAA render feed a post-process\n * that requires a single-sample source, without an extra resolve pass.\n * Caller contract (not validated): must be single-sample with a color\n * format and size matching `rt`; WebGPU errors at pass-encode time if not.\n * Ignored when `rt` is single-sample. */\n rst?: RenderTarget;\n /** Optional separate depth/stencil attachment. The pass binds this target's\n * depth view instead of `rt`'s own, and uses its `depthStencilFormat` for\n * pipeline signature matching. The colour `rt` must omit `depthStencilFormat`\n * (so it allocates no internal depth) and match this target in size + sample\n * count. Two ownership modes, distinguished by `_eager`:\n * - `_eager` depth (e.g. a `GeometryRendererTask` output): the task neither\n * builds nor clears nor disposes it — it loads it (`loadOp: \"load\"`) and the\n * caller owns clearing. This is how scenes reuse a pre-rendered depth buffer.\n * - non-`_eager` depth: the task owns it — builds/rebuilds it in `record()`,\n * clears it (`loadOp: \"clear\"`), and disposes it. Used by the default\n * single-sample scene task, whose colour `rt` is the depth-less\n * engine `scRT`. */\n depth?: RenderTarget;\n /** Background clear color. May be mutated frame-to-frame. */\n clrColor?: GPUColorDict;\n /** When true, color `loadOp` is \"clear\"; when false, \"load\" (overlays previous\n * color content). Depth is always cleared when rt-owned and always loaded when\n * supplied via `depth`. */\n clr?: boolean;\n /** Per-pass camera override. Null/undefined uses `scene.camera`. */\n cam?: Camera | null;\n /** Use canvas dimensions, not render-target dimensions, for this pass's scene UBO aspect. */\n cs?: boolean;\n /** Scene-texture transmission settings. `copyCount: 0` copies before every transmissive draw.\n * `generateMipmaps: false` allocates only mip 0 for the refraction texture and skips mip generation.\n * `mipLevelCount` caps the generated chain when a material only samples low explicit LODs.\n * `grabDepth: true` also snapshots the task's DEPTH attachment at the same mid-pass grab (see\n * `TransmissionOptions.grabDepth`). */\n transmission?: { copyCount?: number; generateMipmaps?: boolean; mipLevelCount?: number; grabDepth?: boolean };\n /** @internal Skip clustered-light preparation for passes that never run forward lighting. */\n _skipClusteredLights?: boolean;\n}\n\n/** A frame-graph task that records a single `RenderPass`, binds the scene's `RenderTarget`, and draws renderables into it. */\nexport interface RenderTask extends Task {\n readonly name: string;\n /** Render tasks are scene-bound because they consume scene camera, lights, and renderables. */\n readonly scene: SceneContext;\n /** Live task configuration. Mutating `clr` or `clrColor` affects subsequent frames. */\n /** @internal */\n readonly _config: RenderTaskConfig;\n /** @internal */\n _autoFromScene: boolean;\n\n /** Source-of-truth renderables. Bucketed binding lists below are derived from\n * this list at `record()` (or re-sync when auto-filled and `_renderableVersion` changes). */\n /** @internal */\n _renderables: Renderable[];\n /** @internal */\n _opaqueBindings: DrawBinding[];\n /** @internal */\n _directBindings: DrawBinding[];\n /** @internal */\n _transparentBindings: DrawBinding[];\n /** Cached opaque render bundle. Invalidated by renderable list mutations\n * (`_lastVersion`) and the global visibility/resource epoch (`_lastVis`). */\n /** @internal */\n _opaqueBundles: GPURenderBundle[];\n /** @internal */\n _lastVersion: number;\n /** @internal */\n _lastVis: number;\n /** @internal True once `record()` has run — the task is \"live\" (GPU target allocated, material batch builders\n * present). A runtime `addMesh` after this resolves + re-buckets THIS task immediately (no frame-graph rebuild). */\n _recorded: boolean;\n\n /** @internal */\n _renderPassDescriptor: GPURenderPassDescriptor;\n /** @internal */\n _colorAttachment: GPURenderPassColorAttachment;\n /** @internal External depth source from `config.depth`. When unset,\n * the pass uses `config.rt._depthView`. */\n _depthSrc?: RenderTarget;\n /** @internal External depth/stencil `loadOp` (\"load\" when `config.depth` is\n * set). When unset, defaults to `\"clear\"`. */\n _depthLoadOp?: GPULoadOp;\n\n /** Per-task scene UBO + bind group. Created eagerly in createRenderTask\n * so renderables can reference `_sceneBG` at `bind()` time. Written each\n * frame by `_writePassSceneUBO`. Destroyed in `dispose()`. */\n /** @internal */\n _sceneUBO: GPUBuffer;\n /** @internal */\n _sceneBG: GPUBindGroup;\n /** @internal */\n _lightsUBO: GPUBuffer;\n /** @internal */\n _suData: Float32Array;\n /** @internal */\n _su: unknown[];\n /** Optional transmission-enabled execute path: copies the scene texture for refraction and draws transmissive\n * renderables. Present only when the task was configured with `transmission`. Returns the number of draw calls issued. */\n /** @internal */\n _executeWithTransmission?(sampleCount: number): number;\n /** @internal */\n _targetSignature: RenderTargetSignature;\n /** @internal Lazy feature work flushed after binding updates and before the render pass. */\n _updateBatches: DrawUpdateBatch[];\n\n /** Add a mesh to this task's explicit render list with an optional per-pass material override. Resolved via\n * `material._buildGroup._rebuildSingle`, so the mesh's material family must already have been registered with the\n * scene (its batch builder has run). BEFORE the first `record()` the add is QUEUED and drained at record() time;\n * AFTER (a live/runtime add) it is resolved + re-bucketed into THIS task immediately, so the mesh renders on the\n * next frame without a `frameGraph.build()` (which would re-allocate shared GPU resources across all tasks). */\n addMesh(mesh: Mesh, opts?: { material?: Material }): void;\n /** @internal */\n _pendingMeshes: { mesh: Mesh; material: Material }[];\n}\n\ninterface MutableDrawUpdateContext {\n targetWidth: number;\n targetHeight: number;\n _camera?: Camera | null;\n}\n\n/** Create a render pass task. GPU resources (target textures + descriptor)\n * are not allocated until `record()` runs (via `frameGraph.build()`).\n *\n * Swapchain-targeted tasks acquire the swap view per-frame at execute time. */\nexport function createRenderTask(config: RenderTaskConfig, engine: EngineContext, scene: SceneContext): RenderTask {\n const sc = scene as SceneContext;\n config.clrColor ??= { r: 0.2, g: 0.2, b: 0.3, a: 1.0 };\n config.clr ??= true;\n const desc = config.rt._descriptor;\n // Render upright: row 0 of the GPU texture is the top of the scene. Every\n // RT (offscreen or swapchain) renders without a projection Y-flip; pipelines\n // use the default ccw front face; downstream samplers see upright pixels.\n const targetSignature = {\n _colorFormat: desc.format,\n _depthStencilFormat: config.depth?._descriptor.dFormat ?? desc.dFormat,\n _depthCompare: desc._depthCompare,\n _sampleCount: desc.samples ?? 1,\n };\n\n const sceneBGL = getSceneBindGroupLayout(engine);\n const sceneUBO = createEmptyUniformBuffer(engine, SCENE_UBO_BYTES);\n const lightsUBO = ensureSceneLightState(engine, sc)._buffer;\n const sceneBG = engine._device.createBindGroup({\n layout: sceneBGL,\n entries: [\n { binding: 0, resource: { buffer: sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const updateContext: MutableDrawUpdateContext = { targetWidth: 0, targetHeight: 0 };\n const task: RenderTask = {\n name: config.name,\n _config: config,\n engine: engine,\n scene: sc,\n _passes: [],\n _autoFromScene: false,\n _renderables: [],\n _opaqueBindings: [],\n _directBindings: [],\n _transparentBindings: [],\n _opaqueBundles: [],\n _lastVersion: -1,\n _lastVis: 0,\n _recorded: false,\n _renderPassDescriptor: { colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _depthSrc: config.depth,\n _depthLoadOp: config.depth ? (config.depth._eager ? \"load\" : \"clear\") : undefined,\n _sceneUBO: sceneUBO,\n _sceneBG: sceneBG,\n _lightsUBO: lightsUBO,\n _suData: new F32(SCENE_UBO_BYTES / 4),\n _su: [],\n _targetSignature: targetSignature,\n _updateBatches: [],\n _pendingMeshes: [],\n addMesh(mesh, opts) {\n const material = opts?.material ?? mesh.material;\n if (!material) {\n return;\n }\n task._pendingMeshes.push({ mesh, material });\n if (task._recorded) {\n // Live (post-record) add: resolve + re-bucket THIS task now — buildBindings clears its bundle cache\n // so it re-records on the next execute. Deliberately NOT a frame-graph rebuild (that re-allocates the\n // shared scene UBO + every task's render target mid-frame and crashes the in-flight submit).\n resolvePendingMeshes(task, sc);\n // A live add makes the render list explicit (mirrors record(), where a pending mesh forces\n // _autoFromScene = false). Without this, an auto-mirroring task's next scene-version resync in\n // prepareRenderTaskPass would clear _renderables and drop the just-added mesh.\n task._autoFromScene = false;\n buildBindings(task, engine, targetSignature);\n }\n },\n record(): void {\n if (task._autoFromScene) {\n task._renderables.length = 0;\n }\n resolvePendingMeshes(task, sc);\n task._autoFromScene = task._renderables.length === 0;\n if (task._autoFromScene) {\n task._renderables.push(...sc._renderables);\n }\n // Read config.rt dynamically — transmission retargeting swaps it after\n // the task is created, and the engine scRT must never be rebuilt.\n const rt = config.rt;\n buildRenderTarget(rt, engine);\n if (config.rst && (rt._descriptor.samples ?? 1) > 1) {\n buildRenderTarget(config.rst, engine);\n }\n // A non-eager external depth (e.g. the default single-sample scene task's\n // depth, whose colour rt is the depth-less scRT) is task-managed:\n // build/rebuild it here. Eager depths (GeometryRendererTask outputs) are\n // pre-built and skipped by buildRenderTarget.\n if (config.depth && !config.depth._eager) {\n buildRenderTarget(config.depth, engine);\n }\n updateContext.targetWidth = rt._width;\n updateContext.targetHeight = rt._height;\n refreshTaskSceneBindGroup(task, engine);\n buildBindings(task, engine, targetSignature);\n buildRenderPassDescriptor(task, rt);\n task._recorded = true; // task is now live — a subsequent addMesh resolves + re-buckets immediately\n },\n execute(): number {\n return executePass(task, engine, targetSignature, updateContext);\n },\n dispose(): void {\n task._passes.length = 0;\n // disposeRenderTarget no-ops on the engine scRT and on eager\n // GeometryRendererTask depth outputs (both `_eager`), and on an undefined\n // rst/depth — so these can be passed unconditionally.\n disposeRenderTarget(config.rt);\n disposeRenderTarget(config.rst);\n disposeRenderTarget(config.depth);\n task._opaqueBindings.length = 0;\n task._directBindings.length = 0;\n task._transparentBindings.length = 0;\n task._renderables.length = 0;\n task._opaqueBundles.length = 0;\n task._sceneUBO.destroy();\n for (const batch of task._updateBatches) {\n batch.destroy();\n }\n task._updateBatches.length = 0;\n },\n };\n return task;\n}\n\n/** Remove a mesh from this task's renderable + binding lists. Idempotent. */\nexport function removeMeshFromTask(task: RenderTask, mesh: object): void {\n // Not a renderable-bearing task (e.g. a post/effect task that also carries `_config`): nothing to\n // remove. Guard keeps callers that scan all frame-graph tasks (removeFromScene) shape-safe.\n if (!task._renderables) {\n return;\n }\n let removed = false;\n for (let i = task._pendingMeshes.length - 1; i >= 0; i--) {\n if (task._pendingMeshes[i]!.mesh === mesh) {\n task._pendingMeshes.splice(i, 1);\n removed = true;\n }\n }\n for (let i = task._renderables.length - 1; i >= 0; i--) {\n if (task._renderables[i]!.mesh === mesh) {\n task._renderables.splice(i, 1);\n removed = true;\n }\n }\n for (const arr of [task._opaqueBindings, task._directBindings, task._transparentBindings]) {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (arr[i]!.renderable.mesh === mesh) {\n arr.splice(i, 1);\n removed = true;\n }\n }\n }\n if (removed) {\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction resolvePendingMeshes(task: RenderTask, sc: SceneContext): void {\n if (task._pendingMeshes.length === 0) {\n return;\n }\n for (const { mesh, material } of task._pendingMeshes) {\n const rebuild = material._buildGroup?._rebuildSingle;\n if (!rebuild) {\n throw new Error();\n }\n const renderable = rebuild(sc, mesh, material);\n if (!task._renderables.includes(renderable)) {\n task._renderables.push(renderable);\n }\n }\n task._pendingMeshes.length = 0;\n}\n\n/** Per-frame back-to-front sort for transparent bindings using the active camera. */\nfunction sortTransparentBindings(task: RenderTask, camera: Camera | null | undefined): void {\n const arr = task._transparentBindings;\n if (arr.length <= 1 || !camera) {\n return;\n }\n const v = getViewMatrix(camera);\n for (const b of arr) {\n const wc = b.renderable._worldCenter;\n b._sortDistance = wc ? wc[0]! * v[2]! + wc[1]! * v[6]! + wc[2]! * v[10]! + v[14]! : 0;\n }\n arr.sort((a, b) => b._sortDistance! - a._sortDistance! || a.renderable.order - b.renderable.order);\n}\n\n/** (Re)bucket task._renderables into bound lists. */\nfunction buildBindings(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature): void {\n const opaque = task._opaqueBindings;\n const direct = task._directBindings;\n const transparent = task._transparentBindings;\n opaque.length = 0;\n direct.length = 0;\n transparent.length = 0;\n for (const r of task._renderables) {\n const binding = r.bind(eng, targetSignature);\n for (const batch of binding._updateBatches ?? []) {\n if (!task._updateBatches.includes(batch)) {\n task._updateBatches.push(batch);\n }\n }\n if (r.isTransparent || r._transmissive) {\n transparent.push(binding);\n } else if (r._direct) {\n direct.push(binding);\n } else {\n opaque.push(binding);\n }\n }\n opaque.sort((a, b) => a.renderable.order - b.renderable.order);\n direct.sort((a, b) => a.renderable.order - b.renderable.order);\n task._opaqueBundles.length = 0;\n task._lastVersion = (task.scene as SceneContext)._renderableVersion;\n}\n\nfunction buildRenderPassDescriptor(task: RenderTask, rt: RenderTarget): void {\n const att = task._colorAttachment;\n att.view = rt._colorView!;\n // End-of-pass MSAA resolve into a caller-supplied single-sample target.\n // record() only builds the target's color view for an MSAA rt, so its\n // presence is the gate. The swapchain case is wired per-frame in\n // executePass (its view changes each frame); this custom view is stable.\n att.resolveTarget = task._config.rst?._colorView ?? undefined;\n task._renderPassDescriptor.colorAttachments = rt._colorView ? [att] : [];\n\n const depthSrc = task._depthSrc ?? rt;\n const depthView = depthSrc._depthView;\n let depthAttachment: GPURenderPassDepthStencilAttachment | undefined;\n if (depthView) {\n const dd = depthSrc._descriptor;\n const loadOp = task._depthLoadOp ?? \"clear\";\n depthAttachment = {\n view: depthView,\n depthClearValue: dd._depthClearValue ?? 0,\n depthLoadOp: loadOp,\n depthStoreOp: \"store\",\n };\n if (dd.dFormat?.includes(\"stencil\")) {\n depthAttachment.stencilClearValue = 0;\n depthAttachment.stencilLoadOp = loadOp;\n depthAttachment.stencilStoreOp = \"store\";\n }\n }\n\n task._renderPassDescriptor.depthStencilAttachment = depthAttachment;\n}\n\nfunction prepareRenderTaskPass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): void {\n const sc = task.scene as SceneContext;\n // Auto-resync when the source scene mutates.\n if (task._autoFromScene && task._lastVersion !== sc._renderableVersion) {\n task._renderables.length = 0;\n task._renderables.push(...sc._renderables);\n buildBindings(task, eng, targetSignature);\n }\n\n // Pre-pass work — runs before beginRenderPass. Updates the task-owned scene\n // UBO, scene-wide lights UBO, and per-binding UBOs. The scene bind group may\n // also need a refresh (lights buffer can be resized when glTF lights\n // extension raises MAX_LIGHTS after this task was first recorded).\n refreshTaskSceneBindGroup(task, eng);\n const camera = task._config.cam ?? sc.camera;\n if (!task._config._skipClusteredLights && targetSignature._colorFormat) {\n sc._clusteredLightUpdater?.(camera, context.targetWidth, context.targetHeight);\n }\n _writePassSceneUBO(task, eng, sc, camera);\n refreshSceneLightsUBO(eng, sc);\n // Expose the active camera to per-binding `update()` calls. Some renderables\n // (e.g. transparent billboard systems) need it to compute view-space sort\n // depths during their update.\n (context as MutableDrawUpdateContext)._camera = camera;\n for (const batch of task._updateBatches) {\n batch.reset();\n }\n updateBindings(task._opaqueBindings, context);\n updateBindings(task._directBindings, context);\n updateBindings(task._transparentBindings, context);\n for (const batch of task._updateBatches) {\n batch.flush(eng);\n }\n // Per-frame back-to-front sort for transparent bindings — must run AFTER\n // updateBindings so renderables that compute `_worldCenter` inside their\n // own `update()` (billboard systems) are seen with current values.\n sortTransparentBindings(task, camera);\n}\n\nfunction executePass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): number {\n const sc = task.scene;\n const sampleCount = targetSignature._sampleCount;\n prepareRenderTaskPass(task, eng, targetSignature, context);\n const att = task._colorAttachment;\n const cfg = task._config;\n if (cfg.rt._colorView) {\n // The engine scRT's color view is re-acquired every frame, so re-read\n // it here. Offscreen color views are stable between rebuilds — leaving att.view\n // untouched preserves an external override (swapchain-overlay shares the base\n // scene's MSAA color view). The resolve target (rst) is re-read each frame so an\n // `rst === scRT` picks up its fresh per-frame view.\n if (cfg.rt === eng.scRT) {\n att.view = cfg.rt._colorView;\n }\n att.resolveTarget = cfg.rst?._colorView ?? undefined;\n att.clearValue = task._autoFromScene ? sc.clearColor : cfg.clrColor!;\n att.loadOp = cfg.clr ? \"clear\" : \"load\";\n }\n if (task._executeWithTransmission) {\n return task._executeWithTransmission(sampleCount);\n }\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n const draws = executePassBody(task, pass);\n pass.end();\n return draws;\n}\n\n/** Body of the registered `RenderPass`. Receives the live render-pass encoder\n * and issues all draws (viewport/scissor, group(0) bind, opaque bundle replay,\n * then direct-draws non-transparent direct + transparent). Returns the draw count. */\nfunction executePassBody(task: RenderTask, pass: GPURenderPassEncoder): number {\n const eng = task.engine as EngineContext;\n const cfg = task._config;\n const rt = cfg.rt;\n const scene = task.scene as SceneContext;\n const opaqueBindings = task._opaqueBindings;\n const opaqueBundles = task._opaqueBundles;\n const sceneBG = task._sceneBG;\n\n const camera = cfg.cam ?? scene.camera;\n const v = camera?.viewport;\n if (v) {\n const rw = rt._width;\n const rh = rt._height;\n const x = Math.floor(v.x * rw);\n const y = Math.floor((1 - v.y - v.height) * rh);\n const w = Math.ceil((v.x + v.width) * rw) - x;\n const h = Math.ceil((1 - v.y) * rh) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n }\n // Scene bind group (group 0) is task-owned and identical for every draw in this pass.\n pass.setBindGroup(0, sceneBG);\n\n // Opaque: cached render bundle. Invalidated by scene mutation (_renderableVersion) or\n // the global visibility/resource epoch (_vis). The bundle records group(0) at its start.\n if (task._lastVersion !== scene._renderableVersion || task._lastVis !== _vis || opaqueBundles.length === 0) {\n const desc = rt._descriptor;\n const be = eng._device.createRenderBundleEncoder({\n colorFormats: desc.format ? [desc.format] : [],\n // Use the task's target signature, not the RT descriptor: a depth\n // override (config.depth) supplies the depth format externally, so\n // the cached opaque pipelines are built with it while the colour RT\n // carries no depthStencilFormat of its own. The bundle encoder's\n // attachment state must match those pipelines exactly.\n depthStencilFormat: task._targetSignature._depthStencilFormat,\n sampleCount: desc.samples ?? 1,\n });\n be.setBindGroup(0, sceneBG);\n drawList(be, opaqueBindings, eng);\n opaqueBundles[0] = be.finish();\n task._lastVersion = scene._renderableVersion;\n task._lastVis = _vis;\n }\n let draws = opaqueBindings.length;\n pass.executeBundles(opaqueBundles);\n // executeBundles invalidates pass bind-group state — rebind group 0 before further draws.\n pass.setBindGroup(0, sceneBG);\n draws += drawList(pass, task._directBindings, eng);\n draws += drawList(pass, task._transparentBindings, eng);\n return draws;\n}\n\nfunction refreshTaskSceneBindGroup(task: RenderTask, eng: EngineContext): void {\n const lightsUBO = ensureSceneLightState(eng, task.scene as SceneContext)._buffer;\n if (lightsUBO === task._lightsUBO) {\n return;\n }\n task._lightsUBO = lightsUBO;\n task._sceneBG = eng._device.createBindGroup({\n layout: getSceneBindGroupLayout(eng),\n entries: [\n { binding: 0, resource: { buffer: task._sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n}\n\n/** Write the canonical SceneUniforms struct to the task-owned scene UBO.\n * Bails before touching scratch/GPU when all inputs are unchanged.\n * @internal Exported for unit testing of the scene-UBO change-detection guard. */\nexport function _writePassSceneUBO(task: RenderTask, eng: EngineContext, scene: SceneContext, camera: Camera | null): void {\n if (!camera) {\n return;\n }\n\n const v = camera.viewport;\n const rt = task._config.rt;\n const aspect = (task._config.cs ? eng.canvas.width / eng.canvas.height : rt._width / rt._height) * (v ? v.width / v.height : 1);\n const fog = scene.fog;\n const img = scene.imageProcessing;\n const envRotationY = scene.envRotationY || 0;\n const wv = camera.worldMatrixVersion;\n // `envTextures` identity is tracked so an environment loaded (or swapped) AFTER the scene has reached\n // steady state invalidates this cache. Its spherical-harmonics irradiance and `lodGenerationScale` are\n // written into the scene UBO below (via `_packSceneUniforms` + the env-SH contributor); without tracking\n // it, a late env load would change none of the other guarded inputs, so the UBO would never be rewritten\n // and the model would keep zero irradiance (dark diffuse, specular-only \"mirror\" look).\n const envTextures = scene._envTextures;\n const s = task._su;\n if (s[0] === camera && s[1] === fog && s[2] === wv && s[3] === aspect && s[4] === envRotationY && s[5] === img.exposure && s[6] === img.contrast && s[7] === envTextures) {\n return;\n }\n s[0] = camera;\n s[1] = fog;\n s[2] = wv;\n s[3] = aspect;\n s[4] = envRotationY;\n s[5] = img.exposure;\n s[6] = img.contrast;\n s[7] = envTextures;\n\n const data = task._suData;\n _packSceneUniforms(data, eng, scene, camera, aspect);\n const contribs = scene._sceneUboContributors;\n if (contribs) {\n for (const c of contribs) {\n c(data, scene);\n }\n }\n eng._device.queue.writeBuffer(task._sceneUBO, 0, data as Float32Array<ArrayBuffer>);\n}\n\nfunction updateBindings(list: readonly DrawBinding[], context: DrawUpdateContext): void {\n for (const b of list) {\n b.update?.(context);\n }\n}\n\n/** @internal Iterate DrawBindings, deduping setPipeline. */\nexport function drawList(enc: GPURenderPassEncoder | GPURenderBundleEncoder, list: readonly DrawBinding[], engine: EngineContext): number {\n let lp: GPURenderPipeline | null = null;\n let draws = 0;\n for (const b of list) {\n const mesh = b.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (b.pipeline !== lp) {\n enc.setPipeline(b.pipeline);\n lp = b.pipeline;\n }\n draws += b.draw(enc, engine);\n }\n return draws;\n}\n"],"names":[],"mappings":"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"}
|