@forgeax/engine-render 0.1.21 → 0.1.23
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/README.md +150 -29
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +14 -6
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +10 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
- package/dist/chunk-4L3P6DT5.mjs.map +1 -0
- package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
- package/dist/chunk-4NPUASZR.mjs.map +1 -0
- package/dist/chunk-DIYW3M5D.mjs +5085 -0
- package/dist/chunk-DIYW3M5D.mjs.map +1 -0
- package/dist/chunk-FBC4R44J.mjs +1003 -0
- package/dist/chunk-FBC4R44J.mjs.map +1 -0
- package/dist/{chunk-FS2KNUQH.mjs → chunk-FF7K3FSO.mjs} +253 -489
- package/dist/chunk-FF7K3FSO.mjs.map +1 -0
- package/dist/chunk-HZUPSYW7.mjs +1104 -0
- package/dist/chunk-HZUPSYW7.mjs.map +1 -0
- package/dist/{chunk-6OPXDQ2E.mjs → chunk-QODA5UKU.mjs} +33 -294
- package/dist/chunk-QODA5UKU.mjs.map +1 -0
- package/dist/chunk-YALPS44A.mjs +296 -0
- package/dist/chunk-YALPS44A.mjs.map +1 -0
- package/dist/{chunk-5YADUCA7.mjs → chunk-ZUWKAZ2I.mjs} +585 -991
- package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +4 -0
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/light-probe.d.ts +9 -0
- package/dist/components/light-probe.d.ts.map +1 -0
- package/dist/components/rect-area-light.d.ts +12 -0
- package/dist/components/rect-area-light.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +4 -0
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/spot-light.d.ts +3 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +10437 -10044
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +8 -1
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/lifecycle-transaction.d.ts +2 -0
- package/dist/device/lifecycle-transaction.d.ts.map +1 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/gpu-driven.d.ts +26 -0
- package/dist/errors/gpu-driven.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +9 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +26 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -0
- package/dist/extract/gpu-driven.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +63 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +98 -2
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +64 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +14 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +8 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +0 -1
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -3
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +90 -5
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +163 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/internal.d.ts +9 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +23 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/light-buffer-layout.d.ts +58 -149
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +26 -12
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/resources.d.ts +72 -0
- package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/state.d.ts +24 -0
- package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +8 -6
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +50 -10
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +7 -3
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-timing.d.ts +19 -7
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +0 -20
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +3 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +57 -6
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +49 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +1 -2
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/inspection.d.ts +10 -0
- package/dist/reflection/inspection.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +49 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts +60 -0
- package/dist/reflection/record-owner.d.ts.map +1 -0
- package/dist/render-contract.d.ts +14 -8
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +7 -0
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +104 -16
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +12 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend-record.d.ts +22 -0
- package/dist/scene/probe-blend-record.d.ts.map +1 -0
- package/dist/scene/probe-blend.d.ts +142 -0
- package/dist/scene/probe-blend.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +0 -6
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +103 -9
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/visibility/bounds.d.ts +20 -0
- package/dist/scene/visibility/bounds.d.ts.map +1 -0
- package/dist/scene/visibility/budget.d.ts +16 -0
- package/dist/scene/visibility/budget.d.ts.map +1 -0
- package/dist/scene/visibility/facet.d.ts +73 -0
- package/dist/scene/visibility/facet.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-lod.d.ts +46 -0
- package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
- package/dist/scene/visibility/inspection.d.ts +132 -0
- package/dist/scene/visibility/inspection.d.ts.map +1 -0
- package/dist/scene/visibility/lod-selector.d.ts +25 -0
- package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
- package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
- package/dist/scene/visibility/types.d.ts +34 -0
- package/dist/scene/visibility/types.d.ts.map +1 -0
- package/dist/ssr/admission.d.ts +122 -0
- package/dist/ssr/admission.d.ts.map +1 -0
- package/dist/ssr/composition.d.ts +32 -0
- package/dist/ssr/composition.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +39 -0
- package/dist/ssr/errors.d.ts.map +1 -0
- package/dist/ssr/identity.d.ts +13 -0
- package/dist/ssr/identity.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +1 -1
- package/dist/temporal/frame-coordinator.d.ts +13 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +2 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -5
- package/dist/temporal/view.d.ts +7 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts +4 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +8 -4
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +13 -1
- package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
- package/src/__tests__/environment-generation.integration.test.ts +16 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
- package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
- package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
- package/src/__tests__/factory-contract.integration.test.ts +33 -0
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
- package/src/__tests__/gpu-lod-evidence.ts +188 -0
- package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
- package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
- package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
- package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
- package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
- package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
- package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
- package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
- package/src/__tests__/gpu-scene.unit.test.ts +49 -3
- package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
- package/src/__tests__/light-inspection.unit.test.ts +55 -0
- package/src/__tests__/light-resource-error.unit.test.ts +43 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
- package/src/__tests__/lod-bounds.unit.test.ts +42 -0
- package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
- package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
- package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
- package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
- package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
- package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
- package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
- package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
- package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
- package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
- package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
- package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
- package/src/__tests__/lod-selector.profile.test.ts +35 -0
- package/src/__tests__/lod-selector.unit.test.ts +68 -0
- package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
- package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
- package/src/__tests__/ltc-resources.unit.test.ts +32 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
- package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
- package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
- package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
- package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
- package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
- package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
- package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
- package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
- package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
- package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
- package/src/__tests__/occlusion-query.evidence.ts +178 -0
- package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
- package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/probe-bindings.unit.test.ts +200 -0
- package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
- package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
- package/src/__tests__/probe-capacity.integration.test.ts +97 -0
- package/src/__tests__/probe-recovery.integration.test.ts +104 -0
- package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
- package/src/__tests__/profiler-phase-token.test.ts +1 -0
- package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
- package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
- package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
- package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
- package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
- package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
- package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
- package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
- package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
- package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
- package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
- package/src/__tests__/ssr-composition.unit.test.ts +46 -0
- package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
- package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
- package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
- package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
- package/src/__tests__/temporal-view.unit.test.ts +3 -3
- package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
- package/src/__tests__/visibility-budget.integration.test.ts +140 -0
- package/src/__tests__/visibility-budget.unit.test.ts +70 -0
- package/src/__tests__/visibility-extract.integration.test.ts +11 -6
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +16 -9
- package/src/assembly/factory.ts +547 -93
- package/src/assembly/host-contract.ts +10 -0
- package/src/cluster-binner.ts +31 -0
- package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
- package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
- package/src/components/index.ts +3 -0
- package/src/components/light-helpers.ts +52 -1
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/gpu-residency.ts +140 -9
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/lifecycle.ts +8 -1
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +32 -0
- package/src/errors/render.ts +55 -1
- package/src/extract/camera.ts +3 -3
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +0 -23
- package/src/gpu-driven/batch-topology.ts +206 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +953 -41
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +134 -65
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +6 -6
- package/src/index.ts +74 -0
- package/src/inspection-types.ts +220 -1
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +154 -324
- package/src/materials.ts +16 -2
- package/src/pbr-pipeline.ts +151 -45
- package/src/pipeline/standard-forward-lane.ts +47 -0
- package/src/pipeline/standard-lighting/graph.ts +2 -1
- package/src/pipeline/standard-lighting/light-frame.ts +3 -2
- package/src/pipeline/standard-lighting/topology.ts +1 -1
- package/src/pipeline/standard-lighting/transport.ts +2 -1
- package/src/pipeline/standard-pipeline.ts +2 -0
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +12 -1
- package/src/plugin.ts +4 -0
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
- package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
- package/src/prepare/extended-lighting/resources.ts +389 -0
- package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
- package/src/prepare/extended-lighting/state.ts +92 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +23 -1
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/frame-lighting.ts +252 -53
- package/src/record/frame-snapshot.ts +57 -12
- package/src/record/frame.ts +410 -93
- package/src/record/gpu-timing.ts +108 -44
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +204 -39
- package/src/record/main-pass-material.ts +8 -1
- package/src/record/main-pass-sprite-draws.ts +52 -85
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +65 -4
- package/src/record/shadow-pass.ts +66 -40
- package/src/record/typed-frame-graph.ts +225 -83
- package/src/record/view-ubo.ts +14 -24
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +196 -1
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +17 -5
- package/src/render-pipeline.ts +5 -0
- package/src/render-system-extract.ts +493 -134
- package/src/render-system.ts +811 -615
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
- package/src/scene/probe-blend-record.ts +54 -0
- package/src/scene/probe-blend.ts +813 -0
- package/src/scene/render-scene-types.ts +0 -7
- package/src/scene/render-scene.ts +848 -183
- package/src/scene/visibility/bounds.ts +57 -0
- package/src/scene/visibility/budget.ts +40 -0
- package/src/scene/visibility/facet.ts +400 -0
- package/src/scene/visibility/gpu-frame-timing.ts +101 -0
- package/src/scene/visibility/gpu-lod.ts +119 -0
- package/src/scene/visibility/inspection.ts +313 -0
- package/src/scene/visibility/lod-selector.ts +84 -0
- package/src/scene/visibility/occlusion-confidence.ts +478 -0
- package/src/scene/visibility/occlusion-pass.ts +165 -0
- package/src/scene/visibility/occlusion-query-pool.ts +178 -0
- package/src/scene/visibility/occlusion-runtime.ts +672 -0
- package/src/scene/visibility/types.ts +50 -0
- package/src/ssr/admission.ts +451 -0
- package/src/ssr/composition.ts +73 -0
- package/src/ssr/errors.ts +76 -0
- package/src/ssr/identity.ts +12 -0
- package/src/systems/skin-palette-allocator.ts +1 -1
- package/src/temporal/frame-coordinator.ts +26 -0
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +4 -4
- package/src/typed-render-graph-primitives.ts +48 -0
- package/src/volume/passes.ts +46 -49
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-5YADUCA7.mjs.map +0 -1
- package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
- package/dist/chunk-BXBQQKFQ.mjs +0 -67
- package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
- package/dist/chunk-FS2KNUQH.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
getOrCreateHdrpBuffers,
|
|
26
26
|
packClusterUniform,
|
|
27
27
|
} from '../hdrp-buffers';
|
|
28
|
-
import {
|
|
28
|
+
import { DIRECT_LIGHT_SLOT_FLOAT_COUNT, packDirectLightSlot } from '../light-buffer-layout';
|
|
29
29
|
import {
|
|
30
30
|
type PreparedStandardLighting,
|
|
31
31
|
prepareStandardLighting,
|
|
@@ -36,6 +36,12 @@ import {
|
|
|
36
36
|
selectStandardClusterTransport,
|
|
37
37
|
} from '../pipeline/standard-lighting/transport';
|
|
38
38
|
import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE } from '../pipeline/standard-profile';
|
|
39
|
+
import {
|
|
40
|
+
COOKIE_MATRIX_BYTES,
|
|
41
|
+
COOKIE_SLICE_SIZE,
|
|
42
|
+
IES_SLICE_HEIGHT,
|
|
43
|
+
IES_SLICE_WIDTH,
|
|
44
|
+
} from '../prepare/extended-lighting/resources';
|
|
39
45
|
import type { ReflectionProbeTable } from '../reflection/gpu-table';
|
|
40
46
|
import type { ReflectionProbeSelectionResult } from '../reflection/projection';
|
|
41
47
|
import type { CameraSnapshot, RenderHdrpClusterPhase } from '../render-contract';
|
|
@@ -53,6 +59,8 @@ import {
|
|
|
53
59
|
} from '../shadow-atlas';
|
|
54
60
|
import { getOrCreateSsaoBuffers } from '../ssao-buffers';
|
|
55
61
|
import { getSsaoParameters } from '../ssao-config';
|
|
62
|
+
// extendedLighting keeps Spot modifier factors on the existing light record
|
|
63
|
+
// path; no additional render pass or submit owner is introduced.
|
|
56
64
|
import type { BindGroupCounts, RenderFrameState } from './frame-snapshot';
|
|
57
65
|
import {
|
|
58
66
|
computeProjectionMatrix,
|
|
@@ -155,10 +163,10 @@ export function buildPerFrameBindGroups(
|
|
|
155
163
|
hdrpClusterBindGroup: BindGroup | null;
|
|
156
164
|
hdrpClusterMembershipBindGroup: BindGroup | null;
|
|
157
165
|
} {
|
|
158
|
-
// View main (#1) chain = b0(viewUniformBuffer),
|
|
159
|
-
// b2(spotLightsBuffer), b3(graph shadowDepth view or
|
|
166
|
+
// View main (#1) chain = b0(viewUniformBuffer), b3(graph shadowDepth view or
|
|
160
167
|
// shadowFallbackTextureView), b4(shadowSampler), b5(atlas view), b6
|
|
161
|
-
// (shadowParams); variant 'view-main'.
|
|
168
|
+
// (shadowParams); variant 'view-main'. Local lights are never mirrored in
|
|
169
|
+
// the view group: Standard consumes the one Cluster group(2) payload.
|
|
162
170
|
// Mesh (#2) chain = inner b0 buffer (meshStorageBuffer.buffer); variant 'mesh'.
|
|
163
171
|
let viewBindGroup: BindGroup | null = null;
|
|
164
172
|
let meshBindGroup: BindGroup | null = null;
|
|
@@ -229,6 +237,47 @@ export function buildPerFrameBindGroups(
|
|
|
229
237
|
graphSpotShadowView !== undefined
|
|
230
238
|
? graphSpotShadowView
|
|
231
239
|
: pipelineState.shadowFallbackTextureView;
|
|
240
|
+
const extendedLighting = pipelineState.extendedLightingAvailable ?? true;
|
|
241
|
+
const iesProfileTextureView = pipelineState.iesProfileTextureView;
|
|
242
|
+
const cookieTextureView = pipelineState.cookieTextureView;
|
|
243
|
+
const cookieMatrixBuffer = pipelineState.cookieMatrixBuffer;
|
|
244
|
+
const ltcLambertTextureView = pipelineState.ltcLambertTextureView;
|
|
245
|
+
const ltcGgxTextureView = pipelineState.ltcGgxTextureView;
|
|
246
|
+
const extendedLightingResources =
|
|
247
|
+
extendedLighting &&
|
|
248
|
+
iesProfileTextureView !== undefined &&
|
|
249
|
+
cookieTextureView !== undefined &&
|
|
250
|
+
cookieMatrixBuffer !== undefined &&
|
|
251
|
+
ltcLambertTextureView !== undefined &&
|
|
252
|
+
ltcGgxTextureView !== undefined
|
|
253
|
+
? {
|
|
254
|
+
sampler: pipelineState.defaultSampler,
|
|
255
|
+
iesProfileTextureView,
|
|
256
|
+
cookieTextureView,
|
|
257
|
+
ltcLambertTextureView,
|
|
258
|
+
ltcGgxTextureView,
|
|
259
|
+
cookieMatrixBuffer,
|
|
260
|
+
}
|
|
261
|
+
: undefined;
|
|
262
|
+
if (extendedLighting && extendedLightingResources === undefined) {
|
|
263
|
+
return {
|
|
264
|
+
viewBindGroup: null,
|
|
265
|
+
meshBindGroup: null,
|
|
266
|
+
hdrpClusterBindGroup: null,
|
|
267
|
+
hdrpClusterMembershipBindGroup,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const extendedLightingViews =
|
|
271
|
+
extendedLightingResources !== undefined
|
|
272
|
+
? [
|
|
273
|
+
extendedLightingResources.sampler,
|
|
274
|
+
extendedLightingResources.iesProfileTextureView,
|
|
275
|
+
extendedLightingResources.cookieTextureView,
|
|
276
|
+
extendedLightingResources.ltcLambertTextureView,
|
|
277
|
+
extendedLightingResources.ltcGgxTextureView,
|
|
278
|
+
extendedLightingResources.cookieMatrixBuffer,
|
|
279
|
+
]
|
|
280
|
+
: [];
|
|
232
281
|
const projectorAvailable = pipelineState.projectorAvailable !== false;
|
|
233
282
|
const b11View = graphTargets?.projector ?? pipelineState.defaultWhiteTextureView;
|
|
234
283
|
const b12Sampler = graphTargets?.projectorSampler ?? pipelineState.defaultSampler;
|
|
@@ -236,14 +285,15 @@ export function buildPerFrameBindGroups(
|
|
|
236
285
|
frameState.viewBindGroupCache,
|
|
237
286
|
[
|
|
238
287
|
pipelineState.viewUniformBuffer,
|
|
239
|
-
pipelineState.pointLightsBuffer,
|
|
240
|
-
pipelineState.spotLightsBuffer,
|
|
241
288
|
b3View,
|
|
242
289
|
shadowSampler,
|
|
243
290
|
b5View,
|
|
244
291
|
pipelineState.shadowParamsBuffer,
|
|
245
292
|
b8View,
|
|
246
|
-
...
|
|
293
|
+
...extendedLightingViews,
|
|
294
|
+
...(extendedLightingResources === undefined && projectorAvailable
|
|
295
|
+
? [b11View, b12Sampler]
|
|
296
|
+
: []),
|
|
247
297
|
pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
|
|
248
298
|
],
|
|
249
299
|
'view-main',
|
|
@@ -256,20 +306,6 @@ export function buildPerFrameBindGroups(
|
|
|
256
306
|
value: { buffer: pipelineState.viewUniformBuffer, size: VIEW_UNIFORM_BYTES },
|
|
257
307
|
},
|
|
258
308
|
},
|
|
259
|
-
{
|
|
260
|
-
binding: 1,
|
|
261
|
-
resource: {
|
|
262
|
-
kind: 'buffer',
|
|
263
|
-
value: { buffer: pipelineState.pointLightsBuffer },
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
binding: 2,
|
|
268
|
-
resource: {
|
|
269
|
-
kind: 'buffer',
|
|
270
|
-
value: { buffer: pipelineState.spotLightsBuffer },
|
|
271
|
-
},
|
|
272
|
-
},
|
|
273
309
|
{
|
|
274
310
|
binding: 3,
|
|
275
311
|
resource: {
|
|
@@ -339,12 +375,61 @@ export function buildPerFrameBindGroups(
|
|
|
339
375
|
},
|
|
340
376
|
},
|
|
341
377
|
},
|
|
342
|
-
...(projectorAvailable
|
|
378
|
+
...(extendedLightingResources === undefined && projectorAvailable
|
|
343
379
|
? [
|
|
344
380
|
{ binding: 11, resource: { kind: 'textureView' as const, value: b11View } },
|
|
345
381
|
{ binding: 12, resource: { kind: 'sampler' as const, value: b12Sampler } },
|
|
346
382
|
]
|
|
347
383
|
: []),
|
|
384
|
+
...(extendedLightingResources !== undefined
|
|
385
|
+
? [
|
|
386
|
+
{
|
|
387
|
+
binding: 9,
|
|
388
|
+
resource: {
|
|
389
|
+
kind: 'sampler' as const,
|
|
390
|
+
value: extendedLightingResources.sampler,
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
binding: 11,
|
|
395
|
+
resource: {
|
|
396
|
+
kind: 'textureView' as const,
|
|
397
|
+
value: extendedLightingResources.iesProfileTextureView,
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
binding: 12,
|
|
402
|
+
resource: {
|
|
403
|
+
kind: 'textureView' as const,
|
|
404
|
+
value: extendedLightingResources.cookieTextureView,
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
binding: 13,
|
|
409
|
+
resource: {
|
|
410
|
+
kind: 'textureView' as const,
|
|
411
|
+
value: extendedLightingResources.ltcLambertTextureView,
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
binding: 14,
|
|
416
|
+
resource: {
|
|
417
|
+
kind: 'textureView' as const,
|
|
418
|
+
value: extendedLightingResources.ltcGgxTextureView,
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
binding: 15,
|
|
423
|
+
resource: {
|
|
424
|
+
kind: 'buffer' as const,
|
|
425
|
+
value: {
|
|
426
|
+
buffer: extendedLightingResources.cookieMatrixBuffer,
|
|
427
|
+
size: COOKIE_MATRIX_BYTES,
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
]
|
|
432
|
+
: []),
|
|
348
433
|
// feat-20260625-spot-light-shadow-mapping w25: the per-spot
|
|
349
434
|
// fragment-read lightViewProj matrices fold into the View UBO
|
|
350
435
|
// (binding 0, `view.spotLightViewProj`) — no standalone binding 9
|
|
@@ -451,12 +536,11 @@ export function buildPerFrameBindGroups(
|
|
|
451
536
|
|
|
452
537
|
/**
|
|
453
538
|
* feat-20260704 M3/w18: per-frame lighting preparation, extracted verbatim from
|
|
454
|
-
* `recordFrame`. (1) pin the
|
|
455
|
-
*
|
|
539
|
+
* `recordFrame`. (1) pin the point + spot shadow snapshot lists onto frameState
|
|
540
|
+
* for the shadow caster
|
|
456
541
|
* pass closures + lazy-allocate the point-shadow cube_array atlas on first
|
|
457
|
-
* non-empty frame (AC-09 zero-shadow zero-alloc). (3)
|
|
458
|
-
*
|
|
459
|
-
* spot arrays, and totalLightCount.
|
|
542
|
+
* non-empty frame (AC-09 zero-shadow zero-alloc). (3) derive the directional
|
|
543
|
+
* fallback and the unified local-light corpus used by Standard Cluster.
|
|
460
544
|
*
|
|
461
545
|
* @internal
|
|
462
546
|
*/
|
|
@@ -474,6 +558,7 @@ export function prepareFrameLighting(
|
|
|
474
558
|
light: DirectionalLightSnapshot;
|
|
475
559
|
pointLights: ExtractedLights['point'];
|
|
476
560
|
spotLights: ExtractedLights['spot'];
|
|
561
|
+
rectLights: ExtractedLights['rect'];
|
|
477
562
|
totalLightCount: number;
|
|
478
563
|
standard: StandardTopologyInputValue;
|
|
479
564
|
},
|
|
@@ -528,14 +613,16 @@ export function prepareFrameLighting(
|
|
|
528
613
|
//
|
|
529
614
|
// - lights.directional : feeds the View UBO at slot [16..23]
|
|
530
615
|
// (lightDir + lightColor; existing path).
|
|
531
|
-
// - lights.point[]
|
|
532
|
-
//
|
|
616
|
+
// - lights.point/spot/rect[] : packed into the one unified Standard
|
|
617
|
+
// Cluster payload below. No per-kind light
|
|
618
|
+
// transport exists at the renderer boundary.
|
|
533
619
|
//
|
|
534
620
|
// Each variant carries the discriminant `kind` so the record-time packing
|
|
535
621
|
// call sites can run exhaustive switch (charter P2 + AC-03).
|
|
536
622
|
const directionalLight: DirectionalLightSnapshot | undefined = lights.directional;
|
|
537
623
|
const pointLights = lights.point;
|
|
538
624
|
const spotLights = lights.spot;
|
|
625
|
+
const rectLights = lights.rect;
|
|
539
626
|
|
|
540
627
|
// Case C: 0 DirectionalLight = legitimate scene; the View UBO falls
|
|
541
628
|
// back to a zero-intensity directional payload so the shader's
|
|
@@ -549,7 +636,10 @@ export function prepareFrameLighting(
|
|
|
549
636
|
};
|
|
550
637
|
|
|
551
638
|
const totalLightCount =
|
|
552
|
-
(directionalLight !== undefined ? 1 : 0) +
|
|
639
|
+
(directionalLight !== undefined ? 1 : 0) +
|
|
640
|
+
pointLights.length +
|
|
641
|
+
spotLights.length +
|
|
642
|
+
rectLights.length;
|
|
553
643
|
|
|
554
644
|
const clusterGrid = frameState.installedPipelineConfig?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
555
645
|
const local = [
|
|
@@ -574,6 +664,16 @@ export function prepareFrameLighting(
|
|
|
574
664
|
: 1000,
|
|
575
665
|
source,
|
|
576
666
|
})),
|
|
667
|
+
...rectLights.map((source) => ({
|
|
668
|
+
kind: 'rect-area' as const,
|
|
669
|
+
shadowed: false,
|
|
670
|
+
position: source.position,
|
|
671
|
+
range:
|
|
672
|
+
(Number.isFinite(source.invRangeSquared) && source.invRangeSquared > 0
|
|
673
|
+
? Math.sqrt(1 / source.invRangeSquared)
|
|
674
|
+
: 1000) + Math.hypot(source.halfWidth, source.halfHeight),
|
|
675
|
+
source,
|
|
676
|
+
})),
|
|
577
677
|
];
|
|
578
678
|
const prepared = prepareStandardLighting({
|
|
579
679
|
directional: directionalLight,
|
|
@@ -590,14 +690,16 @@ export function prepareFrameLighting(
|
|
|
590
690
|
// Storage-capable Standard frames keep the same Cluster ABI even when the
|
|
591
691
|
// local-light corpus is empty. Directional-only scenes still need the
|
|
592
692
|
// unified mesh group(2) contract so their PBR draws do not select a second
|
|
593
|
-
//
|
|
594
|
-
// graph remains structurally identical.
|
|
595
|
-
//
|
|
693
|
+
// local-light layout; the existing transport emits a zero-light payload and
|
|
694
|
+
// the graph remains structurally identical. The no-storage backend has no
|
|
695
|
+
// storage-backed local-light representation, so a directional-only frame
|
|
696
|
+
// remains the sole no-local transport case.
|
|
596
697
|
if (prepared.value.local.length === 0 && !internals.device.caps.storageBuffer) {
|
|
597
698
|
return ok({
|
|
598
699
|
light,
|
|
599
700
|
pointLights,
|
|
600
701
|
spotLights,
|
|
702
|
+
rectLights,
|
|
601
703
|
totalLightCount,
|
|
602
704
|
standard: { kind: 'no-local-lights', prepared: prepared.value },
|
|
603
705
|
});
|
|
@@ -619,11 +721,109 @@ export function prepareFrameLighting(
|
|
|
619
721
|
light,
|
|
620
722
|
pointLights,
|
|
621
723
|
spotLights,
|
|
724
|
+
rectLights,
|
|
622
725
|
totalLightCount,
|
|
623
726
|
standard: { kind: 'clustered', prepared: prepared.value, transport: transport.value },
|
|
624
727
|
});
|
|
625
728
|
}
|
|
626
729
|
|
|
730
|
+
function modifierDigest(data: Uint8Array): number {
|
|
731
|
+
let hash = 2166136261;
|
|
732
|
+
for (let index = 0; index < data.length; index += 1) {
|
|
733
|
+
hash ^= data[index] ?? 0;
|
|
734
|
+
hash = Math.imul(hash, 16777619);
|
|
735
|
+
}
|
|
736
|
+
return hash >>> 0;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/** Upload authored Spot modifier payloads into the renderer-owned array lane. */
|
|
740
|
+
export function writeSpotModifierTextures(
|
|
741
|
+
internals: RenderSystemInternals,
|
|
742
|
+
pipelineState: PipelineState,
|
|
743
|
+
spots: readonly ExtractedLights['spot'][number][],
|
|
744
|
+
): void {
|
|
745
|
+
const iesTexture = pipelineState.iesProfileTexture;
|
|
746
|
+
const cookieTexture = pipelineState.cookieTexture;
|
|
747
|
+
const cookieMatrixBuffer = pipelineState.cookieMatrixBuffer;
|
|
748
|
+
if (iesTexture === undefined && cookieTexture === undefined && cookieMatrixBuffer === undefined)
|
|
749
|
+
return;
|
|
750
|
+
let state = pipelineState.spotModifierUploadState;
|
|
751
|
+
if (state === undefined) {
|
|
752
|
+
state = { ies: new Map(), cookie: new Map(), cookieMatrix: new Map() };
|
|
753
|
+
pipelineState.spotModifierUploadState = state;
|
|
754
|
+
} else if (state.cookieMatrix === undefined) {
|
|
755
|
+
state = { ...state, cookieMatrix: new Map() };
|
|
756
|
+
pipelineState.spotModifierUploadState = state;
|
|
757
|
+
}
|
|
758
|
+
for (const spot of spots) {
|
|
759
|
+
if (spot.iesProfileSlice !== undefined && spot.iesProfileData !== undefined && iesTexture) {
|
|
760
|
+
if (spot.iesProfileData.byteLength === IES_SLICE_WIDTH * IES_SLICE_HEIGHT * 2) {
|
|
761
|
+
const digest = modifierDigest(spot.iesProfileData);
|
|
762
|
+
if (state.ies.get(spot.iesProfileSlice) !== digest) {
|
|
763
|
+
const result = internals.device.queue.writeTexture(
|
|
764
|
+
{ texture: iesTexture, mipLevel: 0, origin: { x: 0, y: 0, z: spot.iesProfileSlice } },
|
|
765
|
+
spot.iesProfileData,
|
|
766
|
+
{ offset: 0, bytesPerRow: IES_SLICE_WIDTH * 2, rowsPerImage: IES_SLICE_HEIGHT },
|
|
767
|
+
{ width: IES_SLICE_WIDTH, height: IES_SLICE_HEIGHT, depthOrArrayLayers: 1 },
|
|
768
|
+
);
|
|
769
|
+
if (!result.ok) throw result.error;
|
|
770
|
+
state.ies.set(spot.iesProfileSlice, digest);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
// Authored Cookie and the SpotLight projector share the same
|
|
775
|
+
// fixed 256x256 array transport on the extended topology. Their shader
|
|
776
|
+
// projection remains distinct: Cookie uses cookieMatrices, projector
|
|
777
|
+
// uses View.spotLightViewProj. Upload both identities when a frame carries
|
|
778
|
+
// both fields, while the direct-light metadata selects the one in use.
|
|
779
|
+
for (const modifier of [
|
|
780
|
+
{
|
|
781
|
+
slice: spot.cookieSlice,
|
|
782
|
+
data: spot.cookieData,
|
|
783
|
+
matrix: spot.cookieMatrix,
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
slice: spot.projectorSlice,
|
|
787
|
+
data: spot.projectorData,
|
|
788
|
+
matrix: spot.projectorMatrix,
|
|
789
|
+
},
|
|
790
|
+
]) {
|
|
791
|
+
if (modifier.slice !== undefined && modifier.data !== undefined && cookieTexture) {
|
|
792
|
+
if (modifier.data.byteLength === COOKIE_SLICE_SIZE * COOKIE_SLICE_SIZE * 4) {
|
|
793
|
+
const digest = modifierDigest(modifier.data);
|
|
794
|
+
if (state.cookie.get(modifier.slice) !== digest) {
|
|
795
|
+
const result = internals.device.queue.writeTexture(
|
|
796
|
+
{ texture: cookieTexture, mipLevel: 0, origin: { x: 0, y: 0, z: modifier.slice } },
|
|
797
|
+
modifier.data,
|
|
798
|
+
{ offset: 0, bytesPerRow: COOKIE_SLICE_SIZE * 4, rowsPerImage: COOKIE_SLICE_SIZE },
|
|
799
|
+
{ width: COOKIE_SLICE_SIZE, height: COOKIE_SLICE_SIZE, depthOrArrayLayers: 1 },
|
|
800
|
+
);
|
|
801
|
+
if (!result.ok) throw result.error;
|
|
802
|
+
state.cookie.set(modifier.slice, digest);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (modifier.slice !== undefined && modifier.matrix !== undefined && cookieMatrixBuffer) {
|
|
807
|
+
const matrixBytes = new Uint8Array(
|
|
808
|
+
modifier.matrix.buffer,
|
|
809
|
+
modifier.matrix.byteOffset,
|
|
810
|
+
modifier.matrix.byteLength,
|
|
811
|
+
);
|
|
812
|
+
const digest = modifierDigest(matrixBytes);
|
|
813
|
+
if (state.cookieMatrix.get(modifier.slice) !== digest) {
|
|
814
|
+
const result = internals.device.queue.writeBuffer(
|
|
815
|
+
cookieMatrixBuffer,
|
|
816
|
+
modifier.slice * 16 * Float32Array.BYTES_PER_ELEMENT,
|
|
817
|
+
modifier.matrix,
|
|
818
|
+
);
|
|
819
|
+
if (!result.ok) throw result.error;
|
|
820
|
+
state.cookieMatrix.set(modifier.slice, digest);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
627
827
|
/**
|
|
628
828
|
* feat-20260704 M3/w18: write the point-shadow params UBO (bound at viewBg
|
|
629
829
|
* binding 6), extracted verbatim from `recordFrame`.
|
|
@@ -723,6 +923,7 @@ export function writeHdrpClusterAndSsaoBuffers(
|
|
|
723
923
|
gpuMembershipPipelineReady = false,
|
|
724
924
|
membershipBindGroupLayout: BindGroupLayout | null = null,
|
|
725
925
|
projectorLightSlotIndex?: number,
|
|
926
|
+
pipelineState?: PipelineState,
|
|
726
927
|
): Result<void, RenderError> {
|
|
727
928
|
const configuredClusterGrid = prepared.layout.grid;
|
|
728
929
|
const gpuMembership = transport.producer === 'gpu';
|
|
@@ -778,6 +979,14 @@ export function writeHdrpClusterAndSsaoBuffers(
|
|
|
778
979
|
};
|
|
779
980
|
}
|
|
780
981
|
|
|
982
|
+
if (pipelineState !== undefined) {
|
|
983
|
+
const preparedSpots: ExtractedLights['spot'][number][] = [];
|
|
984
|
+
for (const local of prepared.local) {
|
|
985
|
+
if (local.source?.kind === 'spot') preparedSpots.push(local.source);
|
|
986
|
+
}
|
|
987
|
+
writeSpotModifierTextures(internals, pipelineState, preparedSpots);
|
|
988
|
+
}
|
|
989
|
+
|
|
781
990
|
const gridX = prepared.layout.grid.x;
|
|
782
991
|
const gridY = prepared.layout.grid.y;
|
|
783
992
|
const gridZ = prepared.layout.grid.z;
|
|
@@ -795,30 +1004,17 @@ export function writeHdrpClusterAndSsaoBuffers(
|
|
|
795
1004
|
profilePhase,
|
|
796
1005
|
'record/scene-state/hdrp-cluster/payload-packing',
|
|
797
1006
|
() => {
|
|
798
|
-
const lightDataPayload = new Float32Array(
|
|
1007
|
+
const lightDataPayload = new Float32Array(
|
|
1008
|
+
prepared.layout.lightDataSlotCount * DIRECT_LIGHT_SLOT_FLOAT_COUNT,
|
|
1009
|
+
);
|
|
799
1010
|
let slotIdx = 0;
|
|
800
1011
|
for (const local of prepared.local) {
|
|
801
1012
|
const source = local.source;
|
|
802
1013
|
if (source === undefined) return null;
|
|
803
1014
|
const projectorSelected =
|
|
804
|
-
projectorLightSlotIndex
|
|
805
|
-
const packed =
|
|
806
|
-
|
|
807
|
-
source.shadowAtlasLayer !== undefined &&
|
|
808
|
-
source.shadowAtlasLayer >= 0 &&
|
|
809
|
-
source.shadowNear !== undefined &&
|
|
810
|
-
source.shadowFar !== undefined
|
|
811
|
-
? packLightSlot(
|
|
812
|
-
source,
|
|
813
|
-
{
|
|
814
|
-
shadowAtlasLayer: source.shadowAtlasLayer,
|
|
815
|
-
near: source.shadowNear,
|
|
816
|
-
far: source.shadowFar,
|
|
817
|
-
},
|
|
818
|
-
projectorSelected,
|
|
819
|
-
)
|
|
820
|
-
: packLightSlot(source, undefined, projectorSelected);
|
|
821
|
-
lightDataPayload.set(packed, slotIdx * 16);
|
|
1015
|
+
projectorLightSlotIndex === undefined ? undefined : projectorLightSlotIndex === slotIdx;
|
|
1016
|
+
const packed = packDirectLightSlot(source, projectorSelected);
|
|
1017
|
+
lightDataPayload.set(packed, slotIdx * DIRECT_LIGHT_SLOT_FLOAT_COUNT);
|
|
822
1018
|
slotIdx += 1;
|
|
823
1019
|
}
|
|
824
1020
|
|
|
@@ -843,7 +1039,10 @@ export function writeHdrpClusterAndSsaoBuffers(
|
|
|
843
1039
|
|
|
844
1040
|
return {
|
|
845
1041
|
hdrpBuffers,
|
|
846
|
-
lightDataUploadPayload: lightDataPayload.subarray(
|
|
1042
|
+
lightDataUploadPayload: lightDataPayload.subarray(
|
|
1043
|
+
0,
|
|
1044
|
+
slotIdx * DIRECT_LIGHT_SLOT_FLOAT_COUNT,
|
|
1045
|
+
),
|
|
847
1046
|
clusterUniformPayload: new Uint8Array(clusterUniformPayload),
|
|
848
1047
|
};
|
|
849
1048
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Extracted from render-system-record.ts (feat-20260704 M3/w17, pure move).
|
|
3
3
|
|
|
4
4
|
import type { World } from '@forgeax/engine-ecs';
|
|
5
|
+
import type { RenderReadVersion } from '@forgeax/engine-ecs/projection';
|
|
5
6
|
import { vec3 } from '@forgeax/engine-math';
|
|
6
7
|
import type { ResolvedColorTargetDescriptor } from '@forgeax/engine-render-graph';
|
|
7
8
|
import type {
|
|
@@ -81,6 +82,7 @@ import type {
|
|
|
81
82
|
RenderableSnapshot,
|
|
82
83
|
SpotLightSnapshot,
|
|
83
84
|
} from '../render-system-extract';
|
|
85
|
+
import type { ProbeBlendRecord } from '../scene/probe-blend-record';
|
|
84
86
|
import type { ShadowAtlas } from '../shadow-atlas';
|
|
85
87
|
import type {
|
|
86
88
|
TemporalFrame,
|
|
@@ -90,6 +92,18 @@ import type {
|
|
|
90
92
|
import type { VolumetricFogInspection } from '../volume/inspection';
|
|
91
93
|
import type { VolumeTemporalSignature } from '../volume/temporal';
|
|
92
94
|
|
|
95
|
+
/** Retained probe record bytes carried with one extracted render frame. */
|
|
96
|
+
export interface ProbeBlendFrameSnapshot {
|
|
97
|
+
readonly records: readonly ProbeBlendRecord[];
|
|
98
|
+
readonly recordByteLength: 160;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Renderer-owned GPU cache entry for one object's 160B probe record. */
|
|
102
|
+
export interface ProbeBlendBufferCacheEntry {
|
|
103
|
+
readonly generation: number;
|
|
104
|
+
readonly bytes: Uint8Array;
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
/**
|
|
94
108
|
* feat-20260608-create-app-param-surface-trim / M1 / D-8 (q8 user lock):
|
|
95
109
|
* fallback clear color when the world carries no Camera entity. Opaque
|
|
@@ -154,14 +168,17 @@ export function validateGraphTargetCaptureReadback(input: {
|
|
|
154
168
|
readonly bytes: Uint8Array;
|
|
155
169
|
readonly expectedByteLength: number;
|
|
156
170
|
readonly sentinel?: Uint8Array;
|
|
171
|
+
readonly allowZero?: boolean;
|
|
157
172
|
}): GraphTargetCaptureReadbackValidation {
|
|
158
|
-
const { bytes, expectedByteLength, sentinel } = input;
|
|
173
|
+
const { bytes, expectedByteLength, sentinel, allowZero = false } = input;
|
|
159
174
|
if (bytes.byteLength !== expectedByteLength)
|
|
160
175
|
return { ok: false, code: 'capture-readback-length' };
|
|
161
176
|
if (sentinel?.every((value, index) => bytes[index] === value)) {
|
|
162
177
|
return { ok: false, code: 'capture-readback-untouched-sentinel' };
|
|
163
178
|
}
|
|
164
|
-
if (bytes.every((value) => value === 0))
|
|
179
|
+
if (!allowZero && bytes.every((value) => value === 0)) {
|
|
180
|
+
return { ok: false, code: 'capture-readback-empty' };
|
|
181
|
+
}
|
|
165
182
|
for (let index = 0; index + 1 < bytes.length; index += 2) {
|
|
166
183
|
const exponent = ((bytes[index + 1] ?? 0) >>> 2) & 0x1f;
|
|
167
184
|
if (exponent === 0x1f) return { ok: false, code: 'capture-readback-non-finite' };
|
|
@@ -191,6 +208,25 @@ export interface GraphTargetCaptureRequest {
|
|
|
191
208
|
};
|
|
192
209
|
}
|
|
193
210
|
|
|
211
|
+
/** Renderer-private readback request for the Standard fallback MRT. */
|
|
212
|
+
export interface ReflectionFallbackReadbackRequest {
|
|
213
|
+
readonly name: string;
|
|
214
|
+
readonly buffer: Buffer;
|
|
215
|
+
readonly bytesPerRow: number;
|
|
216
|
+
readonly width: number;
|
|
217
|
+
readonly height: number;
|
|
218
|
+
readonly expected: {
|
|
219
|
+
readonly format: ResolvedColorTargetDescriptor['format'];
|
|
220
|
+
readonly width: number;
|
|
221
|
+
readonly height: number;
|
|
222
|
+
readonly usage: number;
|
|
223
|
+
readonly graphGeneration: number;
|
|
224
|
+
readonly frameId: number;
|
|
225
|
+
readonly textureIdentity: number;
|
|
226
|
+
};
|
|
227
|
+
encoded: boolean;
|
|
228
|
+
}
|
|
229
|
+
|
|
194
230
|
/**
|
|
195
231
|
* Build a synthetic CameraSnapshot the record stage uses when the world
|
|
196
232
|
* carries no Camera entity. Identity-shaped projection / view inputs
|
|
@@ -253,12 +289,14 @@ export function makeZeroCameraFallbackSnapshot(): CameraSnapshot {
|
|
|
253
289
|
*/
|
|
254
290
|
export interface RenderFrameState {
|
|
255
291
|
frameNumber: number;
|
|
292
|
+
/** Demand for the frame-local Standard fallback MRT. */
|
|
293
|
+
reflectionFallbackDemand?: boolean;
|
|
256
294
|
/** Monotonic compiled-graph identity used by diagnostic readbacks. */
|
|
257
295
|
graphGeneration: number;
|
|
258
296
|
/** Number of successfully submitted TAA frames; failed attempts do not advance it. */
|
|
259
297
|
successfulTemporalFrameIndex?: number;
|
|
260
298
|
/** The renderer-owned accepted-submit temporal fact consumed by consumers. */
|
|
261
|
-
temporalFrame?: TemporalFrame;
|
|
299
|
+
temporalFrame?: TemporalFrame | undefined;
|
|
262
300
|
/** The sole transaction that advances temporal history after queue.submit. */
|
|
263
301
|
readonly temporalFrameTransaction: TemporalFrameTransaction;
|
|
264
302
|
/** Staged input is consumed only by the graph submit owner. */
|
|
@@ -271,6 +309,8 @@ export interface RenderFrameState {
|
|
|
271
309
|
readonly graphGeneration: number;
|
|
272
310
|
} | null;
|
|
273
311
|
graphTargetCapture?: GraphTargetCaptureRequest | undefined;
|
|
312
|
+
/** One-frame producer-owned copy target for fallback MRT readback. */
|
|
313
|
+
reflectionFallbackReadback?: ReflectionFallbackReadbackRequest | undefined;
|
|
274
314
|
/** Last successfully rendered static directional shadow atlas token. */
|
|
275
315
|
directionalShadowCache: DirectionalShadowCache | null;
|
|
276
316
|
/** Last successfully submitted camera post-process mode. */
|
|
@@ -314,6 +354,10 @@ export interface RenderFrameState {
|
|
|
314
354
|
readonly retiredCompiledFrameGraphs: Set<CompiledRenderGraph<RenderPipelineFrame>>;
|
|
315
355
|
/** Physical outputs projected by typed graph passes for downstream observers. */
|
|
316
356
|
currentFrameObservationSource: FrameObservationSource | undefined;
|
|
357
|
+
/** Completed-frame source for the producer-owned fallback MRT. */
|
|
358
|
+
reflectionFallbackObservationSource?: FrameObservationSource | undefined;
|
|
359
|
+
/** Completion fence for the producer-owned fallback row/readback promotion. */
|
|
360
|
+
reflectionFallbackCompletion?: Promise<void> | undefined;
|
|
317
361
|
/** Camera antialias mode for the last successfully submitted graph. */
|
|
318
362
|
lastSuccessfulCameraAntialias: CameraSnapshot['antialias'] | undefined;
|
|
319
363
|
/** Staged TAA GPU state is promoted only after queue.submit succeeds. */
|
|
@@ -331,6 +375,11 @@ export interface RenderFrameState {
|
|
|
331
375
|
currentDirectionalShadowView: TextureView | null;
|
|
332
376
|
currentSpotShadowView: TextureView | null;
|
|
333
377
|
readonly instanceBuffers: Map<number, InstanceBufferCacheEntry>;
|
|
378
|
+
/** Per-object ProbeBlendRecord buffers; upload is one atomic 160B write. */
|
|
379
|
+
readonly probeBlendBuffers: Map<number, ProbeBlendBufferCacheEntry>;
|
|
380
|
+
/** One renderer-owned record array; each object selects its 256B-aligned lane. */
|
|
381
|
+
probeBlendRecordBuffer?: GpuBuffer;
|
|
382
|
+
probeBlendRecordBufferCapacity: number;
|
|
334
383
|
/** Per-entity vertex buffers for the Standard CPU morph lane. */
|
|
335
384
|
readonly morphBuffers?: Map<number, MorphBufferCacheEntry>;
|
|
336
385
|
readonly hdrpClusterBinScratch: ClusterBinScratch;
|
|
@@ -358,15 +407,11 @@ export interface RenderFrameState {
|
|
|
358
407
|
transientInstanceBuffers: InstanceBufferCacheEntry[];
|
|
359
408
|
warnedZeroLightStandard: boolean;
|
|
360
409
|
/**
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
* actionable console.warn without per-frame flooding (charter P3 explicit
|
|
365
|
-
* failure: warn-once preserves signal/noise floor).
|
|
410
|
+
* feat-20260608-multi-light-warn-once M3: once-warn latch for the
|
|
411
|
+
* single-directional authoring constraint. Standard local lights use the
|
|
412
|
+
* unified Cluster budget; there is no per-kind local-light cap.
|
|
366
413
|
*/
|
|
367
414
|
warnedMultiLightDirectional: boolean;
|
|
368
|
-
warnedMultiLightPoint: boolean;
|
|
369
|
-
warnedMultiLightSpot: boolean;
|
|
370
415
|
/**
|
|
371
416
|
* feat-20260630-equirect-kind-internalized-ibl-declarative-skyligh M3 / w19:
|
|
372
417
|
* once-warn latches for >1 Skylight / >1 SkyboxBackground entity. Fire at most
|
|
@@ -662,11 +707,11 @@ export interface DirectionalShadowCache {
|
|
|
662
707
|
* ECS state that can change the contents of a directional shadow map.
|
|
663
708
|
*
|
|
664
709
|
* The ECS-owned RenderReadLease is the only render-facing mutation boundary.
|
|
665
|
-
* Its
|
|
710
|
+
* Its version is intentionally conservative: any published World change
|
|
666
711
|
* invalidates the cached atlas, while render never reaches through World for
|
|
667
712
|
* component-clock storage.
|
|
668
713
|
*/
|
|
669
714
|
export interface DirectionalShadowWorldState {
|
|
670
715
|
readonly worldIdentity: string;
|
|
671
|
-
readonly
|
|
716
|
+
readonly version: RenderReadVersion;
|
|
672
717
|
}
|