@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
package/src/pbr-pipeline.ts
CHANGED
|
@@ -25,11 +25,11 @@ import type {
|
|
|
25
25
|
BindGroup,
|
|
26
26
|
BindGroupEntry,
|
|
27
27
|
BindGroupLayout,
|
|
28
|
-
BindGroupLayoutDescriptor,
|
|
29
28
|
Buffer,
|
|
30
29
|
PipelineLayout,
|
|
31
30
|
RhiDevice,
|
|
32
31
|
Sampler,
|
|
32
|
+
TextureFormat,
|
|
33
33
|
TextureView,
|
|
34
34
|
} from '@forgeax/engine-rhi';
|
|
35
35
|
import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, type ShaderCatalog } from '@forgeax/engine-shader';
|
|
@@ -72,6 +72,10 @@ export interface PbrPipelineLayoutBundle {
|
|
|
72
72
|
readonly meshArrayBgl: BindGroupLayout;
|
|
73
73
|
/** Per-instance storage BindGroupLayout (slot 3). */
|
|
74
74
|
readonly instancesBgl: BindGroupLayout;
|
|
75
|
+
/** Probe-enabled slot-3 BGL; aliases `instancesBgl` when probes are unavailable. */
|
|
76
|
+
readonly probeInstancesBgl: BindGroupLayout;
|
|
77
|
+
/** Same pipeline layout with the probe-enabled slot-3 BGL, when supported. */
|
|
78
|
+
readonly probePipelineLayout: PipelineLayout | null;
|
|
75
79
|
/**
|
|
76
80
|
* Same 4 layouts in slot order. Useful for assertion sites that check the
|
|
77
81
|
* pipeline-layout `bindGroupLayouts` array shape (t57 (a) + (d)).
|
|
@@ -84,6 +88,14 @@ export interface PbrPipelineLayoutBundle {
|
|
|
84
88
|
];
|
|
85
89
|
}
|
|
86
90
|
|
|
91
|
+
/** Derives the Standard PBR attachment list without allocating a closed path. */
|
|
92
|
+
export function standardPbrColorFormats(
|
|
93
|
+
baseFormat: TextureFormat,
|
|
94
|
+
fallbackDemand: boolean,
|
|
95
|
+
): readonly TextureFormat[] {
|
|
96
|
+
return fallbackDemand ? [baseFormat, 'rgba16float'] : [baseFormat];
|
|
97
|
+
}
|
|
98
|
+
|
|
87
99
|
// ─── Base entries (round-4 SSOT) ────────────────────────────────────────────
|
|
88
100
|
|
|
89
101
|
/**
|
|
@@ -325,14 +337,21 @@ export const INJECTION_KIND_LENGTHS = {
|
|
|
325
337
|
*/
|
|
326
338
|
export interface PbrCaps {
|
|
327
339
|
readonly storageBuffer: boolean;
|
|
340
|
+
/**
|
|
341
|
+
* Whether the selected material variant declares the optional extended
|
|
342
|
+
* lighting view resources. The default keeps the historical helper shape
|
|
343
|
+
* for callers that build the canonical full PBR layout; the renderer passes
|
|
344
|
+
* the device/variant decision explicitly.
|
|
345
|
+
*/
|
|
346
|
+
readonly extendedLighting?: boolean;
|
|
347
|
+
/** Selects the optional binding(1) ProbeBlendRecord lane. */
|
|
348
|
+
readonly probeBlend?: boolean;
|
|
328
349
|
/** Whether the device can carry the optional SpotLight projector texture. */
|
|
329
350
|
readonly projectorAvailable?: boolean;
|
|
330
351
|
}
|
|
331
352
|
|
|
332
353
|
/**
|
|
333
354
|
* The view BGL entry list. binding 0 = view UBO (vertex + fragment);
|
|
334
|
-
* binding 1 = pointLights (storage or uniform, per caps);
|
|
335
|
-
* binding 2 = spotLights (storage or uniform, per caps);
|
|
336
355
|
* binding 3 = directional shadowMap atlas (texture_depth_2d, vertex+fragment).
|
|
337
356
|
* feat-20260613-csm-cascaded-shadow-maps: this is the CSM atlas — N
|
|
338
357
|
* cascades tiled into one 2D depth texture, sampled via per-cascade UV
|
|
@@ -372,12 +391,11 @@ export interface PbrCaps {
|
|
|
372
391
|
* layout and consumed only by the dedicated points-lines shader).
|
|
373
392
|
* Isolated here so M4 round-4 tests can recreate the layout.
|
|
374
393
|
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
394
|
+
* Local lights are not part of the view group. Standard material variants
|
|
395
|
+
* consume the one Cluster payload in group(2), while this group retains only
|
|
396
|
+
* camera and shadow resources.
|
|
378
397
|
*/
|
|
379
398
|
export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[] {
|
|
380
|
-
const lightBufType: GPUBufferBindingType = caps.storageBuffer ? 'read-only-storage' : 'uniform';
|
|
381
399
|
const entries: GPUBindGroupLayoutEntry[] = [
|
|
382
400
|
{
|
|
383
401
|
binding: 0,
|
|
@@ -386,16 +404,6 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
|
|
|
386
404
|
// Keeping this dynamic is also valid for the display slot at offset 0.
|
|
387
405
|
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
388
406
|
},
|
|
389
|
-
{
|
|
390
|
-
binding: 1,
|
|
391
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
392
|
-
buffer: { type: lightBufType },
|
|
393
|
-
},
|
|
394
|
-
{
|
|
395
|
-
binding: 2,
|
|
396
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
397
|
-
buffer: { type: lightBufType },
|
|
398
|
-
},
|
|
399
407
|
{
|
|
400
408
|
binding: 3,
|
|
401
409
|
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
@@ -422,9 +430,9 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
|
|
|
422
430
|
// shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each
|
|
423
431
|
// lane stores `(near, far, 1/(far-near), 0)` so the fragment-shader
|
|
424
432
|
// depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)
|
|
425
|
-
// can avoid sampling
|
|
426
|
-
//
|
|
427
|
-
// HDRP shaders even though the BGL declares it (charter P4 single SSOT
|
|
433
|
+
// can avoid sampling DirectLightSlot for the URP path. The shared
|
|
434
|
+
// DirectLightSlot metadata remains the identity owner, so binding 6 is
|
|
435
|
+
// unused on HDRP shaders even though the BGL declares it (charter P4 single SSOT
|
|
428
436
|
// BGL across pipelines; the HDRP variant simply doesn't reference the
|
|
429
437
|
// binding in WGSL, which is allowed).
|
|
430
438
|
{
|
|
@@ -474,12 +482,41 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
|
|
|
474
482
|
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
475
483
|
},
|
|
476
484
|
];
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
485
|
+
const extendedLighting = caps.extendedLighting ?? true;
|
|
486
|
+
if (extendedLighting) {
|
|
487
|
+
entries.push(
|
|
488
|
+
{
|
|
489
|
+
binding: 9,
|
|
490
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
491
|
+
sampler: { type: 'filtering' },
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
binding: 11,
|
|
495
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
496
|
+
texture: { sampleType: 'float', viewDimension: '2d-array' },
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
binding: 12,
|
|
500
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
501
|
+
texture: { sampleType: 'float', viewDimension: '2d-array' },
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
binding: 13,
|
|
505
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
506
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
binding: 14,
|
|
510
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
511
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
binding: 15,
|
|
515
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
516
|
+
buffer: { type: 'uniform' },
|
|
517
|
+
},
|
|
518
|
+
);
|
|
519
|
+
} else if (caps.projectorAvailable !== false) {
|
|
483
520
|
entries.push(
|
|
484
521
|
{
|
|
485
522
|
binding: 11,
|
|
@@ -508,8 +545,8 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
|
|
|
508
545
|
* material, mesh-array, instances]`; the material BGL is derived from the
|
|
509
546
|
* standard material schema and engine injection chain.
|
|
510
547
|
*
|
|
511
|
-
* `caps.storageBuffer===false` switches
|
|
512
|
-
*
|
|
548
|
+
* `caps.storageBuffer===false` switches the mesh-array and instances entries
|
|
549
|
+
* to `uniform`; local-light resources are never part of this view group.
|
|
513
550
|
*
|
|
514
551
|
* Throws on each `createBindGroupLayout` / `createPipelineLayout` Result
|
|
515
552
|
* failure -- the engine bootstrap path (createRenderer) wraps the call in
|
|
@@ -545,9 +582,27 @@ export function buildPbrPipelineLayouts(
|
|
|
545
582
|
|
|
546
583
|
// instances BGL.
|
|
547
584
|
const instancesBglRes = device.createBindGroupLayout(
|
|
548
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
585
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
586
|
+
kind: 'pbr-instances',
|
|
587
|
+
caps: { ...caps, probeBlend: false },
|
|
588
|
+
}),
|
|
549
589
|
);
|
|
550
590
|
if (!instancesBglRes.ok) throw instancesBglRes.error;
|
|
591
|
+
// ProbeBlendRecord is a storage-buffer-only ABI extension. A uniform
|
|
592
|
+
// fallback cannot afford the extra fragment-stage uniform binding on
|
|
593
|
+
// WebGL2/GLES, so do not even construct the probe BGL on that capability
|
|
594
|
+
// route. The record stage gates the matching variant and bind group with
|
|
595
|
+
// the same storage capability; aliasing the ordinary BGL keeps the bundle
|
|
596
|
+
// total and makes an accidental probe request fail closed at layout select.
|
|
597
|
+
const probeInstancesBglRes = caps.storageBuffer
|
|
598
|
+
? device.createBindGroupLayout(
|
|
599
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
600
|
+
kind: 'pbr-instances',
|
|
601
|
+
caps: { ...caps, probeBlend: true },
|
|
602
|
+
}),
|
|
603
|
+
)
|
|
604
|
+
: { ok: true as const, value: instancesBglRes.value };
|
|
605
|
+
if (!probeInstancesBglRes.ok) throw probeInstancesBglRes.error;
|
|
551
606
|
|
|
552
607
|
// Pipeline layout (4 slots).
|
|
553
608
|
const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [
|
|
@@ -561,6 +616,21 @@ export function buildPbrPipelineLayouts(
|
|
|
561
616
|
bindGroupLayouts: layouts,
|
|
562
617
|
});
|
|
563
618
|
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
619
|
+
const probeLayouts: readonly [
|
|
620
|
+
BindGroupLayout,
|
|
621
|
+
BindGroupLayout,
|
|
622
|
+
BindGroupLayout,
|
|
623
|
+
BindGroupLayout,
|
|
624
|
+
] = [viewBglRes.value, materialBglRes.value, meshArrayBglRes.value, probeInstancesBglRes.value];
|
|
625
|
+
let probePipelineLayout: PipelineLayout | null = null;
|
|
626
|
+
if (caps.storageBuffer) {
|
|
627
|
+
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
628
|
+
label: 'pbr-probe-pl',
|
|
629
|
+
bindGroupLayouts: probeLayouts,
|
|
630
|
+
});
|
|
631
|
+
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
632
|
+
probePipelineLayout = probePipelineLayoutRes.value;
|
|
633
|
+
}
|
|
564
634
|
|
|
565
635
|
return {
|
|
566
636
|
pipelineLayout: pipelineLayoutRes.value,
|
|
@@ -568,6 +638,8 @@ export function buildPbrPipelineLayouts(
|
|
|
568
638
|
materialBgl: materialBglRes.value,
|
|
569
639
|
meshArrayBgl: meshArrayBglRes.value,
|
|
570
640
|
instancesBgl: instancesBglRes.value,
|
|
641
|
+
probeInstancesBgl: probeInstancesBglRes.value,
|
|
642
|
+
probePipelineLayout,
|
|
571
643
|
bindGroupLayouts: layouts,
|
|
572
644
|
};
|
|
573
645
|
}
|
|
@@ -685,6 +757,21 @@ export function buildPbrSkinLayouts(
|
|
|
685
757
|
bindGroupLayouts: layouts,
|
|
686
758
|
});
|
|
687
759
|
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
760
|
+
const probeLayouts: readonly [
|
|
761
|
+
BindGroupLayout,
|
|
762
|
+
BindGroupLayout,
|
|
763
|
+
BindGroupLayout,
|
|
764
|
+
BindGroupLayout,
|
|
765
|
+
] = [pbr.viewBgl, pbr.materialBgl, skinMeshArrayBglRes.value, pbr.probeInstancesBgl];
|
|
766
|
+
let probePipelineLayout: PipelineLayout | null = null;
|
|
767
|
+
if (caps.storageBuffer) {
|
|
768
|
+
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
769
|
+
label: 'pbr-skin-probe-pl',
|
|
770
|
+
bindGroupLayouts: probeLayouts,
|
|
771
|
+
});
|
|
772
|
+
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
773
|
+
probePipelineLayout = probePipelineLayoutRes.value;
|
|
774
|
+
}
|
|
688
775
|
|
|
689
776
|
return {
|
|
690
777
|
pipelineLayout: pipelineLayoutRes.value,
|
|
@@ -692,6 +779,8 @@ export function buildPbrSkinLayouts(
|
|
|
692
779
|
materialBgl: pbr.materialBgl,
|
|
693
780
|
meshArrayBgl: skinMeshArrayBglRes.value,
|
|
694
781
|
instancesBgl: pbr.instancesBgl,
|
|
782
|
+
probeInstancesBgl: pbr.probeInstancesBgl,
|
|
783
|
+
probePipelineLayout,
|
|
695
784
|
bindGroupLayouts: layouts,
|
|
696
785
|
};
|
|
697
786
|
}
|
|
@@ -860,8 +949,9 @@ export const SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = '';
|
|
|
860
949
|
* - `'unlit-material'` — 7 entries: base PBR material only (no inject)
|
|
861
950
|
* - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL
|
|
862
951
|
* 2. Caps-driven literal shapes (no shader):
|
|
863
|
-
* - `'pbr-view'` —
|
|
864
|
-
*
|
|
952
|
+
* - `'pbr-view'` — camera/shadow bindings, optional projector
|
|
953
|
+
* texture/sampler (11/12), and the Points/Lines UBO (10). Local lights
|
|
954
|
+
* are carried exclusively by the Standard Cluster group(2).
|
|
865
955
|
* (directional 3/4, point 5/6, cascade 7, spot atlas 8; the former
|
|
866
956
|
* spot lightViewProj matrices moved into the View UBO)
|
|
867
957
|
* - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)
|
|
@@ -909,7 +999,7 @@ export interface BindGroupLayoutDescriptorOutput {
|
|
|
909
999
|
}
|
|
910
1000
|
|
|
911
1001
|
/** Build the canonical HDRP group(2) bind-group layout. */
|
|
912
|
-
export function createHdrpBindGroupLayoutDescriptor():
|
|
1002
|
+
export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {
|
|
913
1003
|
const meshBufType: GPUBufferBindingType = 'read-only-storage';
|
|
914
1004
|
const clusterBufType: GPUBufferBindingType = 'read-only-storage';
|
|
915
1005
|
return {
|
|
@@ -961,7 +1051,7 @@ export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor
|
|
|
961
1051
|
}
|
|
962
1052
|
|
|
963
1053
|
/** Build the HDRP group(2) layout for the clustered skin variant. */
|
|
964
|
-
export function createHdrpSkinBindGroupLayoutDescriptor():
|
|
1054
|
+
export function createHdrpSkinBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {
|
|
965
1055
|
const base = createHdrpBindGroupLayoutDescriptor();
|
|
966
1056
|
const baseEntries = base.entries;
|
|
967
1057
|
if (baseEntries === undefined || baseEntries[0] === undefined) {
|
|
@@ -1088,19 +1178,35 @@ export function buildBindGroupLayoutDescriptor(
|
|
|
1088
1178
|
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
1089
1179
|
? 'read-only-storage'
|
|
1090
1180
|
: 'uniform';
|
|
1181
|
+
const entries: GPUBindGroupLayoutEntry[] = [
|
|
1182
|
+
{
|
|
1183
|
+
binding: 0,
|
|
1184
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1185
|
+
buffer: { type: meshBufType, hasDynamicOffset: false },
|
|
1186
|
+
},
|
|
1187
|
+
...(caps.probeBlend === true
|
|
1188
|
+
? [
|
|
1189
|
+
{
|
|
1190
|
+
// Per-object fragment lane; the record is always exactly 160B.
|
|
1191
|
+
binding: 1,
|
|
1192
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1193
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
1194
|
+
},
|
|
1195
|
+
]
|
|
1196
|
+
: []),
|
|
1197
|
+
];
|
|
1091
1198
|
return {
|
|
1092
|
-
label: 'pbr-instances-bgl',
|
|
1093
|
-
entries:
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
],
|
|
1199
|
+
label: caps.probeBlend === true ? 'pbr-probe-instances-bgl' : 'pbr-instances-bgl',
|
|
1200
|
+
entries: entries.map((entry) =>
|
|
1201
|
+
entry.binding === 0
|
|
1202
|
+
? {
|
|
1203
|
+
...entry,
|
|
1204
|
+
// Standard transmission reads the same per-instance transform in
|
|
1205
|
+
// fs_main to convert glTF unit-space thickness into world metres.
|
|
1206
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1207
|
+
}
|
|
1208
|
+
: entry,
|
|
1209
|
+
),
|
|
1104
1210
|
};
|
|
1105
1211
|
}
|
|
1106
1212
|
case 'pbr-skin-mesh-array': {
|
|
@@ -5,6 +5,11 @@ import type {
|
|
|
5
5
|
} from '@forgeax/engine-render-graph';
|
|
6
6
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
7
7
|
import { SceneDataUnavailableError } from '../errors/render';
|
|
8
|
+
import {
|
|
9
|
+
GPU_TEXTURE_USAGE_COPY_SRC,
|
|
10
|
+
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
|
|
11
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
12
|
+
} from '../gpu-texture-usage';
|
|
8
13
|
import type {
|
|
9
14
|
RenderPipeline,
|
|
10
15
|
RenderPipelineBuildContext,
|
|
@@ -29,6 +34,7 @@ import {
|
|
|
29
34
|
transmissionDemandForTopology,
|
|
30
35
|
} from '../transmission/backdrop';
|
|
31
36
|
import {
|
|
37
|
+
addReflectionFallbackObservationPass,
|
|
32
38
|
addTypedFrameObservationPass,
|
|
33
39
|
addTypedScenePass,
|
|
34
40
|
addTypedSkyboxPass,
|
|
@@ -135,6 +141,35 @@ function buildUrp(
|
|
|
135
141
|
: sceneResolved;
|
|
136
142
|
if (!scene.ok) return scene;
|
|
137
143
|
|
|
144
|
+
const reflectionFallback = topology.reflectionFallback?.enabled
|
|
145
|
+
? target(graph, 'reflection-fallback-linear-hdr', {
|
|
146
|
+
format: 'rgba16float',
|
|
147
|
+
size: 'surface',
|
|
148
|
+
sampleCount: scene.value.sampleCount,
|
|
149
|
+
domain: 'linear-hdr',
|
|
150
|
+
usage:
|
|
151
|
+
GPU_TEXTURE_USAGE_COPY_SRC |
|
|
152
|
+
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
|
|
153
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
154
|
+
})
|
|
155
|
+
: ok(undefined);
|
|
156
|
+
if (!reflectionFallback.ok) return reflectionFallback;
|
|
157
|
+
if (reflectionFallback.value !== undefined) {
|
|
158
|
+
const initialized = graph.addRasterPass('reflection-fallback-clear', {
|
|
159
|
+
accesses: [{ resource: reflectionFallback.value.view, usage: 'color-attachment' }],
|
|
160
|
+
colorAttachments: [
|
|
161
|
+
{
|
|
162
|
+
view: reflectionFallback.value.view,
|
|
163
|
+
loadOp: 'clear',
|
|
164
|
+
storeOp: 'store',
|
|
165
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
encode: () => {},
|
|
169
|
+
});
|
|
170
|
+
if (!initialized.ok) return initialized;
|
|
171
|
+
}
|
|
172
|
+
|
|
138
173
|
const shadows = addTypedShadowPasses(graph, topology);
|
|
139
174
|
if (!shadows.ok) return shadows;
|
|
140
175
|
|
|
@@ -163,6 +198,9 @@ function buildUrp(
|
|
|
163
198
|
const main = addTypedScenePass(graph, {
|
|
164
199
|
name: 'main',
|
|
165
200
|
color: scene.value,
|
|
201
|
+
...(reflectionFallback.value === undefined
|
|
202
|
+
? {}
|
|
203
|
+
: { colorTargets: [scene.value, reflectionFallback.value] }),
|
|
166
204
|
depth: depth.value,
|
|
167
205
|
...(msaa ? { resolve: sceneResolved.value } : {}),
|
|
168
206
|
sampled: [
|
|
@@ -179,6 +217,7 @@ function buildUrp(
|
|
|
179
217
|
extraAccesses: clusterReads,
|
|
180
218
|
...(transmissionActive ? { recordMode: 'opaque' as const } : {}),
|
|
181
219
|
...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
|
|
220
|
+
...(context.occlusion === undefined ? {} : { occlusion: context.occlusion }),
|
|
182
221
|
});
|
|
183
222
|
if (!main.ok) return main;
|
|
184
223
|
|
|
@@ -286,6 +325,7 @@ function buildUrp(
|
|
|
286
325
|
depthSample.value,
|
|
287
326
|
shadows.value.directional?.view,
|
|
288
327
|
shadows.value.spot.view,
|
|
328
|
+
clusterBuffers.value,
|
|
289
329
|
);
|
|
290
330
|
if (!volume.ok) return volume;
|
|
291
331
|
}
|
|
@@ -318,6 +358,13 @@ function buildUrp(
|
|
|
318
358
|
);
|
|
319
359
|
if (!observation.ok) return observation;
|
|
320
360
|
}
|
|
361
|
+
if (reflectionFallback.value?.sampleCount === 1) {
|
|
362
|
+
const fallbackObservation = addReflectionFallbackObservationPass(
|
|
363
|
+
graph,
|
|
364
|
+
reflectionFallback.value,
|
|
365
|
+
);
|
|
366
|
+
if (!fallbackObservation.ok) return fallbackObservation;
|
|
367
|
+
}
|
|
321
368
|
|
|
322
369
|
const post = addStandardPost(
|
|
323
370
|
context,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
GPU_BUFFER_USAGE_UNIFORM,
|
|
12
12
|
} from '../../gpu-usage';
|
|
13
13
|
import { getOrCreateHdrpBuffers, type HdrpBuffers } from '../../hdrp-buffers';
|
|
14
|
+
import { BYTES_PER_DIRECT_LIGHT_SLOT } from '../../light-buffer-layout';
|
|
14
15
|
import type { _InternalRenderPipelineContext } from '../../record/render-context';
|
|
15
16
|
import type { RenderPipelineFrame } from '../../render-pipeline';
|
|
16
17
|
import type { StandardTopologyInputValue } from './topology';
|
|
@@ -65,7 +66,7 @@ export function importStandardClusterBuffers(
|
|
|
65
66
|
const usage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
|
|
66
67
|
const lightData = graph.importBuffer(
|
|
67
68
|
'hdrp-light-data',
|
|
68
|
-
{ size: layout.lightDataSlotCount *
|
|
69
|
+
{ size: layout.lightDataSlotCount * BYTES_PER_DIRECT_LIGHT_SLOT, usage },
|
|
69
70
|
(frame) => resolveBuffers(frame, descriptor).lightDataBuffer,
|
|
70
71
|
);
|
|
71
72
|
if (!lightData.ok) return lightData;
|
|
@@ -2,12 +2,13 @@ import type { Mat4, Vec3 } from '@forgeax/engine-math';
|
|
|
2
2
|
import type {
|
|
3
3
|
DirectionalLightSnapshot,
|
|
4
4
|
PointLightSnapshot,
|
|
5
|
+
RectAreaDirectLightSnapshot,
|
|
5
6
|
SpotLightSnapshot,
|
|
6
7
|
} from '../../render-system-extract';
|
|
7
8
|
import type { StandardLightCount } from '../standard-profile';
|
|
8
9
|
|
|
9
10
|
export interface StandardLocalLightInput {
|
|
10
|
-
readonly kind: 'point' | 'spot';
|
|
11
|
+
readonly kind: 'point' | 'spot' | 'rect-area';
|
|
11
12
|
readonly position: Vec3;
|
|
12
13
|
readonly range: number;
|
|
13
14
|
/** Whether the shadow producer admitted this local light to its atlas. */
|
|
@@ -17,7 +18,7 @@ export interface StandardLocalLightInput {
|
|
|
17
18
|
* it on the POD frame prevents Forward/Deferred from rebuilding a second
|
|
18
19
|
* light list while leaving hand-authored unit fixtures source-free.
|
|
19
20
|
*/
|
|
20
|
-
readonly source?: PointLightSnapshot | SpotLightSnapshot;
|
|
21
|
+
readonly source?: PointLightSnapshot | SpotLightSnapshot | RectAreaDirectLightSnapshot;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export interface StandardLightFrame {
|
|
@@ -2,7 +2,7 @@ import { err, ok, type Result } from '@forgeax/engine-types';
|
|
|
2
2
|
import type { PreparedStandardLighting } from './prepare';
|
|
3
3
|
import type { StandardClusterTransport } from './transport';
|
|
4
4
|
|
|
5
|
-
/** A prepared frame with no local lights on a non-storage
|
|
5
|
+
/** A prepared frame with no local lights on a non-storage backend. */
|
|
6
6
|
export interface StandardNoLocalTopologyInput {
|
|
7
7
|
readonly kind: 'no-local-lights';
|
|
8
8
|
readonly prepared: PreparedStandardLighting;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
2
|
import { type RenderError, StandardClusterTransportUnavailableError } from '../../errors/render';
|
|
3
|
+
import { BYTES_PER_DIRECT_LIGHT_SLOT } from '../../light-buffer-layout';
|
|
3
4
|
import type { PreparedStandardLighting } from './prepare';
|
|
4
5
|
|
|
5
6
|
export interface StandardClusterCapabilities {
|
|
@@ -71,7 +72,7 @@ export function selectStandardClusterTransport(
|
|
|
71
72
|
occupiedClusterCount: occupiedClusterCount(prepared),
|
|
72
73
|
clusterGridBytes: prepared.layout.clusterGridU32Length * Uint32Array.BYTES_PER_ELEMENT,
|
|
73
74
|
lightIndexListBytes: prepared.membershipEntryCount * Uint32Array.BYTES_PER_ELEMENT,
|
|
74
|
-
lightDataBytes: requested *
|
|
75
|
+
lightDataBytes: requested * BYTES_PER_DIRECT_LIGHT_SLOT,
|
|
75
76
|
lightBoundsBytes: prepared.lightBounds.byteLength,
|
|
76
77
|
});
|
|
77
78
|
}
|
|
@@ -312,6 +312,7 @@ function buildStandardDeferredLane(
|
|
|
312
312
|
...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
|
|
313
313
|
passKind: 'forward',
|
|
314
314
|
...(transmissionActive ? { recordMode: 'opaque' as const } : {}),
|
|
315
|
+
...(context.occlusion === undefined ? {} : { occlusion: context.occlusion }),
|
|
315
316
|
extraAccesses: forwardExtraAccesses,
|
|
316
317
|
});
|
|
317
318
|
if (!forward.ok) return forward;
|
|
@@ -403,6 +404,7 @@ function buildStandardDeferredLane(
|
|
|
403
404
|
depthSample.value,
|
|
404
405
|
shadows.value.directional?.view,
|
|
405
406
|
shadows.value.spot.view,
|
|
407
|
+
buffers.value,
|
|
406
408
|
);
|
|
407
409
|
if (!volume.ok) return volume;
|
|
408
410
|
}
|
package/src/pipeline-builder.ts
CHANGED
|
@@ -122,6 +122,8 @@ export interface PipelineBuilderContext {
|
|
|
122
122
|
* tonemap field (M9 keeps the LDR shape; HDR variants are OOS-M9).
|
|
123
123
|
*/
|
|
124
124
|
readonly colorFormat: GPUTextureFormat;
|
|
125
|
+
/** Additional color targets for an MRT pass; the first target is colorFormat. */
|
|
126
|
+
readonly colorFormats?: readonly GPUTextureFormat[] | undefined;
|
|
125
127
|
/** Depth attachment format, or `undefined` for a color-only pass. */
|
|
126
128
|
readonly depthFormat: GPUTextureFormat | undefined;
|
|
127
129
|
/**
|
|
@@ -324,7 +326,8 @@ export function buildPipelineForMaterialShader(
|
|
|
324
326
|
// layout. The skinned variant additionally reads JOINTS_0 / WEIGHTS_0;
|
|
325
327
|
// both layouts come from the same geometry projection used by the main
|
|
326
328
|
// pass, so shadow rendering cannot silently reinterpret an 18F stream.
|
|
327
|
-
|
|
329
|
+
const attachmentFormats = ctx.colorFormats ?? colorFormatsForPassKind(passKind, ctx.colorFormat);
|
|
330
|
+
if (attachmentFormats.length === 0) {
|
|
328
331
|
// bug-20260619-csm RC-3 (AC-10): a material may supply a custom
|
|
329
332
|
// ShadowCaster pass shader that carries a fragment stage (e.g. an
|
|
330
333
|
// alpha-test cutout that calls `discard` and returns
|
|
@@ -399,7 +402,7 @@ export function buildPipelineForMaterialShader(
|
|
|
399
402
|
const forwardSpec: PipelineSpec = {
|
|
400
403
|
shader: { id, passKind, variantSet: undefined },
|
|
401
404
|
attachments: {
|
|
402
|
-
colorFormats:
|
|
405
|
+
colorFormats: attachmentFormats,
|
|
403
406
|
depthFormat: ctx.depthFormat,
|
|
404
407
|
sampleCount: (sampleCount === 4 ? 4 : 1) as 1 | 4,
|
|
405
408
|
},
|
package/src/pipeline-spec.ts
CHANGED
|
@@ -319,12 +319,23 @@ export function standardTopologyVariantSet(
|
|
|
319
319
|
topology: { readonly kind: 'no-local-lights' | 'clustered' } | undefined,
|
|
320
320
|
storageBuffer: boolean,
|
|
321
321
|
vertexColorAvailable: boolean,
|
|
322
|
+
probeBlendAvailable = false,
|
|
322
323
|
): string {
|
|
323
|
-
|
|
324
|
+
const capabilityVariantSet = standardCapabilityVariantSet(
|
|
324
325
|
topology?.kind === 'clustered',
|
|
325
326
|
storageBuffer,
|
|
326
327
|
vertexColorAvailable,
|
|
327
328
|
);
|
|
329
|
+
if (!probeBlendAvailable || !storageBuffer) return capabilityVariantSet;
|
|
330
|
+
// The canonical empty key cannot carry the clustered=true fact through
|
|
331
|
+
// resolveMaterialShaderVariantSet (an omitted cluster axis means false).
|
|
332
|
+
// Expand that base before adding the object-level Probe ABI axis so shader,
|
|
333
|
+
// group(3) bind group, and pipeline layout remain one exact variant.
|
|
334
|
+
const explicitCapabilityVariantSet =
|
|
335
|
+
capabilityVariantSet === ''
|
|
336
|
+
? 'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true'
|
|
337
|
+
: capabilityVariantSet;
|
|
338
|
+
return `${explicitCapabilityVariantSet}+PROBE_BLEND_AVAILABLE=true`;
|
|
328
339
|
}
|
|
329
340
|
|
|
330
341
|
/**
|
package/src/plugin.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Camera } from './components/camera';
|
|
|
5
5
|
import { DirectionalLight } from './components/directional-light';
|
|
6
6
|
import { Instances } from './components/instances';
|
|
7
7
|
import { Layer } from './components/layer';
|
|
8
|
+
import { LightProbe } from './components/light-probe';
|
|
8
9
|
import { Lines } from './components/lines';
|
|
9
10
|
import { MeshFilter } from './components/mesh-filter';
|
|
10
11
|
import { MeshRenderer } from './components/mesh-renderer';
|
|
@@ -12,6 +13,7 @@ import { PointLight } from './components/point-light';
|
|
|
12
13
|
import { PointLightShadow } from './components/point-light-shadow';
|
|
13
14
|
import { Points } from './components/points';
|
|
14
15
|
import { PostProcessParams } from './components/post-process-params';
|
|
16
|
+
import { RectAreaLight } from './components/rect-area-light';
|
|
15
17
|
import { SceneInstance } from './components/scene-instance';
|
|
16
18
|
import { SkyboxBackground } from './components/skybox-background';
|
|
17
19
|
import { Skylight } from './components/skylight';
|
|
@@ -30,6 +32,7 @@ const RENDER_COMPONENTS: readonly Component[] = [
|
|
|
30
32
|
DirectionalLight,
|
|
31
33
|
Instances,
|
|
32
34
|
Layer,
|
|
35
|
+
LightProbe,
|
|
33
36
|
MeshFilter,
|
|
34
37
|
MeshRenderer,
|
|
35
38
|
PointLight,
|
|
@@ -37,6 +40,7 @@ const RENDER_COMPONENTS: readonly Component[] = [
|
|
|
37
40
|
Points,
|
|
38
41
|
Lines,
|
|
39
42
|
PostProcessParams,
|
|
43
|
+
RectAreaLight,
|
|
40
44
|
SceneInstance,
|
|
41
45
|
SkyboxBackground,
|
|
42
46
|
Skylight,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RhiCaps, RhiDevice } from '@forgeax/engine-rhi';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { deriveExtendedLightingCapability } from '../extended-lighting/resources';
|
|
4
|
+
|
|
5
|
+
const device = {
|
|
6
|
+
caps: {
|
|
7
|
+
backendKind: 'null',
|
|
8
|
+
compute: true,
|
|
9
|
+
storageBuffer: true,
|
|
10
|
+
storageTexture: true,
|
|
11
|
+
rgba16floatRenderable: true,
|
|
12
|
+
samplerAliasing: true,
|
|
13
|
+
} as RhiCaps,
|
|
14
|
+
limits: {
|
|
15
|
+
maxSampledTexturesPerShaderStage: 20,
|
|
16
|
+
maxTextureDimension2D: 4096,
|
|
17
|
+
maxTextureArrayLayers: 32,
|
|
18
|
+
maxUniformBuffersPerShaderStage: 12,
|
|
19
|
+
},
|
|
20
|
+
} as unknown as RhiDevice;
|
|
21
|
+
|
|
22
|
+
describe('extended lighting capability admission', () => {
|
|
23
|
+
it('derives admission from real format, filter, array, and uniform facts', () => {
|
|
24
|
+
expect(deriveExtendedLightingCapability(device)).toEqual({
|
|
25
|
+
admitted: true,
|
|
26
|
+
topology: 'extendedLighting',
|
|
27
|
+
reason: undefined,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('rejects a device whose array or uniform limit cannot hold the contract', () => {
|
|
32
|
+
const limited = {
|
|
33
|
+
...device,
|
|
34
|
+
limits: { ...device.limits, maxTextureArrayLayers: 16, maxUniformBuffersPerShaderStage: 0 },
|
|
35
|
+
} as RhiDevice;
|
|
36
|
+
|
|
37
|
+
expect(deriveExtendedLightingCapability(limited)).toMatchObject({
|
|
38
|
+
admitted: false,
|
|
39
|
+
topology: 'extendedLighting',
|
|
40
|
+
reason: expect.stringContaining('maxTextureArrayLayers'),
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('rejects the topology when the sampled-texture limit is below the shader contract', () => {
|
|
45
|
+
const limited = {
|
|
46
|
+
...device,
|
|
47
|
+
limits: { ...device.limits, maxSampledTexturesPerShaderStage: 16 },
|
|
48
|
+
} as RhiDevice;
|
|
49
|
+
|
|
50
|
+
expect(deriveExtendedLightingCapability(limited)).toEqual({
|
|
51
|
+
admitted: false,
|
|
52
|
+
topology: 'extendedLighting',
|
|
53
|
+
reason: 'maxSampledTexturesPerShaderStage 16 < 20',
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|