@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
|
@@ -1,50 +1,28 @@
|
|
|
1
|
-
// @forgeax/engine-
|
|
2
|
-
// PointLight + SpotLight std430 storage buffers + storage-buffer cap gate.
|
|
1
|
+
// @forgeax/engine-render - host-side DirectLightSlot ABI and buffer helpers.
|
|
3
2
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// [ 0..2 ] position vec3<f32>
|
|
20
|
-
// [ 3 ] invRangeSquared f32
|
|
21
|
-
// [ 4..6 ] color vec3<f32> (host-pre-multiplied)
|
|
22
|
-
// [ 7 ] cosInner f32
|
|
23
|
-
// [ 8..10] direction vec3<f32> (raw outgoing vector)
|
|
24
|
-
// [ 11 ] cosOuter f32
|
|
25
|
-
// [12] depthBias, [13] normalBias, [14] pcfKernelSize
|
|
26
|
-
// [ 15 ] shadowAtlasTile i32 (sentinel -1 = unassigned/clipped; 0..3 = tile)
|
|
27
|
-
// — feat-20260625-spot-light-shadow-mapping M2 / w8 (D-4):
|
|
28
|
-
// SpotLight receiver controls occupy the 4th vec4 column. The tile
|
|
29
|
-
// lane is written i32 via an Int32Array view of the same backing
|
|
30
|
-
// ArrayBuffer; the shader reads `shadowAtlasTile: i32` from byte
|
|
31
|
-
// 60..64 of struct SpotLight (common.wgsl). -1 (0xFFFFFFFF) is the
|
|
32
|
-
// unassigned/clipped sentinel — shader samples shadow only when
|
|
33
|
-
// tile >= 0. Mirrors point's slot-7 shadowAtlasLayer pattern.
|
|
34
|
-
// [ 16 ] shadowIntensity f32 (default 1; [0,1] residual visibility)
|
|
35
|
-
// [17..19] std430 tail pad (the struct rounds to the next 16 B boundary)
|
|
36
|
-
//
|
|
37
|
-
// Array header (16 B, std430 stride alignment):
|
|
38
|
-
// [ 0 ] count u32 (number of valid slots in the trailing array)
|
|
39
|
-
// [ 1..3 ] pad u32 = 0
|
|
3
|
+
// Point, Spot, and Rect snapshots share one five-row, 80-byte Cluster slot.
|
|
4
|
+
// The same packer is used by the Cluster producer and every Cluster consumer;
|
|
5
|
+
// this is the only local-light transport.
|
|
6
|
+
|
|
7
|
+
import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
|
|
8
|
+
import type {
|
|
9
|
+
PointLightSnapshot,
|
|
10
|
+
RectAreaDirectLightSnapshot,
|
|
11
|
+
SpotLightSnapshot,
|
|
12
|
+
} from './render-system-extract';
|
|
13
|
+
// Owns the byte-frozen std430 layout (D-S2). Point, Spot, and Rect all use the
|
|
14
|
+
// same five-row DirectLightSlot; the kind and resource identities are carried
|
|
15
|
+
// by the metadata row. Point uses the angular lanes as neutral values. Spot
|
|
16
|
+
// uses row 3's x/y/z lanes for volume shadow receiver controls and w for the
|
|
17
|
+
// extended-lighting roll angle. Rect uses row 2/3 for its two tangent axes.
|
|
40
18
|
//
|
|
41
19
|
// AC anchor: requirements AC-04 (c) + C-7 (16 B alignment); plan-strategy
|
|
42
20
|
// section 2 D-S2 (byte-frozen layout); research Finding 2 (Bevy
|
|
43
21
|
// invRangeSquared naming) + Finding 9 (Bevy storage buffer pattern).
|
|
44
22
|
//
|
|
45
|
-
// Cap gate: maxStorageBuffersPerShaderStage >= 4 (
|
|
46
|
-
// entries: meshSSBO +
|
|
47
|
-
// minimum is 8, requirements assumption A-7 + plan R-4). The closed
|
|
23
|
+
// Cap gate: maxStorageBuffersPerShaderStage >= 4 (Cluster occupies four
|
|
24
|
+
// storage entries: meshSSBO + light_data + cluster_grid + light_index_list;
|
|
25
|
+
// default WebGPU minimum is 8, requirements assumption A-7 + plan R-4). The closed
|
|
48
26
|
// `RhiErrorCode` union has no `'rhi-not-supported'` member; the
|
|
49
27
|
// plan-strategy phrasing collapses onto the spec-aligned `'limit-exceeded'`
|
|
50
28
|
// arm which already documents "input value exceeded device.limits.<name>"
|
|
@@ -52,213 +30,22 @@
|
|
|
52
30
|
// keeps `RhiErrorCode` count at 18 (AGENTS.md error model evolution
|
|
53
31
|
// contract: minor add-only; w20a explicitly forbids count drift).
|
|
54
32
|
|
|
55
|
-
import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
|
|
56
|
-
import type { PointLightSnapshot, SpotLightSnapshot } from './render-system-extract';
|
|
57
|
-
|
|
58
|
-
// ── HDRP LightSlot cluster-forward unified struct ─────────────────────────────
|
|
59
|
-
// feat-20260608-cluster-lighting M4 / w16.
|
|
60
|
-
//
|
|
61
|
-
// LightSlot is the single std430 struct shared by point and spot lights in the
|
|
62
|
-
// HDRP cluster-forward path. Field layout is byte-frozen (AC-11 double-sided
|
|
63
|
-
// lock with WGSL hdrp-cluster-forward.wgsl LightSlot struct):
|
|
64
|
-
//
|
|
65
|
-
// [ 0..2 ] position vec3<f32>
|
|
66
|
-
// [ 3 ] invRangeSquared f32
|
|
67
|
-
// [ 4..6 ] color vec3<f32> (host pre-multiplied: color * intensity)
|
|
68
|
-
// [ 7 ] cosInner f32 (point: 1.0)
|
|
69
|
-
// [ 8..10] direction vec3<f32> (point: vec3(0))
|
|
70
|
-
// [ 11 ] cosOuter f32 (point: 0.0)
|
|
71
|
-
// [ 12 ] kind u32 (POINT = 0, SPOT = 1)
|
|
72
|
-
// [ 13 ] shadow identity i32 (point layer / spot tile, -1 sentinel)
|
|
73
|
-
// [14] point near / spot shadowIntensity f32
|
|
74
|
-
// [15] point far / spot pcfKernelSize f32
|
|
75
|
-
//
|
|
76
|
-
// Design: research Finding 1 (Bevy GpuClusteredLight 152B -> forgeax 64B),
|
|
77
|
-
// plan-strategy D-light-slot (kind bit-tag discriminant).
|
|
78
|
-
//
|
|
79
|
-
// The existing URP PointLight (32B) pack function remains unchanged; the URP
|
|
80
|
-
// SpotLight grows from 64B to 80B to carry the independent shadow visibility
|
|
81
|
-
// factor without stealing the tile or PCF lanes. packLightSlot remains the
|
|
82
|
-
// compact 64B HDRP owner and uses a spot-only pad lane for the same value.
|
|
83
|
-
|
|
84
|
-
/** Byte size of one HDRP LightSlot in std430 (16 x f32). AC-11 absolute-value lock. */
|
|
85
|
-
export const BYTES_PER_LIGHT_SLOT = 64;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* LightSlot kind discriminant — closed enum matching WGSL `KIND_POINT` / `KIND_SPOT`.
|
|
89
|
-
* Values are u32 bit-tags (not sequential); AC-12 exhaustive switch.
|
|
90
|
-
*/
|
|
91
|
-
export const LightSlotKind = {
|
|
92
|
-
POINT: 0,
|
|
93
|
-
SPOT: 1,
|
|
94
|
-
} as const;
|
|
95
|
-
export type LightSlotKind = (typeof LightSlotKind)[keyof typeof LightSlotKind];
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Byte-offset layout of one LightSlot in std430 (16 f32 = 64 B).
|
|
99
|
-
*
|
|
100
|
-
* Mirrors the WGSL `LightSlot` struct field order byte-for-byte.
|
|
101
|
-
* All offsets verified by w14 lightslot-layout.test.ts.
|
|
102
|
-
*
|
|
103
|
-
* feat-20260612-point-light-shadows-urp-hdrp M4 / T-M4-4 (plan-strategy §D-8):
|
|
104
|
-
* the prior u32x3 pad lanes at byte 52..64 carry shadow-side data on the HDRP
|
|
105
|
-
* path. `kind_and_pad.x = kind` (u32), `.y = shadow identity` (i32, sentinel
|
|
106
|
-
* -1 = no shadow). For point lights `.z/.w` carry near/far (f32 via bitcast);
|
|
107
|
-
* for spot lights `.z` carries shadowIntensity and `.w` carries the PCF
|
|
108
|
-
* kernel width (f32 via bitcast). The shader reads these lanes through
|
|
109
|
-
* `bitcast<f32>(...)` to
|
|
110
|
-
* keep the WGSL struct as `vec4<u32>` (alignment + naga_oil unchanged).
|
|
111
|
-
*/
|
|
112
|
-
export const LIGHTSLOT_LAYOUT = {
|
|
113
|
-
byteSize: BYTES_PER_LIGHT_SLOT,
|
|
114
|
-
positionOffset: 0,
|
|
115
|
-
invRangeSquaredOffset: 12,
|
|
116
|
-
colorOffset: 16,
|
|
117
|
-
cosInnerOffset: 28,
|
|
118
|
-
directionOffset: 32,
|
|
119
|
-
cosOuterOffset: 44,
|
|
120
|
-
kindOffset: 48,
|
|
121
|
-
shadowPayloadOffset: 52,
|
|
122
|
-
shadowAtlasLayerOffset: 52,
|
|
123
|
-
shadowAtlasTileOffset: 52,
|
|
124
|
-
shadowNearOffset: 56,
|
|
125
|
-
shadowFarOffset: 60,
|
|
126
|
-
spotPcfKernelSizeOffset: 60,
|
|
127
|
-
floatCount: 16,
|
|
128
|
-
vec4Count: 4,
|
|
129
|
-
} as const;
|
|
130
|
-
|
|
131
33
|
/**
|
|
132
34
|
* Minimum storage-buffer count needed by the M3 record stage.
|
|
133
35
|
*
|
|
134
36
|
* 1. Mesh SSBO (entity_world + normalMatrix; per-renderable dynamic
|
|
135
37
|
* offset, 256 B stride).
|
|
136
|
-
* 2.
|
|
137
|
-
* 3.
|
|
38
|
+
* 2. Cluster light_data SSBO.
|
|
39
|
+
* 3. Cluster membership grid SSBO.
|
|
40
|
+
* 4. Cluster light-index-list SSBO.
|
|
138
41
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
42
|
+
* Cluster needs four storage-backed resources in the Standard bind group.
|
|
43
|
+
* This is the complete local-light transport.
|
|
141
44
|
*/
|
|
142
45
|
export const STORAGE_BUFFER_MIN_REQUIRED = 4;
|
|
143
46
|
|
|
144
|
-
/** Byte size of one
|
|
145
|
-
export const
|
|
146
|
-
/**
|
|
147
|
-
* Byte size of one SpotLight std430 slot (five 16-byte columns).
|
|
148
|
-
*
|
|
149
|
-
* feat-20260625-spot-light-shadow-mapping M2 / w8 (D-4) grew 48 -> 64 for
|
|
150
|
-
* `shadowAtlasTile`; the visual-parity contract then adds a fifth column for
|
|
151
|
-
* `shadowIntensity` rather than overloading the tile/PCF lanes.
|
|
152
|
-
*/
|
|
153
|
-
export const SPOT_LIGHT_STD430_BYTES = 80;
|
|
154
|
-
|
|
155
|
-
/** Sentinel value for SpotLight slot[15] meaning "no shadow / clipped". */
|
|
156
|
-
export const SPOT_LIGHT_SHADOW_TILE_SENTINEL = -1;
|
|
157
|
-
/** Sentinel for a projector-only SpotLight with no shadow atlas tile. */
|
|
158
|
-
export const SPOT_LIGHT_PROJECTOR_ONLY_SENTINEL = -2;
|
|
159
|
-
/**
|
|
160
|
-
* High-bit marker carried by the shared LightSlot identity lane when this
|
|
161
|
-
* SpotLight is the one projector selected for the frame. The lower 30 bits
|
|
162
|
-
* retain the shadow-atlas tile (0..3), or zero for projector-only lights, so
|
|
163
|
-
* one 64-byte slot carries both shadow and projector identity without growing
|
|
164
|
-
* the cluster UBO or inventing a second light list.
|
|
165
|
-
*/
|
|
166
|
-
export const SPOT_LIGHT_PROJECTOR_FLAG = 0x40000000;
|
|
167
|
-
export const SPOT_LIGHT_TILE_MASK = SPOT_LIGHT_PROJECTOR_FLAG - 1;
|
|
168
|
-
/** Byte size of the array header (count u32 + 12 B pad to 16 B stride). */
|
|
169
|
-
export const LIGHT_ARRAY_HEADER_BYTES = 16;
|
|
170
|
-
/** Maximum number of slots packed in the first-slice cap layout (D-S3). */
|
|
171
|
-
export const LIGHT_ARRAY_MAX_SLOTS = 4;
|
|
172
|
-
|
|
173
|
-
/** Sentinel value for PointLight slot[7] / LightSlot pad meaning "no shadow". */
|
|
174
|
-
export const POINT_LIGHT_SHADOW_LAYER_SENTINEL = -1;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Pack one PointLightSnapshot into 8 floats / 32 B byte-for-byte std430.
|
|
178
|
-
*
|
|
179
|
-
* Returns a fresh `Float32Array` per call; `Float32Array.byteLength === 32`
|
|
180
|
-
* by construction (Float32Array(8).buffer.byteLength === 32). Slot 7
|
|
181
|
-
* (byte 28..32) carries `shadowAtlasLayer: i32` (sentinel -1 = no shadow,
|
|
182
|
-
* 0..3 = cube_array atlas layer index for shadow casters). The lane is
|
|
183
|
-
* written through an Int32Array view of the same backing ArrayBuffer so the
|
|
184
|
-
* shader's `i32` read at byte 28..32 of `struct PointLight` (common.wgsl)
|
|
185
|
-
* sees the correct two's-complement bits (-1 = 0xFFFFFFFF).
|
|
186
|
-
*/
|
|
187
|
-
export function packPointLight(snap: PointLightSnapshot): Float32Array {
|
|
188
|
-
const out = new Float32Array(8);
|
|
189
|
-
out[0] = snap.position[0] ?? 0;
|
|
190
|
-
out[1] = snap.position[1] ?? 0;
|
|
191
|
-
out[2] = snap.position[2] ?? 0;
|
|
192
|
-
out[3] = snap.invRangeSquared;
|
|
193
|
-
out[4] = snap.color[0] ?? 0;
|
|
194
|
-
out[5] = snap.color[1] ?? 0;
|
|
195
|
-
out[6] = snap.color[2] ?? 0;
|
|
196
|
-
// Slot 7: shadowAtlasLayer i32 via Int32Array view (sentinel -1 default).
|
|
197
|
-
const i32 = new Int32Array(out.buffer);
|
|
198
|
-
i32[7] = snap.shadowAtlasLayer ?? POINT_LIGHT_SHADOW_LAYER_SENTINEL;
|
|
199
|
-
return out;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Pack one SpotLightSnapshot into 20 floats (80 B byte-for-byte std430).
|
|
204
|
-
*
|
|
205
|
-
* cosInner / cosOuter ride the otherwise-padding `.w` lanes of the
|
|
206
|
-
* `color` and `direction` vec4 columns (AC-04 c + plan D-S2 16 B alignment
|
|
207
|
-
* via packing rather than padding rows). Slot 15 carries `shadowAtlasTile: i32`
|
|
208
|
-
* (sentinel -1 = unassigned/clipped, 0..3 = atlas tile) written through an
|
|
209
|
-
* Int32Array view so the shader's `i32` read at byte 60..64 of struct SpotLight
|
|
210
|
-
* (common.wgsl) sees the correct two's-complement bits (-1 = 0xFFFFFFFF).
|
|
211
|
-
* Slots 12..14 carry the shared receiver controls; slot 15 remains the i32
|
|
212
|
-
* shadow tile sentinel; slot 16 carries shadowIntensity and slots 17..19 are
|
|
213
|
-
* alignment tail padding. Surface and volume consumers therefore share one
|
|
214
|
-
* extracted shadow configuration.
|
|
215
|
-
*/
|
|
216
|
-
export function packSpotLight(snap: SpotLightSnapshot): Float32Array {
|
|
217
|
-
const out = new Float32Array(20);
|
|
218
|
-
out[0] = snap.position[0] ?? 0;
|
|
219
|
-
out[1] = snap.position[1] ?? 0;
|
|
220
|
-
out[2] = snap.position[2] ?? 0;
|
|
221
|
-
out[3] = snap.invRangeSquared;
|
|
222
|
-
out[4] = snap.color[0] ?? 0;
|
|
223
|
-
out[5] = snap.color[1] ?? 0;
|
|
224
|
-
out[6] = snap.color[2] ?? 0;
|
|
225
|
-
out[7] = snap.cosInner;
|
|
226
|
-
out[8] = snap.direction[0] ?? 0;
|
|
227
|
-
out[9] = snap.direction[1] ?? 0;
|
|
228
|
-
out[10] = snap.direction[2] ?? 0;
|
|
229
|
-
out[11] = snap.cosOuter;
|
|
230
|
-
out[12] = snap.depthBias ?? 0.005;
|
|
231
|
-
out[13] = snap.normalBias ?? 0.05;
|
|
232
|
-
out[14] = snap.pcfKernelSize ?? 3;
|
|
233
|
-
// Slot 15: shadowAtlasTile i32 via Int32Array view (sentinel -1 default).
|
|
234
|
-
const i32 = new Int32Array(out.buffer);
|
|
235
|
-
i32[15] =
|
|
236
|
-
snap.shadowAtlasTile >= 0
|
|
237
|
-
? snap.shadowAtlasTile
|
|
238
|
-
: snap.projectorAsset !== undefined && snap.lightViewProj !== undefined
|
|
239
|
-
? SPOT_LIGHT_PROJECTOR_ONLY_SENTINEL
|
|
240
|
-
: SPOT_LIGHT_SHADOW_TILE_SENTINEL;
|
|
241
|
-
// Slot 16 begins the fifth vec4 column. The remaining tail lanes stay zero
|
|
242
|
-
// so the std430 array stride is the explicit 80-byte contract.
|
|
243
|
-
out[16] = snap.shadowIntensity ?? 1;
|
|
244
|
-
return out;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Pack the 16-byte std430 array header (count u32 + 12 B pad) for the
|
|
249
|
-
* point/spot light storage buffers.
|
|
250
|
-
*
|
|
251
|
-
* Returns a fresh `ArrayBuffer` so callers can either re-view it as
|
|
252
|
-
* `Uint8Array` for `queue.writeBuffer` or as `Uint32Array` for in-place
|
|
253
|
-
* inspection.
|
|
254
|
-
*/
|
|
255
|
-
export function packLightArrayHeader(count: number): ArrayBuffer {
|
|
256
|
-
const buf = new ArrayBuffer(LIGHT_ARRAY_HEADER_BYTES);
|
|
257
|
-
const u32 = new Uint32Array(buf);
|
|
258
|
-
u32[0] = count >>> 0;
|
|
259
|
-
// Slots 1..3 stay zero (12 B pad to 16 B stride alignment).
|
|
260
|
-
return buf;
|
|
261
|
-
}
|
|
47
|
+
/** Byte size of one Point/Spot/Rect DirectLightSlot. */
|
|
48
|
+
export const BYTES_PER_DIRECT_LIGHT_SLOT = 80;
|
|
262
49
|
|
|
263
50
|
/**
|
|
264
51
|
* Cap gate at createRenderer time: check whether the device has enough
|
|
@@ -275,101 +62,144 @@ export function packLightArrayHeader(count: number): ArrayBuffer {
|
|
|
275
62
|
*
|
|
276
63
|
* Uniform-fallback path decision (plan D-5): `cap === 0` is the wgpu
|
|
277
64
|
* WebGL2 backend signal (`downlevel_webgl2_defaults().limits.
|
|
278
|
-
* maxStorageBuffersPerShaderStage = 0`).
|
|
279
|
-
*
|
|
280
|
-
* entry in the PBR pipeline switches to `uniform`.
|
|
65
|
+
* maxStorageBuffersPerShaderStage = 0`). It remains a mesh/instance fallback;
|
|
66
|
+
* local-light frames require the single Cluster storage transport.
|
|
281
67
|
*/
|
|
68
|
+
/** Closed direct-light kind carried by the unified five-row slot. */
|
|
69
|
+
export const DirectLightSlotKind = {
|
|
70
|
+
POINT: 0,
|
|
71
|
+
SPOT: 1,
|
|
72
|
+
RECT_AREA: 2,
|
|
73
|
+
} as const;
|
|
74
|
+
export type DirectLightSlotKind = 'point' | 'spot' | 'rect-area';
|
|
75
|
+
|
|
76
|
+
/** Metadata identity used for absent shadow, IES, and Cookie resources. */
|
|
77
|
+
export const DIRECT_LIGHT_SLOT_METADATA_SENTINEL = 0xffffffff;
|
|
282
78
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* and stay on the unshadowed `evalPoint` path.
|
|
287
|
-
*
|
|
288
|
-
* `near` / `far` ride the otherwise-pad lanes (`kind_and_pad.zw` in the WGSL
|
|
289
|
-
* struct, byte 56..64) and feed the depth-ref reconstruction in
|
|
290
|
-
* `evalPointShadowed`. Spot lights (and shadow-less point lights) leave these
|
|
291
|
-
* lanes zero per std430 init.
|
|
79
|
+
* SpotLight projector marker carried in the shared shadow identity word. The
|
|
80
|
+
* lower 30 bits retain the selected shadow tile; projector-only spots use tile
|
|
81
|
+
* zero because their matrix is deliberately published in View lane zero.
|
|
292
82
|
*/
|
|
293
|
-
export
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
83
|
+
export const DIRECT_LIGHT_SLOT_PROJECTOR_FLAG = 0x40000000;
|
|
84
|
+
export const DIRECT_LIGHT_SLOT_TILE_MASK = DIRECT_LIGHT_SLOT_PROJECTOR_FLAG - 1;
|
|
85
|
+
/** Byte size of the five-row Point/Spot/Rect transport slot. */
|
|
86
|
+
export const DIRECT_LIGHT_SLOT_FLOAT_COUNT =
|
|
87
|
+
BYTES_PER_DIRECT_LIGHT_SLOT / Float32Array.BYTES_PER_ELEMENT;
|
|
88
|
+
|
|
89
|
+
/** Five vec4 rows shared by host packing and the WGSL direct-light consumer. */
|
|
90
|
+
export const DIRECT_LIGHT_SLOT_LAYOUT = {
|
|
91
|
+
byteSize: BYTES_PER_DIRECT_LIGHT_SLOT,
|
|
92
|
+
rowByteOffsets: [0, 16, 32, 48, 64],
|
|
93
|
+
positionOffset: 0,
|
|
94
|
+
rangeOffset: 12,
|
|
95
|
+
colorOffset: 16,
|
|
96
|
+
firstAngleOffset: 28,
|
|
97
|
+
primaryAxisOffset: 32,
|
|
98
|
+
secondAngleOffset: 44,
|
|
99
|
+
auxiliaryAxisOffset: 48,
|
|
100
|
+
metadataByteOffset: 64,
|
|
101
|
+
kindByteOffset: 64,
|
|
102
|
+
shadowByteOffset: 68,
|
|
103
|
+
iesProfileByteOffset: 72,
|
|
104
|
+
cookieByteOffset: 76,
|
|
105
|
+
/** Spot-only roll angle stored in the fourth row's w lane. */
|
|
106
|
+
rollDegByteOffset: 60,
|
|
107
|
+
floatCount: DIRECT_LIGHT_SLOT_FLOAT_COUNT,
|
|
108
|
+
vec4Count: 5,
|
|
109
|
+
} as const;
|
|
110
|
+
|
|
111
|
+
type DirectLightModifierMetadata = {
|
|
112
|
+
readonly iesProfileSlice?: number;
|
|
113
|
+
readonly cookieSlice?: number;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type DirectLightSnapshot =
|
|
117
|
+
| (PointLightSnapshot & DirectLightModifierMetadata)
|
|
118
|
+
| (SpotLightSnapshot & DirectLightModifierMetadata)
|
|
119
|
+
| (RectAreaDirectLightSnapshot & DirectLightModifierMetadata);
|
|
120
|
+
|
|
121
|
+
function directLightMetadata(value: number | undefined): number {
|
|
122
|
+
return value === undefined ? DIRECT_LIGHT_SLOT_METADATA_SENTINEL : value >>> 0;
|
|
297
123
|
}
|
|
298
124
|
|
|
299
125
|
/**
|
|
300
|
-
* Pack one
|
|
301
|
-
* (16 floats, std430). Point lights fill `cosInner=1.0`, `direction=vec3(0)`,
|
|
302
|
-
* `cosOuter=0.0`, `kind=POINT(0)`. Spot lights fill all fields verbatim;
|
|
303
|
-
* `direction` is already normalized by extract and this owner never repeats
|
|
304
|
-
* that operation.
|
|
305
|
-
*
|
|
306
|
-
* feat-20260612-point-light-shadows-urp-hdrp M4 / T-M4-4 (plan-strategy §D-8):
|
|
307
|
-
* the optional point `shadow` info threads through to bytes 52..64 as
|
|
308
|
-
* `(shadowAtlasLayer i32, near f32, far f32)`. Spot snapshots write their
|
|
309
|
-
* `shadowAtlasTile` directly into the same identity lane, put shadowIntensity
|
|
310
|
-
* in the `.z` lane, and the PCF kernel width in `.w`. The shader reads `near`/`far`
|
|
311
|
-
* through `bitcast<f32>(kind_and_pad.zw)` so the WGSL struct stays
|
|
312
|
-
* `kind_and_pad: vec4<u32>` (alignment + naga_oil compose unchanged). When
|
|
313
|
-
* `shadow` is undefined (no PointLightShadow) the lanes default to
|
|
314
|
-
* `(layer = -1, 0, 0)` -- shader gates on `layer >= 0` so unshadowed lights
|
|
315
|
-
* stay on the `evaluate_point_light` path. Spot lights write their tile or -1.
|
|
126
|
+
* Pack one Point, Spot, or Rect snapshot into the unified five-row slot.
|
|
316
127
|
*
|
|
317
|
-
*
|
|
128
|
+
* Row 0 is position plus inverse range. Row 1 is color plus the first
|
|
129
|
+
* angular/size fact. Row 2 is the primary axis plus the second angular/size
|
|
130
|
+
* fact. Row 3 is the auxiliary Rect axis. Row 4 is four u32 identities.
|
|
318
131
|
*/
|
|
319
|
-
export function
|
|
320
|
-
|
|
321
|
-
shadow?: PointShadowSlotInfo,
|
|
132
|
+
export function packDirectLightSlot(
|
|
133
|
+
snapshot: DirectLightSnapshot,
|
|
322
134
|
projectorSelected?: boolean,
|
|
323
135
|
): Float32Array {
|
|
324
|
-
const out = new Float32Array(
|
|
325
|
-
|
|
326
|
-
out[
|
|
327
|
-
out[
|
|
328
|
-
out[
|
|
329
|
-
out[
|
|
330
|
-
|
|
331
|
-
out[
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (snap.kind === 'point' && shadow !== undefined) {
|
|
349
|
-
i32[13] = shadow.shadowAtlasLayer;
|
|
350
|
-
out[14] = shadow.near;
|
|
351
|
-
out[15] = shadow.far;
|
|
352
|
-
} else if (snap.kind === 'spot') {
|
|
353
|
-
// The optional argument is explicit at the record owner. Keeping the
|
|
354
|
-
// source-derived fallback preserves standalone packing fixtures while the
|
|
355
|
-
// production path marks only the accepted projector identity.
|
|
356
|
-
const hasProjector =
|
|
357
|
-
projectorSelected ?? (snap.projectorAsset !== undefined && snap.lightViewProj !== undefined);
|
|
358
|
-
const tile = snap.shadowAtlasTile >= 0 ? snap.shadowAtlasTile : 0;
|
|
359
|
-
i32[13] = hasProjector
|
|
360
|
-
? SPOT_LIGHT_PROJECTOR_FLAG | (tile & SPOT_LIGHT_TILE_MASK)
|
|
361
|
-
: snap.shadowAtlasTile >= 0
|
|
362
|
-
? snap.shadowAtlasTile
|
|
363
|
-
: SPOT_LIGHT_SHADOW_TILE_SENTINEL;
|
|
364
|
-
out[14] = snap.shadowIntensity ?? 1;
|
|
365
|
-
// HDRP has no separate 80-byte SpotLight payload. Reuse the otherwise
|
|
366
|
-
// unused spot `.w` lane so the cluster path consumes the same authored PCF
|
|
367
|
-
// width as the URP and volume paths.
|
|
368
|
-
out[15] = snap.pcfKernelSize ?? 3;
|
|
136
|
+
const out = new Float32Array(DIRECT_LIGHT_SLOT_FLOAT_COUNT);
|
|
137
|
+
out[0] = snapshot.position[0] ?? 0;
|
|
138
|
+
out[1] = snapshot.position[1] ?? 0;
|
|
139
|
+
out[2] = snapshot.position[2] ?? 0;
|
|
140
|
+
out[3] = snapshot.invRangeSquared;
|
|
141
|
+
out[4] = snapshot.color[0] ?? 0;
|
|
142
|
+
out[5] = snapshot.color[1] ?? 0;
|
|
143
|
+
out[6] = snapshot.color[2] ?? 0;
|
|
144
|
+
|
|
145
|
+
if (snapshot.kind === 'point') {
|
|
146
|
+
out[7] = 1;
|
|
147
|
+
} else if (snapshot.kind === 'spot') {
|
|
148
|
+
out[7] = snapshot.cosInner;
|
|
149
|
+
out[8] = snapshot.direction[0] ?? 0;
|
|
150
|
+
out[9] = snapshot.direction[1] ?? 0;
|
|
151
|
+
out[10] = snapshot.direction[2] ?? 0;
|
|
152
|
+
out[11] = snapshot.cosOuter;
|
|
153
|
+
// Row 3 is the Rect auxiliary axis for RectArea lights. Spot uses x/y/z
|
|
154
|
+
// for its receiver controls and w for roll; the surface direct-light
|
|
155
|
+
// owner only consumes w, while the volume owner consumes the full row.
|
|
156
|
+
out[12] = snapshot.depthBias ?? 0.005;
|
|
157
|
+
out[13] = snapshot.normalBias ?? 0.05;
|
|
158
|
+
out[14] = snapshot.shadowIntensity ?? 1;
|
|
159
|
+
out[15] = snapshot.rollDeg ?? 0;
|
|
369
160
|
} else {
|
|
370
|
-
|
|
371
|
-
|
|
161
|
+
out[7] = snapshot.halfWidth;
|
|
162
|
+
out[8] = snapshot.axisY[0] ?? 0;
|
|
163
|
+
out[9] = snapshot.axisY[1] ?? 0;
|
|
164
|
+
out[10] = snapshot.axisY[2] ?? 0;
|
|
165
|
+
out[11] = snapshot.halfHeight;
|
|
166
|
+
out[12] = snapshot.axisX[0] ?? 0;
|
|
167
|
+
out[13] = snapshot.axisX[1] ?? 0;
|
|
168
|
+
out[14] = snapshot.axisX[2] ?? 0;
|
|
372
169
|
}
|
|
170
|
+
|
|
171
|
+
const metadata = new Uint32Array(out.buffer);
|
|
172
|
+
metadata[16] =
|
|
173
|
+
snapshot.kind === 'point'
|
|
174
|
+
? DirectLightSlotKind.POINT
|
|
175
|
+
: snapshot.kind === 'spot'
|
|
176
|
+
? DirectLightSlotKind.SPOT
|
|
177
|
+
: DirectLightSlotKind.RECT_AREA;
|
|
178
|
+
const spotProjectorSelected =
|
|
179
|
+
snapshot.kind === 'spot' &&
|
|
180
|
+
(projectorSelected ??
|
|
181
|
+
(snapshot.projectorAsset !== undefined && snapshot.lightViewProj !== undefined));
|
|
182
|
+
const spotShadowMetadata =
|
|
183
|
+
snapshot.kind === 'spot'
|
|
184
|
+
? spotProjectorSelected
|
|
185
|
+
? DIRECT_LIGHT_SLOT_PROJECTOR_FLAG |
|
|
186
|
+
((snapshot.shadowAtlasTile >= 0 ? snapshot.shadowAtlasTile : 0) &
|
|
187
|
+
DIRECT_LIGHT_SLOT_TILE_MASK)
|
|
188
|
+
: directLightMetadata(snapshot.shadowAtlasTile)
|
|
189
|
+
: undefined;
|
|
190
|
+
metadata[17] = directLightMetadata(
|
|
191
|
+
snapshot.kind === 'point'
|
|
192
|
+
? snapshot.shadowAtlasLayer
|
|
193
|
+
: snapshot.kind === 'spot'
|
|
194
|
+
? spotShadowMetadata
|
|
195
|
+
: undefined,
|
|
196
|
+
);
|
|
197
|
+
metadata[18] = directLightMetadata(snapshot.iesProfileSlice);
|
|
198
|
+
metadata[19] = directLightMetadata(
|
|
199
|
+
spotProjectorSelected && snapshot.kind === 'spot'
|
|
200
|
+
? snapshot.projectorSlice
|
|
201
|
+
: snapshot.cookieSlice,
|
|
202
|
+
);
|
|
373
203
|
return out;
|
|
374
204
|
}
|
|
375
205
|
|
|
@@ -383,8 +213,8 @@ export function assertStorageBufferCap(cap: number): Result<boolean, RhiError> {
|
|
|
383
213
|
return err(
|
|
384
214
|
new RhiError({
|
|
385
215
|
code: 'limit-exceeded',
|
|
386
|
-
expected: `device.limits.maxStorageBuffersPerShaderStage >= ${STORAGE_BUFFER_MIN_REQUIRED}, or exactly 0 for
|
|
387
|
-
hint: `device.limits.maxStorageBuffersPerShaderStage = ${cap} < ${STORAGE_BUFFER_MIN_REQUIRED} and != 0. WebGPU spec default minimum is 8; this
|
|
216
|
+
expected: `device.limits.maxStorageBuffersPerShaderStage >= ${STORAGE_BUFFER_MIN_REQUIRED}, or exactly 0 for the mesh-only fallback`,
|
|
217
|
+
hint: `device.limits.maxStorageBuffersPerShaderStage = ${cap} < ${STORAGE_BUFFER_MIN_REQUIRED} and != 0. WebGPU spec default minimum is 8; this adapter cannot run the unified Cluster local-light path.`,
|
|
388
218
|
detail: {
|
|
389
219
|
maxStorageBufferBindingSize: cap,
|
|
390
220
|
requestedBytes: STORAGE_BUFFER_MIN_REQUIRED,
|
package/src/materials.ts
CHANGED
|
@@ -130,6 +130,16 @@ function pass(
|
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
function shadowCasterRenderState(
|
|
134
|
+
renderState: MaterialRenderState | undefined,
|
|
135
|
+
): MaterialRenderState | undefined {
|
|
136
|
+
if (renderState?.cullMode === undefined && renderState?.frontFace === undefined) return undefined;
|
|
137
|
+
return {
|
|
138
|
+
...(renderState.cullMode === undefined ? {} : { cullMode: renderState.cullMode }),
|
|
139
|
+
...(renderState.frontFace === undefined ? {} : { frontFace: renderState.frontFace }),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
133
143
|
interface UnlitOpts {
|
|
134
144
|
/** Asset-side authored color space. Defaults to sRGB. */
|
|
135
145
|
readonly colorSpace?: MaterialColorSpace;
|
|
@@ -150,7 +160,9 @@ function unlit(rgba: readonly [number, number, number, number], opts?: UnlitOpts
|
|
|
150
160
|
const passes: [MaterialPass, ...MaterialPass[]] = [
|
|
151
161
|
pass('forward', UNLIT_MODULE, opts?.renderState, undefined, opts?.queue),
|
|
152
162
|
];
|
|
153
|
-
if (opts?.castShadow !== false)
|
|
163
|
+
if (opts?.castShadow !== false) {
|
|
164
|
+
passes.push(pass('shadow-caster', UNLIT_MODULE, shadowCasterRenderState(opts?.renderState)));
|
|
165
|
+
}
|
|
154
166
|
return {
|
|
155
167
|
kind: 'material',
|
|
156
168
|
...(opts?.colorSpace === undefined || opts.colorSpace === 'srgb'
|
|
@@ -292,7 +304,9 @@ function standard(opts: StandardOpts): MaterialAsset {
|
|
|
292
304
|
if (transmission === 0) {
|
|
293
305
|
passes.push(pass('deferred', STANDARD_MODULE, opts.renderState, 'fs_gbuffer', opts.queue));
|
|
294
306
|
}
|
|
295
|
-
if (opts.castShadow !== false)
|
|
307
|
+
if (opts.castShadow !== false) {
|
|
308
|
+
passes.push(pass('shadow-caster', STANDARD_MODULE, shadowCasterRenderState(opts.renderState)));
|
|
309
|
+
}
|
|
296
310
|
return {
|
|
297
311
|
kind: 'material',
|
|
298
312
|
...(opts.colorSpace === undefined || opts.colorSpace === 'srgb'
|