@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
|
@@ -70,6 +70,32 @@ export interface TemporalFrameReceipt<T = unknown> {
|
|
|
70
70
|
readonly historyDirection: 'a-to-b' | 'b-to-a';
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export type ReflectionFallbackTemporalReset =
|
|
74
|
+
| { readonly reset: false }
|
|
75
|
+
| { readonly reset: true; readonly reason: 'reflection-fallback-generation' };
|
|
76
|
+
|
|
77
|
+
/** Maps committed producer generations into the existing temporal reset seam. */
|
|
78
|
+
export function resolveReflectionFallbackTemporalReset(
|
|
79
|
+
previousGeneration: number | undefined,
|
|
80
|
+
nextGeneration: number | undefined,
|
|
81
|
+
): ReflectionFallbackTemporalReset {
|
|
82
|
+
if (previousGeneration === undefined || nextGeneration === undefined) return { reset: false };
|
|
83
|
+
return previousGeneration === nextGeneration
|
|
84
|
+
? { reset: false }
|
|
85
|
+
: { reset: true, reason: 'reflection-fallback-generation' };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Keeps SSR admission on the existing producer-generation reset seam. The
|
|
90
|
+
* admission path never allocates or resolves temporal history itself.
|
|
91
|
+
*/
|
|
92
|
+
export function resolveSsrAdmissionTemporalReset(
|
|
93
|
+
previousGeneration: number | undefined,
|
|
94
|
+
nextGeneration: number | undefined,
|
|
95
|
+
): ReflectionFallbackTemporalReset {
|
|
96
|
+
return resolveReflectionFallbackTemporalReset(previousGeneration, nextGeneration);
|
|
97
|
+
}
|
|
98
|
+
|
|
73
99
|
function failure(code: TemporalFrameErrorCode, hint: string): TemporalFrameError {
|
|
74
100
|
return {
|
|
75
101
|
code,
|
package/src/temporal/frame.ts
CHANGED
|
@@ -44,6 +44,8 @@ export interface TemporalFrameTransaction {
|
|
|
44
44
|
stage(input: TemporalFrameInput): void;
|
|
45
45
|
commit(submit: TemporalSubmitResult): Result<TemporalFrame, TemporalFrameSubmitError>;
|
|
46
46
|
snapshot(): TemporalFrame;
|
|
47
|
+
/** Drop accepted/staged history after a producer or device generation cut. */
|
|
48
|
+
reset(reason?: Extract<TemporalResetReason, 'signature-change' | 'device-recovery'>): void;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
function copyInput(input: TemporalFrameInput): TemporalFrameInput {
|
|
@@ -82,6 +84,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
82
84
|
let accepted: TemporalFrame | undefined;
|
|
83
85
|
let staged: TemporalFrameInput | undefined;
|
|
84
86
|
let historyEpoch = 0;
|
|
87
|
+
let pendingResetReason: Exclude<TemporalResetReason, 'none' | 'queue-submit-failed'> | undefined;
|
|
85
88
|
|
|
86
89
|
return {
|
|
87
90
|
stage(input) {
|
|
@@ -96,7 +99,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
96
99
|
return err(new TemporalFrameSubmitError('queue-submit-failed'));
|
|
97
100
|
}
|
|
98
101
|
|
|
99
|
-
const resetReason = submit.resetReason ?? staged.resetReason ?? 'none';
|
|
102
|
+
const resetReason = submit.resetReason ?? staged.resetReason ?? pendingResetReason ?? 'none';
|
|
100
103
|
const shouldReset = resetReason !== 'none';
|
|
101
104
|
if (shouldReset) historyEpoch += 1;
|
|
102
105
|
const next: TemporalFrame = {
|
|
@@ -117,6 +120,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
117
120
|
};
|
|
118
121
|
accepted = next;
|
|
119
122
|
staged = undefined;
|
|
123
|
+
pendingResetReason = undefined;
|
|
120
124
|
return ok(copyFrame(next));
|
|
121
125
|
},
|
|
122
126
|
snapshot() {
|
|
@@ -124,5 +128,14 @@ export function createTemporalFrameTransaction(options: {
|
|
|
124
128
|
throw new Error('TemporalFrame snapshot is unavailable before commit');
|
|
125
129
|
return copyFrame(accepted);
|
|
126
130
|
},
|
|
131
|
+
reset(reason = 'signature-change') {
|
|
132
|
+
accepted = undefined;
|
|
133
|
+
staged = undefined;
|
|
134
|
+
historyEpoch += 1;
|
|
135
|
+
// The reason is carried into the next accepted frame while clearing the
|
|
136
|
+
// committed frame prevents stale motion vectors from crossing the
|
|
137
|
+
// producer/device boundary.
|
|
138
|
+
pendingResetReason = reason;
|
|
139
|
+
},
|
|
127
140
|
};
|
|
128
141
|
}
|
package/src/temporal/view.ts
CHANGED
|
@@ -38,6 +38,8 @@ export interface TemporalViewInput {
|
|
|
38
38
|
readonly historyValid?: boolean;
|
|
39
39
|
readonly currentUnjitteredViewProjection?: ArrayLike<number> | undefined;
|
|
40
40
|
readonly previousUnjitteredViewProjection?: ArrayLike<number> | undefined;
|
|
41
|
+
readonly currentCameraPosition?: readonly [number, number, number] | undefined;
|
|
42
|
+
readonly previousCameraPosition?: readonly [number, number, number] | undefined;
|
|
41
43
|
readonly resetReason?: TemporalResetReason | undefined;
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -55,6 +57,8 @@ interface TemporalViewSnapshot {
|
|
|
55
57
|
readonly historyValid: boolean;
|
|
56
58
|
readonly currentUnjitteredViewProjection: ArrayLike<number> | undefined;
|
|
57
59
|
readonly previousUnjitteredViewProjection: ArrayLike<number> | undefined;
|
|
60
|
+
readonly currentCameraPosition: readonly [number, number, number] | undefined;
|
|
61
|
+
readonly previousCameraPosition: readonly [number, number, number] | undefined;
|
|
58
62
|
readonly resetReason: TemporalResetReason | undefined;
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -70,6 +74,9 @@ export interface TemporalView {
|
|
|
70
74
|
/** Unjittered matrices are supplied by the renderer projection owner. */
|
|
71
75
|
readonly currentUnjitteredViewProjection: ArrayLike<number> | undefined;
|
|
72
76
|
readonly previousUnjitteredViewProjection: ArrayLike<number> | undefined;
|
|
77
|
+
/** Camera origins follow the same accepted-submit boundary as the matrices. */
|
|
78
|
+
readonly currentCameraPosition: readonly [number, number, number] | undefined;
|
|
79
|
+
readonly previousCameraPosition: readonly [number, number, number] | undefined;
|
|
73
80
|
readonly currentProjection: 'jittered' | 'unjittered';
|
|
74
81
|
readonly previousProjection: 'unjittered';
|
|
75
82
|
readonly historyRequired: boolean;
|
|
@@ -112,6 +119,8 @@ export function createTemporalView(input: TemporalViewInput): TemporalView {
|
|
|
112
119
|
historyValid: input.historyValid ?? false,
|
|
113
120
|
currentUnjitteredViewProjection: input.currentUnjitteredViewProjection,
|
|
114
121
|
previousUnjitteredViewProjection: input.previousUnjitteredViewProjection,
|
|
122
|
+
currentCameraPosition: input.currentCameraPosition,
|
|
123
|
+
previousCameraPosition: input.previousCameraPosition,
|
|
115
124
|
resetReason: input.resetReason,
|
|
116
125
|
});
|
|
117
126
|
const taa = input.antialias === 'taa';
|
|
@@ -135,6 +144,8 @@ export function createTemporalView(input: TemporalViewInput): TemporalView {
|
|
|
135
144
|
temporalFrameIndex: frameIndex,
|
|
136
145
|
currentUnjitteredViewProjection: input.currentUnjitteredViewProjection,
|
|
137
146
|
previousUnjitteredViewProjection: input.previousUnjitteredViewProjection,
|
|
147
|
+
currentCameraPosition: input.currentCameraPosition,
|
|
148
|
+
previousCameraPosition: input.previousCameraPosition,
|
|
138
149
|
currentProjection: taa ? 'jittered' : 'unjittered',
|
|
139
150
|
previousProjection: 'unjittered',
|
|
140
151
|
historyRequired: taa,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
58
58
|
import { decodeTileBits } from '@forgeax/engine-graphics-extras';
|
|
59
59
|
import { type box3, frustum, mat4 } from '@forgeax/engine-math';
|
|
60
|
-
import { ChildOf, Children, Transform } from '@forgeax/engine-scene';
|
|
60
|
+
import { ChildOf, Children, GlobalTransform, Transform } from '@forgeax/engine-scene';
|
|
61
61
|
import {
|
|
62
62
|
type Handle,
|
|
63
63
|
type MaterialAsset,
|
|
@@ -874,13 +874,13 @@ function bucketTileLayer(
|
|
|
874
874
|
* cull paths use byte-identical planes (charter P4 consistent abstraction).
|
|
875
875
|
*/
|
|
876
876
|
function buildCameraFrustumPlanes(world: World): frustum.Frustum | null {
|
|
877
|
-
const query = world.query({ with: [Camera, Transform] }).unwrap();
|
|
877
|
+
const query = world.query({ with: [Camera, Transform, GlobalTransform] }).unwrap();
|
|
878
878
|
let result: frustum.Frustum | null = null;
|
|
879
879
|
for (const row of query) {
|
|
880
880
|
const camEntity = row.entity;
|
|
881
881
|
|
|
882
882
|
const camRes = world.get(camEntity, Camera);
|
|
883
|
-
const trRes = world.get(camEntity,
|
|
883
|
+
const trRes = world.get(camEntity, GlobalTransform);
|
|
884
884
|
if (!camRes.ok || !trRes.ok) continue;
|
|
885
885
|
|
|
886
886
|
const cam = camRes.value;
|
|
@@ -1081,7 +1081,7 @@ function evictDeadPerCellStreamingCaches(work: readonly LayerWork[], world: Worl
|
|
|
1081
1081
|
/**
|
|
1082
1082
|
* Walk every TileLayer ChildOf-ing a Tilemap, extract its non-zero cells
|
|
1083
1083
|
* into derived render entities. A Renderer attaches this system to FrameEnd;
|
|
1084
|
-
* World's final publication then resolves newly-created
|
|
1084
|
+
* World's final publication then resolves newly-created GlobalTransform.world values before the
|
|
1085
1085
|
* read-only render walk begins.
|
|
1086
1086
|
*
|
|
1087
1087
|
* Two paths based on `TileLayer.sortScope`:
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from './render-graph-primitives';
|
|
35
35
|
import type { RenderPipelineFrame, RenderPipelineGpuDrivenProjection } from './render-pipeline';
|
|
36
36
|
import { createRenderPipelineTarget, type RenderPipelineTarget } from './render-pipeline';
|
|
37
|
+
import type { OcclusionFrameProjection } from './scene/visibility/occlusion-runtime';
|
|
37
38
|
import {
|
|
38
39
|
getTemporalBindGroupResources,
|
|
39
40
|
getTemporalGpuState,
|
|
@@ -136,6 +137,7 @@ export interface TypedScenePassOptions {
|
|
|
136
137
|
readonly transmissionBackdrop?: GraphTextureView | undefined;
|
|
137
138
|
readonly extraAccesses?: readonly GraphAccess[] | undefined;
|
|
138
139
|
readonly gpuDriven?: RenderPipelineGpuDrivenProjection | undefined;
|
|
140
|
+
readonly occlusion?: OcclusionFrameProjection | undefined;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
export function addTypedScenePass(
|
|
@@ -187,6 +189,7 @@ export function addTypedScenePass(
|
|
|
187
189
|
stencilLoadOp: options.depthLoadOp ?? 'clear',
|
|
188
190
|
stencilStoreOp: 'store',
|
|
189
191
|
},
|
|
192
|
+
occlusionQuerySet: options.occlusion?.querySet,
|
|
190
193
|
encode: ({ pass, frame, resources }) => {
|
|
191
194
|
const colorViews = colorTargets.map((target) => resolvedView(resources, target.view));
|
|
192
195
|
const depthView = resolvedView(resources, options.depth.view);
|
|
@@ -228,13 +231,23 @@ export function addTypedScenePass(
|
|
|
228
231
|
if (groups.viewBindGroup !== null) {
|
|
229
232
|
options.gpuDriven?.encode(groups.viewBindGroup, pass, resources);
|
|
230
233
|
}
|
|
234
|
+
// The context carries the frame's primary occlusion projection for
|
|
235
|
+
// pipeline construction, but only the pass that owns that projection
|
|
236
|
+
// may begin its query. Forwarding it to deferred/temporal scene passes
|
|
237
|
+
// leaves their descriptors without an occlusionQuerySet and makes Dawn
|
|
238
|
+
// reject beginOcclusionQuery in those passes.
|
|
239
|
+
const activeOcclusion = options.occlusion;
|
|
231
240
|
encodeMainPass(
|
|
232
241
|
{
|
|
233
242
|
...internal,
|
|
243
|
+
...(activeOcclusion === undefined ? {} : { occlusion: activeOcclusion }),
|
|
234
244
|
geometryColorView: colorViews[0] ?? null,
|
|
235
245
|
geometryDepthView: depthView,
|
|
236
246
|
geometryColorResolveView: resolveView,
|
|
237
247
|
transparentColorFormat: colorTargets[0]?.format as GPUTextureFormat,
|
|
248
|
+
...(colorTargets[1]?.format === 'rgba16float'
|
|
249
|
+
? { reflectionFallbackColorFormat: 'rgba16float' as const }
|
|
250
|
+
: {}),
|
|
238
251
|
msaaActive: colorTargets[0]?.sampleCount === 4,
|
|
239
252
|
viewBindGroup: groups.viewBindGroup,
|
|
240
253
|
meshBindGroup: groups.meshBindGroup,
|
|
@@ -256,6 +269,10 @@ export function addTypedScenePass(
|
|
|
256
269
|
: { transmissionBackdropView: transmissionBackdrop }),
|
|
257
270
|
},
|
|
258
271
|
);
|
|
272
|
+
if (activeOcclusion !== undefined) {
|
|
273
|
+
const proxyResult = activeOcclusion.encodeProxyBounds(pass);
|
|
274
|
+
if (!proxyResult.ok) throw proxyResult.error;
|
|
275
|
+
}
|
|
259
276
|
},
|
|
260
277
|
});
|
|
261
278
|
}
|
|
@@ -291,6 +308,37 @@ export function addTypedFrameObservationPass(
|
|
|
291
308
|
});
|
|
292
309
|
}
|
|
293
310
|
|
|
311
|
+
/** Publish the same-frame fallback MRT as a detached, copy-readable source. */
|
|
312
|
+
export function addReflectionFallbackObservationPass(
|
|
313
|
+
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
314
|
+
target: RenderPipelineTarget,
|
|
315
|
+
): Result<void, RenderGraphError> {
|
|
316
|
+
return graph.addCopyPass('reflection-fallback-observation', {
|
|
317
|
+
accesses: [{ resource: target.view, usage: 'copy-src' }],
|
|
318
|
+
encode: ({ frame, resources }) => {
|
|
319
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
320
|
+
const texture = resources.texture(target.texture);
|
|
321
|
+
if (!texture.ok) throw texture.error;
|
|
322
|
+
internal.frameState.reflectionFallbackObservationSource = {
|
|
323
|
+
texture: texture.value,
|
|
324
|
+
descriptor: {
|
|
325
|
+
texture: texture.value,
|
|
326
|
+
format: target.format,
|
|
327
|
+
size: { width: frame.targetW, height: frame.targetH },
|
|
328
|
+
usage:
|
|
329
|
+
GPU_TEXTURE_USAGE_COPY_SRC |
|
|
330
|
+
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
|
|
331
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
332
|
+
sample: target.sampleCount,
|
|
333
|
+
},
|
|
334
|
+
frameId: internal.frameState.frameNumber,
|
|
335
|
+
pipelineId: 'forgeax::standard',
|
|
336
|
+
backendId: internal.runtime.device.caps.backendKind,
|
|
337
|
+
};
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
294
342
|
export interface TypedBloomTargets {
|
|
295
343
|
readonly scene: RenderPipelineTarget;
|
|
296
344
|
readonly composited: RenderPipelineTarget;
|
package/src/volume/passes.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type {
|
|
|
2
2
|
GraphBuffer,
|
|
3
3
|
GraphTextureView,
|
|
4
4
|
RenderGraphBuilder,
|
|
5
|
-
RenderGraphError,
|
|
6
5
|
} from '@forgeax/engine-render-graph';
|
|
6
|
+
import { RenderGraphError } from '@forgeax/engine-render-graph';
|
|
7
7
|
import type {
|
|
8
8
|
BindGroup,
|
|
9
9
|
BindGroupLayout,
|
|
@@ -14,18 +14,10 @@ import type {
|
|
|
14
14
|
TextureView,
|
|
15
15
|
} from '@forgeax/engine-rhi';
|
|
16
16
|
import { RhiError } from '@forgeax/engine-rhi';
|
|
17
|
-
import { ok, type Result } from '@forgeax/engine-types';
|
|
17
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
18
18
|
import { GPU_TEXTURE_USAGE_TEXTURE_BINDING } from '../gpu-texture-usage';
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
GPU_BUFFER_USAGE_STORAGE,
|
|
22
|
-
GPU_BUFFER_USAGE_UNIFORM,
|
|
23
|
-
} from '../gpu-usage';
|
|
24
|
-
import {
|
|
25
|
-
LIGHT_ARRAY_HEADER_BYTES,
|
|
26
|
-
LIGHT_ARRAY_MAX_SLOTS,
|
|
27
|
-
SPOT_LIGHT_STD430_BYTES,
|
|
28
|
-
} from '../light-buffer-layout';
|
|
19
|
+
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
|
|
20
|
+
import type { StandardClusterGraphBuffers } from '../pipeline/standard-lighting/graph';
|
|
29
21
|
import { VIEW_UNIFORM_BYTES } from '../record/view-ubo';
|
|
30
22
|
import type { VolumetricFogFrameContext, VolumetricFogShaderSources } from '../render-contract';
|
|
31
23
|
import type {
|
|
@@ -91,8 +83,10 @@ export interface VolumetricFogPassInputs {
|
|
|
91
83
|
readonly view: GraphBuffer;
|
|
92
84
|
readonly directionalShadow?: GraphTextureView;
|
|
93
85
|
readonly spotShadow: GraphTextureView;
|
|
94
|
-
|
|
95
|
-
readonly
|
|
86
|
+
/** The single Standard Cluster light payload consumed by all volume stages. */
|
|
87
|
+
readonly lightData: GraphBuffer;
|
|
88
|
+
/** The Cluster uniform carries the admitted light count for slot guards. */
|
|
89
|
+
readonly clusterUniform: GraphBuffer;
|
|
96
90
|
readonly selectedLightKind: 'directional' | 'point' | 'spot';
|
|
97
91
|
readonly projector?: GraphTextureView;
|
|
98
92
|
}
|
|
@@ -169,10 +163,26 @@ function importVolumeInputs(
|
|
|
169
163
|
directionalShadow: GraphTextureView | undefined,
|
|
170
164
|
spotShadow: GraphTextureView,
|
|
171
165
|
selectedLightKind: 'directional' | 'point' | 'spot' | undefined,
|
|
166
|
+
clusterBuffers: StandardClusterGraphBuffers | null,
|
|
172
167
|
): Result<ImportedVolumeInputs | undefined, RenderGraphError> {
|
|
173
168
|
const volume = topology.volumetricFog;
|
|
174
169
|
if (volume?.enabled !== true || volume.format === undefined || volume.extent === undefined)
|
|
175
170
|
return ok(undefined);
|
|
171
|
+
if (clusterBuffers === null) {
|
|
172
|
+
return err(
|
|
173
|
+
new RenderGraphError({
|
|
174
|
+
code: 'resource-descriptor-invalid',
|
|
175
|
+
expected: 'volumetric fog consumes the Standard Cluster light buffers',
|
|
176
|
+
hint: 'enable the storage-backed Standard Cluster transport before enabling volumetric fog',
|
|
177
|
+
detail: {
|
|
178
|
+
resourceLabel: 'volumetric-fog',
|
|
179
|
+
field: 'clusterBuffers',
|
|
180
|
+
expected: 'StandardClusterGraphBuffers',
|
|
181
|
+
actual: 'missing',
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
176
186
|
const texture = graph.importTexture(
|
|
177
187
|
'volume-density',
|
|
178
188
|
{
|
|
@@ -218,21 +228,6 @@ function importVolumeInputs(
|
|
|
218
228
|
(frame) => frame.pipelineState.viewUniformBuffer,
|
|
219
229
|
);
|
|
220
230
|
if (!view.ok) return view;
|
|
221
|
-
const spotLights = graph.importBuffer(
|
|
222
|
-
'volume-spot-lights',
|
|
223
|
-
{
|
|
224
|
-
size: LIGHT_ARRAY_HEADER_BYTES + LIGHT_ARRAY_MAX_SLOTS * SPOT_LIGHT_STD430_BYTES,
|
|
225
|
-
usage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,
|
|
226
|
-
},
|
|
227
|
-
(frame) => frame.pipelineState.spotLightsBuffer,
|
|
228
|
-
);
|
|
229
|
-
if (!spotLights.ok) return spotLights;
|
|
230
|
-
const pointLights = graph.importBuffer(
|
|
231
|
-
'volume-point-lights',
|
|
232
|
-
{ size: 16 + 4 * 32, usage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST },
|
|
233
|
-
(frame) => frame.pipelineState.pointLightsBuffer,
|
|
234
|
-
);
|
|
235
|
-
if (!pointLights.ok) return pointLights;
|
|
236
231
|
let projector: GraphTextureView | undefined;
|
|
237
232
|
if (volume.projector !== undefined) {
|
|
238
233
|
const projectorTexture = graph.importTexture(
|
|
@@ -270,8 +265,8 @@ function importVolumeInputs(
|
|
|
270
265
|
view: view.value,
|
|
271
266
|
...(directionalShadow === undefined ? {} : { directionalShadow }),
|
|
272
267
|
spotShadow,
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
lightData: clusterBuffers.lightData,
|
|
269
|
+
clusterUniform: clusterBuffers.clusterUniform,
|
|
275
270
|
selectedLightKind: selectedLightKind ?? 'directional',
|
|
276
271
|
...(projector === undefined ? {} : { projector }),
|
|
277
272
|
});
|
|
@@ -283,6 +278,7 @@ export function addAuthoredVolumetricFogPasses(
|
|
|
283
278
|
sceneDepth: GraphTextureView,
|
|
284
279
|
directionalShadow: GraphTextureView | undefined,
|
|
285
280
|
spotShadow: GraphTextureView,
|
|
281
|
+
clusterBuffers: StandardClusterGraphBuffers | null,
|
|
286
282
|
): Result<void, RenderGraphError> {
|
|
287
283
|
// A paired Point+Spot volume stores the Spot shadow lane as well. The
|
|
288
284
|
// topology's primary light remains PointLight for radiance selection, but
|
|
@@ -300,6 +296,7 @@ export function addAuthoredVolumetricFogPasses(
|
|
|
300
296
|
directionalShadow,
|
|
301
297
|
spotShadow,
|
|
302
298
|
shadowLightKind,
|
|
299
|
+
clusterBuffers,
|
|
303
300
|
);
|
|
304
301
|
if (!imported.ok) return imported;
|
|
305
302
|
if (imported.value === undefined) return ok(undefined);
|
|
@@ -342,8 +339,8 @@ export function addVolumetricFogPasses(
|
|
|
342
339
|
resource: shadowResource,
|
|
343
340
|
usage: 'sampled-read',
|
|
344
341
|
},
|
|
345
|
-
{ resource: inputs.
|
|
346
|
-
{ resource: inputs.
|
|
342
|
+
{ resource: inputs.lightData, usage: 'storage-read' },
|
|
343
|
+
{ resource: inputs.clusterUniform, usage: 'uniform-read' },
|
|
347
344
|
...(inputs.projector === undefined
|
|
348
345
|
? []
|
|
349
346
|
: [{ resource: inputs.projector, usage: 'sampled-read' as const }]),
|
|
@@ -365,19 +362,19 @@ export function addVolumetricFogPasses(
|
|
|
365
362
|
},
|
|
366
363
|
},
|
|
367
364
|
{ binding: 7, visibility: 4, buffer: { type: 'read-only-storage' } },
|
|
368
|
-
{ binding: 8, visibility: 4, buffer: { type: '
|
|
365
|
+
{ binding: 8, visibility: 4, buffer: { type: 'uniform' } },
|
|
369
366
|
]);
|
|
370
367
|
const shadow = resources.textureView(shadowResource);
|
|
371
368
|
const params = resources.buffer(inputs.params);
|
|
372
369
|
const view = resources.buffer(inputs.view);
|
|
373
|
-
const
|
|
374
|
-
const
|
|
370
|
+
const lightData = resources.buffer(inputs.lightData);
|
|
371
|
+
const clusterUniform = resources.buffer(inputs.clusterUniform);
|
|
375
372
|
const froxel = resources.textureView(inputs.resources.froxelView);
|
|
376
373
|
if (!shadow.ok) throw shadow.error;
|
|
377
374
|
if (!params.ok) throw params.error;
|
|
378
375
|
if (!view.ok) throw view.error;
|
|
379
|
-
if (!
|
|
380
|
-
if (!
|
|
376
|
+
if (!lightData.ok) throw lightData.error;
|
|
377
|
+
if (!clusterUniform.ok) throw clusterUniform.error;
|
|
381
378
|
if (!froxel.ok) throw froxel.error;
|
|
382
379
|
const shadowSampler = frame.runtime.device.createSampler({ compare: 'less' });
|
|
383
380
|
if (!shadowSampler.ok) throw shadowSampler.error;
|
|
@@ -387,8 +384,8 @@ export function addVolumetricFogPasses(
|
|
|
387
384
|
{ binding: 4, resource: { kind: 'sampler', value: shadowSampler.value } },
|
|
388
385
|
{ binding: 5, resource: { kind: 'buffer', value: { buffer: params.value } } },
|
|
389
386
|
{ binding: 6, resource: { kind: 'textureView', value: froxel.value as never } },
|
|
390
|
-
{ binding: 7, resource: { kind: 'buffer', value: { buffer:
|
|
391
|
-
{ binding: 8, resource: { kind: 'buffer', value: { buffer:
|
|
387
|
+
{ binding: 7, resource: { kind: 'buffer', value: { buffer: lightData.value } } },
|
|
388
|
+
{ binding: 8, resource: { kind: 'buffer', value: { buffer: clusterUniform.value } } },
|
|
392
389
|
]);
|
|
393
390
|
pass.setPipeline(inject.pipeline);
|
|
394
391
|
pass.setBindGroup(0, bindings);
|
|
@@ -406,8 +403,8 @@ export function addVolumetricFogPasses(
|
|
|
406
403
|
{ resource: inputs.resources.temporalView, usage: 'storage-write' },
|
|
407
404
|
{ resource: inputs.params, usage: 'uniform-read' },
|
|
408
405
|
{ resource: inputs.view, usage: 'uniform-read' },
|
|
409
|
-
{ resource: inputs.
|
|
410
|
-
{ resource: inputs.
|
|
406
|
+
{ resource: inputs.lightData, usage: 'storage-read' },
|
|
407
|
+
{ resource: inputs.clusterUniform, usage: 'uniform-read' },
|
|
411
408
|
...(inputs.projector === undefined
|
|
412
409
|
? []
|
|
413
410
|
: [{ resource: inputs.projector, usage: 'sampled-read' as const }]),
|
|
@@ -449,7 +446,7 @@ export function addVolumetricFogPasses(
|
|
|
449
446
|
},
|
|
450
447
|
},
|
|
451
448
|
{ binding: 10, visibility: 4, buffer: { type: 'read-only-storage' } },
|
|
452
|
-
{ binding: 11, visibility: 4, buffer: { type: '
|
|
449
|
+
{ binding: 11, visibility: 4, buffer: { type: 'uniform' } },
|
|
453
450
|
{ binding: 12, visibility: 4, texture: { sampleType: 'float', viewDimension: '2d' } },
|
|
454
451
|
{ binding: 13, visibility: 4, sampler: { type: 'filtering' } },
|
|
455
452
|
]);
|
|
@@ -461,8 +458,8 @@ export function addVolumetricFogPasses(
|
|
|
461
458
|
const temporalSeed = resources.textureView(inputs.resources.temporalView);
|
|
462
459
|
const params = resources.buffer(inputs.params);
|
|
463
460
|
const view = resources.buffer(inputs.view);
|
|
464
|
-
const
|
|
465
|
-
const
|
|
461
|
+
const lightData = resources.buffer(inputs.lightData);
|
|
462
|
+
const clusterUniform = resources.buffer(inputs.clusterUniform);
|
|
466
463
|
const projector =
|
|
467
464
|
inputs.projector === undefined ? undefined : resources.textureView(inputs.projector);
|
|
468
465
|
if (!froxel.ok) throw froxel.error;
|
|
@@ -473,8 +470,8 @@ export function addVolumetricFogPasses(
|
|
|
473
470
|
if (!temporalSeed.ok) throw temporalSeed.error;
|
|
474
471
|
if (!params.ok) throw params.error;
|
|
475
472
|
if (!view.ok) throw view.error;
|
|
476
|
-
if (!
|
|
477
|
-
if (!
|
|
473
|
+
if (!lightData.ok) throw lightData.error;
|
|
474
|
+
if (!clusterUniform.ok) throw clusterUniform.error;
|
|
478
475
|
if (projector !== undefined && !projector.ok) throw projector.error;
|
|
479
476
|
const sampler = frame.runtime.device.createSampler({
|
|
480
477
|
minFilter: 'linear',
|
|
@@ -500,8 +497,8 @@ export function addVolumetricFogPasses(
|
|
|
500
497
|
{ binding: 7, resource: { kind: 'sampler', value: densitySampler.value } },
|
|
501
498
|
{ binding: 8, resource: { kind: 'textureView', value: historySeed.value as never } },
|
|
502
499
|
{ binding: 9, resource: { kind: 'textureView', value: temporalSeed.value as never } },
|
|
503
|
-
{ binding: 10, resource: { kind: 'buffer', value: { buffer:
|
|
504
|
-
{ binding: 11, resource: { kind: 'buffer', value: { buffer:
|
|
500
|
+
{ binding: 10, resource: { kind: 'buffer', value: { buffer: lightData.value } } },
|
|
501
|
+
{ binding: 11, resource: { kind: 'buffer', value: { buffer: clusterUniform.value } } },
|
|
505
502
|
{
|
|
506
503
|
binding: 12,
|
|
507
504
|
resource: {
|