@forgeax/engine-render 0.1.3 → 0.1.6
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 +130 -641
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +6 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -1
- package/dist/{gpu-driven/view-reference.d.ts → __tests__/gpu-driven-view-reference.d.ts} +4 -4
- package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -1
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
- package/dist/{renderer/backend-selection.d.ts → assembly/backend-contract.d.ts} +15 -4
- package/dist/assembly/backend-contract.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +207 -0
- package/dist/assembly/factory.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +84 -0
- package/dist/assembly/host-contract.d.ts.map +1 -0
- package/dist/{renderer → assembly}/material/assembly.d.ts +1 -2
- package/dist/{renderer → assembly}/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-projection.d.ts +30 -0
- package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
- package/dist/authoring.d.ts +10 -11
- package/dist/authoring.d.ts.map +1 -1
- package/dist/authoring.mjs +25 -3
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-CQXZC5XI.mjs +182 -0
- package/dist/chunk-CQXZC5XI.mjs.map +1 -0
- package/dist/chunk-QC4VW3XJ.mjs +79 -0
- package/dist/chunk-QC4VW3XJ.mjs.map +1 -0
- package/dist/chunk-SCRSAK5B.mjs +480 -0
- package/dist/chunk-SCRSAK5B.mjs.map +1 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
- package/dist/components/glyph-text.d.ts +1 -1
- package/dist/components/glyph-text.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +1 -1
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +7 -7
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/scene-instance.d.ts +11 -11
- package/dist/components/skybox-background.d.ts +56 -0
- package/dist/components/skybox-background.d.ts.map +1 -0
- package/dist/components/skylight.d.ts +55 -0
- package/dist/components/skylight.d.ts.map +1 -0
- package/dist/components/sprite-animation.d.ts +2 -3
- package/dist/components/sprite-animation.d.ts.map +1 -1
- package/dist/components/sprite-instances.d.ts +1 -1
- package/dist/components/sprite-playback-mode.d.ts +6 -1
- package/dist/components/sprite-playback-mode.d.ts.map +1 -1
- package/dist/components/sprite-region-override.d.ts +2 -3
- package/dist/components/sprite-region-override.d.ts.map +1 -1
- package/dist/components/tile-layer.d.ts +5 -0
- package/dist/components/tile-layer.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +18 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +27008 -4
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/debug-draw-glue.d.ts +2 -53
- package/dist/debug-draw-glue.d.ts.map +1 -1
- package/dist/device/device-scope.d.ts +83 -0
- package/dist/device/device-scope.d.ts.map +1 -0
- package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
- package/dist/device/gpu-residency.d.ts.map +1 -0
- package/dist/device/resource-types.d.ts +8 -0
- package/dist/device/resource-types.d.ts.map +1 -0
- package/dist/engine-metrics.d.ts +2 -2
- package/dist/engine-metrics.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +28 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +249 -258
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts +19 -0
- package/dist/features/fullscreen.d.ts.map +1 -0
- package/dist/features/host.d.ts +32 -26
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/morph/morph-feature.d.ts +39 -5
- package/dist/features/morph/morph-feature.d.ts.map +1 -1
- package/dist/features/plan.d.ts +182 -0
- package/dist/features/plan.d.ts.map +1 -0
- package/dist/features/prepared-gpu-work.d.ts +21 -17
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -1
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +11 -21
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts +2 -2
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +4 -7
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +2 -2
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/render-graph-resources.d.ts +6 -6
- package/dist/features/render-graph-resources.d.ts.map +1 -1
- package/dist/features/targets.d.ts +5 -5
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +11 -190
- package/dist/features/types.d.ts.map +1 -1
- package/dist/features/vocabulary.d.ts +14 -0
- package/dist/features/vocabulary.d.ts.map +1 -0
- package/dist/fullscreen-post-process-pass.d.ts +4 -25
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +3 -2
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +6 -75
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +13 -112
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +10 -66
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-resource.d.ts +3 -3
- package/dist/gpu-scene-schema.d.ts +1 -94
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +7 -33
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -53
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +74 -180
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +1 -1
- package/dist/index.d.ts +13 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +165 -3
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +69 -0
- package/dist/inspection-types.d.ts.map +1 -0
- package/dist/instance-buffer-cache.d.ts +1 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/internal.d.ts +1 -73
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +1 -43
- package/dist/internal.mjs.map +1 -1
- package/dist/lifecycle.d.ts +36 -2
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/materials.d.ts +0 -3
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +0 -1
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +75 -29
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +5 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +31 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
- package/dist/pipeline/standard-profile.d.ts +40 -0
- package/dist/pipeline/standard-profile.d.ts.map +1 -0
- package/dist/pipeline-builder.d.ts +3 -3
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec-types.d.ts +24 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -0
- package/dist/pipeline-spec.d.ts +16 -155
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts +1 -14
- package/dist/plugin.d.ts.map +1 -1
- package/dist/post-process-errors.d.ts +18 -18
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +7 -73
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +44 -44
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -38
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +64 -52
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +3 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +5 -4
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +90 -59
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +28 -3
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +276 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +235 -0
- package/dist/record/render-context.d.ts.map +1 -0
- package/dist/record/shadow-pass.d.ts +15 -88
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +29 -7
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +3 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/render-contract.d.ts +416 -0
- package/dist/render-contract.d.ts.map +1 -0
- package/dist/render-data.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +14 -362
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +25 -64
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +107 -338
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +21 -713
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +58 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +105 -0
- package/dist/scene/render-scene.d.ts.map +1 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +22 -3
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +2 -4
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +14 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -0
- package/dist/systems/transparent-sort-config.d.ts +23 -2
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +4 -3
- package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +2 -4
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +3 -3
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
- package/src/__tests__/callback-inference.test-d.ts +6 -3
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
- package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
- package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
- package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
- package/src/__tests__/factory-contract.integration.test.ts +158 -209
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
- package/src/__tests__/frame-observation.contract.test.ts +17 -8
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
- package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +9 -16
- package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
- package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
- package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
- package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
- package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
- package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
- package/src/__tests__/gpu-scene.unit.test.ts +10 -24
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
- package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
- package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
- package/src/__tests__/material-cooked-projection.unit.test.ts +2 -51
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +4 -23
- package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
- package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
- package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
- package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
- package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
- package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
- package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
- package/src/__tests__/profiler-default-off.test.ts +1 -1
- package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
- package/src/__tests__/profiler-phase-integration.test.ts +5 -13
- package/src/__tests__/profiler-phase-token.test.ts +3 -8
- package/src/__tests__/public-surface.test-d.ts +65 -3
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
- package/src/__tests__/render-error-code-owner.test-d.ts +18 -23
- package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
- package/src/__tests__/render-error-exhaustive.test-d.ts +8 -1
- package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
- package/src/__tests__/render-feature-context.test-d.ts +16 -40
- package/src/__tests__/render-feature-contract.test-d.ts +9 -18
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
- package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
- package/src/__tests__/render-feature-plan.test-d.ts +161 -0
- package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
- package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
- package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
- package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
- package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
- package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
- package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
- package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
- package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
- package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
- package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
- package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
- package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +46 -50
- package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
- package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
- package/src/__tests__/ssao-config.unit.test.ts +36 -0
- package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
- package/src/__tests__/standard-descriptors.test-d.ts +22 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
- package/src/__tests__/surface-configuration.unit.test.ts +1 -2
- package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
- package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
- package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
- package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
- package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
- package/src/__tests__/visibility-extract.integration.test.ts +20 -11
- package/src/__tests__/visibility-extract.perf.test.ts +66 -32
- package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
- package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
- package/src/__tests__/visibility-instances.integration.test.ts +7 -11
- package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
- package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
- package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
- package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
- package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
- package/src/__tests__/vocabulary.unit.test.ts +1 -1
- package/src/assembly/backend-contract.ts +57 -0
- package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1709 -2693
- package/src/assembly/host-contract.ts +101 -0
- package/src/{renderer → assembly}/material/assembly.ts +1 -3
- package/src/assembly/material/pipeline-projection.ts +63 -0
- package/src/authoring.ts +14 -22
- package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
- package/src/components/glyph-text.ts +3 -2
- package/src/components/index.ts +7 -9
- package/src/components/instances.ts +4 -5
- package/src/components/light-helpers.ts +1 -1
- package/src/components/mesh-filter.ts +11 -10
- package/src/components/post-process-params.ts +3 -3
- package/src/components/scene-instance.ts +12 -12
- package/src/components/skybox-background.ts +103 -0
- package/src/components/{environment.ts → skylight.ts} +2 -111
- package/src/components/sprite-animation.ts +3 -4
- package/src/components/sprite-instances.ts +2 -2
- package/src/components/sprite-playback-mode.ts +7 -1
- package/src/components/sprite-region-override.ts +2 -3
- package/src/components/tile-layer.ts +8 -2
- package/src/construct-renderer.ts +67 -4
- package/src/debug-draw-glue.ts +8 -129
- package/src/device/device-scope.ts +306 -0
- package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
- package/src/device/resource-types.ts +20 -0
- package/src/engine-metrics.ts +12 -19
- package/src/errors/recover.ts +45 -3
- package/src/errors/render.ts +357 -460
- package/src/features/fullscreen.ts +46 -0
- package/src/features/host.ts +575 -309
- package/src/features/morph/morph-feature.ts +195 -105
- package/src/features/plan.ts +447 -0
- package/src/features/prepared-gpu-work.ts +72 -15
- package/src/features/prepared-graphics-store.ts +20 -6
- package/src/features/prepared-graphics.ts +12 -71
- package/src/features/render-graph-compute.ts +14 -5
- package/src/features/render-graph-contribution.ts +43 -63
- package/src/features/render-graph-raster.ts +11 -6
- package/src/features/render-graph-resources.ts +25 -23
- package/src/features/targets.ts +8 -21
- package/src/features/types.ts +39 -227
- package/src/features/vocabulary.ts +24 -0
- package/src/fullscreen-post-process-pass.ts +14 -57
- package/src/glyph-text-layout-system.ts +70 -96
- package/src/gpu-driven/batch-topology.ts +24 -202
- package/src/gpu-driven/production-raster.ts +93 -1108
- package/src/gpu-driven/view-gpu.ts +46 -192
- package/src/gpu-resource.ts +4 -4
- package/src/gpu-scene-schema.ts +11 -99
- package/src/gpu-scene.ts +231 -364
- package/src/hdrp-buffers.ts +12 -221
- package/src/ibl/IblPipelineCache.ts +471 -711
- package/src/ibl/skylight-bind-group.ts +4 -4
- package/src/index.ts +58 -217
- package/src/inspection-types.ts +76 -0
- package/src/instance-buffer-cache.ts +1 -29
- package/src/internal.ts +6 -85
- package/src/lifecycle.ts +64 -19
- package/src/materials.ts +7 -29
- package/src/mesh-material-bindings.ts +0 -1
- package/src/pbr-pipeline.ts +434 -53
- package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
- package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
- package/src/pipeline/standard-profile.ts +65 -0
- package/src/pipeline-builder.ts +60 -64
- package/src/pipeline-spec-types.ts +28 -0
- package/src/pipeline-spec.ts +72 -609
- package/src/plugin.ts +3 -75
- package/src/post-process-errors.ts +31 -33
- package/src/prepare/prepared-graphics-resolver.ts +5 -4
- package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
- package/src/record/frame-lighting.ts +74 -195
- package/src/record/frame-snapshot.ts +45 -60
- package/src/record/frame-targets.ts +8 -243
- package/src/record/frame.ts +509 -796
- package/src/record/helpers.ts +6 -11
- package/src/record/main-pass-geometry.ts +106 -147
- package/src/record/main-pass-material.ts +517 -190
- package/src/record/main-pass-sprite-draws.ts +198 -117
- package/src/record/main-pass.ts +162 -143
- package/src/record/mesh-ssbo.ts +517 -38
- package/src/record/render-context.ts +364 -0
- package/src/record/shadow-pass.ts +138 -1838
- package/src/record/skybox-post-pass.ts +12 -14
- package/src/record/typed-frame-graph.ts +215 -254
- package/src/record/view-ubo.ts +6 -37
- package/src/render-contract.ts +571 -0
- package/src/render-data.ts +3 -3
- package/src/render-graph-primitives.ts +76 -851
- package/src/render-pipeline.ts +104 -188
- package/src/render-system-extract.ts +1048 -1729
- package/src/render-system.ts +330 -1957
- package/src/scene/render-scene-types.ts +64 -0
- package/src/scene/render-scene.ts +1032 -0
- package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
- package/src/ssao-buffers.ts +167 -8
- package/src/systems/skin-palette-allocator.ts +21 -64
- package/src/systems/skin-palette-types.ts +14 -0
- package/src/systems/transparent-sort-config.ts +25 -3
- package/src/tilemap-chunk-extract-system.ts +53 -70
- package/src/typed-render-graph-primitives.ts +35 -24
- package/src/typed-shadow-passes.ts +26 -56
- package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
- package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
- package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
- package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
- package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
- package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
- package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
- package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
- package/dist/__tests__/camera-temporal.test.d.ts +0 -2
- package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
- package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
- package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
- package/dist/__tests__/environment-inspection.test.d.ts +0 -2
- package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
- package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
- package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
- package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
- package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
- package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
- package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
- package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
- package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
- package/dist/__tests__/materials.unit.test.d.ts +0 -2
- package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
- package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
- package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
- package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/plugin.test.d.ts +0 -2
- package/dist/__tests__/plugin.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
- package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
- package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
- package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
- package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
- package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
- package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
- package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
- package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
- package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
- package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
- package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
- package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
- package/dist/chunk-33UF5SAO.mjs +0 -7397
- package/dist/chunk-33UF5SAO.mjs.map +0 -1
- package/dist/chunk-A5QCJSNL.mjs +0 -29913
- package/dist/chunk-A5QCJSNL.mjs.map +0 -1
- package/dist/chunk-JMSB7AR4.mjs +0 -3
- package/dist/chunk-JMSB7AR4.mjs.map +0 -1
- package/dist/chunk-LXNGO6AO.mjs +0 -569
- package/dist/chunk-LXNGO6AO.mjs.map +0 -1
- package/dist/chunk-QRXPSX4X.mjs +0 -659
- package/dist/chunk-QRXPSX4X.mjs.map +0 -1
- package/dist/chunk-YAKEQPWO.mjs +0 -1439
- package/dist/chunk-YAKEQPWO.mjs.map +0 -1
- package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
- package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
- package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
- package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
- package/dist/components/__tests__/fog.test-d.d.ts +0 -2
- package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
- package/dist/components/__tests__/fog.test.d.ts +0 -2
- package/dist/components/__tests__/fog.test.d.ts.map +0 -1
- package/dist/components/atmosphere.d.ts +0 -18
- package/dist/components/atmosphere.d.ts.map +0 -1
- package/dist/components/environment.d.ts +0 -116
- package/dist/components/environment.d.ts.map +0 -1
- package/dist/deferred-lighting.d.ts +0 -13
- package/dist/deferred-lighting.d.ts.map +0 -1
- package/dist/dynamic-texture-store.d.ts +0 -42
- package/dist/dynamic-texture-store.d.ts.map +0 -1
- package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
- package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
- package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
- package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/generation.test.d.ts +0 -2
- package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
- package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
- package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
- package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
- package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
- package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
- package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
- package/dist/environment/__tests__/readiness.test.d.ts +0 -2
- package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
- package/dist/environment/__tests__/recovery.test.d.ts +0 -2
- package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
- package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
- package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
- package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
- package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/signature.test.d.ts +0 -2
- package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
- package/dist/environment/descriptors.d.ts +0 -2
- package/dist/environment/descriptors.d.ts.map +0 -1
- package/dist/environment/extracted-environment.d.ts +0 -53
- package/dist/environment/extracted-environment.d.ts.map +0 -1
- package/dist/environment/generation.d.ts +0 -62
- package/dist/environment/generation.d.ts.map +0 -1
- package/dist/environment/gpu-bundle.d.ts +0 -23
- package/dist/environment/gpu-bundle.d.ts.map +0 -1
- package/dist/environment/graph.d.ts +0 -108
- package/dist/environment/graph.d.ts.map +0 -1
- package/dist/environment/inspection.d.ts +0 -48
- package/dist/environment/inspection.d.ts.map +0 -1
- package/dist/environment/lifecycle.d.ts +0 -22
- package/dist/environment/lifecycle.d.ts.map +0 -1
- package/dist/environment/readiness.d.ts +0 -29
- package/dist/environment/readiness.d.ts.map +0 -1
- package/dist/environment/signature.d.ts +0 -70
- package/dist/environment/signature.d.ts.map +0 -1
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
- package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
- package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
- package/dist/extract/directional-csm.d.ts +0 -129
- package/dist/extract/directional-csm.d.ts.map +0 -1
- package/dist/extract/index.d.ts +0 -5
- package/dist/extract/index.d.ts.map +0 -1
- package/dist/extract/material-interface.d.ts +0 -56
- package/dist/extract/material-interface.d.ts.map +0 -1
- package/dist/extract/schema-readers.d.ts +0 -20
- package/dist/extract/schema-readers.d.ts.map +0 -1
- package/dist/features/graph-contribution.d.ts +0 -64
- package/dist/features/graph-contribution.d.ts.map +0 -1
- package/dist/features/index.d.ts +0 -21
- package/dist/features/index.d.ts.map +0 -1
- package/dist/features/morph/index.d.ts +0 -3
- package/dist/features/morph/index.d.ts.map +0 -1
- package/dist/features/morph/morph-bounds.d.ts +0 -42
- package/dist/features/morph/morph-bounds.d.ts.map +0 -1
- package/dist/features/scene-temporal.d.ts +0 -45
- package/dist/features/scene-temporal.d.ts.map +0 -1
- package/dist/features/taa-resolve.d.ts +0 -21
- package/dist/features/taa-resolve.d.ts.map +0 -1
- package/dist/frame-chain.d.ts +0 -14
- package/dist/frame-chain.d.ts.map +0 -1
- package/dist/gpu-driven/view-reference.d.ts.map +0 -1
- package/dist/gpu-resource-store.d.ts.map +0 -1
- package/dist/hdrp-cluster-membership.d.ts +0 -2
- package/dist/hdrp-cluster-membership.d.ts.map +0 -1
- package/dist/hdrp-pipeline.d.ts +0 -36
- package/dist/hdrp-pipeline.d.ts.map +0 -1
- package/dist/ibl/cubemap-projection.d.ts +0 -23
- package/dist/ibl/cubemap-projection.d.ts.map +0 -1
- package/dist/ibl/face-uniforms.d.ts +0 -65
- package/dist/ibl/face-uniforms.d.ts.map +0 -1
- package/dist/mesh-update-errors.d.ts +0 -71
- package/dist/mesh-update-errors.d.ts.map +0 -1
- package/dist/mipmap-generator.d.ts +0 -39
- package/dist/mipmap-generator.d.ts.map +0 -1
- package/dist/param-schema-projection-census.d.ts +0 -18
- package/dist/param-schema-projection-census.d.ts.map +0 -1
- package/dist/persistent-render-scene.d.ts +0 -158
- package/dist/persistent-render-scene.d.ts.map +0 -1
- package/dist/pipeline/index.d.ts +0 -11
- package/dist/pipeline/index.d.ts.map +0 -1
- package/dist/pipeline-errors.d.ts +0 -110
- package/dist/pipeline-errors.d.ts.map +0 -1
- package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
- package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
- package/dist/prepare/index.d.ts +0 -4
- package/dist/prepare/index.d.ts.map +0 -1
- package/dist/prepare/schema-readers.d.ts +0 -11
- package/dist/prepare/schema-readers.d.ts.map +0 -1
- package/dist/record/__tests__/environment-record.test.d.ts +0 -2
- package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
- package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
- package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
- package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
- package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
- package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
- package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
- package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
- package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
- package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
- package/dist/record/frame-observation.d.ts +0 -38
- package/dist/record/frame-observation.d.ts.map +0 -1
- package/dist/record/index.d.ts +0 -15
- package/dist/record/index.d.ts.map +0 -1
- package/dist/record/main-pass-skin.d.ts +0 -46
- package/dist/record/main-pass-skin.d.ts.map +0 -1
- package/dist/record/main-pass-sprite.d.ts +0 -69
- package/dist/record/main-pass-sprite.d.ts.map +0 -1
- package/dist/record/material-payload.d.ts +0 -43
- package/dist/record/material-payload.d.ts.map +0 -1
- package/dist/record/material-slot-plan.d.ts +0 -26
- package/dist/record/material-slot-plan.d.ts.map +0 -1
- package/dist/record/membership-timing.d.ts +0 -232
- package/dist/record/membership-timing.d.ts.map +0 -1
- package/dist/record/shadow-caster-uniform.d.ts +0 -8
- package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
- package/dist/record/shadow-submit-mode.d.ts +0 -66
- package/dist/record/shadow-submit-mode.d.ts.map +0 -1
- package/dist/render-dispatch-membership.d.ts +0 -47
- package/dist/render-dispatch-membership.d.ts.map +0 -1
- package/dist/render-pipeline-context.d.ts +0 -289
- package/dist/render-pipeline-context.d.ts.map +0 -1
- package/dist/render-pipeline-target.d.ts +0 -16
- package/dist/render-pipeline-target.d.ts.map +0 -1
- package/dist/render-scene-projection.d.ts +0 -174
- package/dist/render-scene-projection.d.ts.map +0 -1
- package/dist/render-system-fold.d.ts +0 -266
- package/dist/render-system-fold.d.ts.map +0 -1
- package/dist/renderer/asset-service.d.ts +0 -10
- package/dist/renderer/asset-service.d.ts.map +0 -1
- package/dist/renderer/backend-selection.d.ts.map +0 -1
- package/dist/renderer/environment-classify.d.ts +0 -6
- package/dist/renderer/environment-classify.d.ts.map +0 -1
- package/dist/renderer/environment-error.d.ts +0 -13
- package/dist/renderer/environment-error.d.ts.map +0 -1
- package/dist/renderer/material/pipeline-projection.d.ts +0 -91
- package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
- package/dist/renderer/renderer-factory.d.ts +0 -283
- package/dist/renderer/renderer-factory.d.ts.map +0 -1
- package/dist/renderer.d.ts +0 -771
- package/dist/renderer.d.ts.map +0 -1
- package/dist/scene-utils/collect-subtree.d.ts +0 -11
- package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
- package/dist/ssao-data.d.ts +0 -34
- package/dist/ssao-data.d.ts.map +0 -1
- package/dist/surface-format.d.ts +0 -10
- package/dist/surface-format.d.ts.map +0 -1
- package/dist/taa-history-store.d.ts +0 -88
- package/dist/taa-history-store.d.ts.map +0 -1
- package/dist/temporal-coverage.d.ts +0 -35
- package/dist/temporal-coverage.d.ts.map +0 -1
- package/dist/temporal-frame-transaction.d.ts +0 -92
- package/dist/temporal-frame-transaction.d.ts.map +0 -1
- package/dist/temporal-inspection.d.ts +0 -57
- package/dist/temporal-inspection.d.ts.map +0 -1
- package/dist/temporal-view.d.ts +0 -43
- package/dist/temporal-view.d.ts.map +0 -1
- package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
- package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
- package/dist/urp-pipeline.d.ts +0 -4
- package/dist/urp-pipeline.d.ts.map +0 -1
- package/src/__tests__/analytic-sky-contract.test.ts +0 -27
- package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
- package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
- package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
- package/src/__tests__/backend-selection.integration.test.ts +0 -11
- package/src/__tests__/camera-temporal.test-d.ts +0 -8
- package/src/__tests__/camera-temporal.test.ts +0 -188
- package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
- package/src/__tests__/environment-inspection.test.ts +0 -45
- package/src/__tests__/fog-ai-user.fixture.ts +0 -350
- package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
- package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
- package/src/__tests__/fog-inspection.integration.test.ts +0 -127
- package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
- package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
- package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
- package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
- package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
- package/src/__tests__/fog-temporal.integration.test.ts +0 -115
- package/src/__tests__/frame-chain.unit.test.ts +0 -26
- package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
- package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
- package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
- package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
- package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
- package/src/__tests__/materials.unit.test.ts +0 -25
- package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
- package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
- package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
- package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
- package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
- package/src/__tests__/plugin.test.ts +0 -25
- package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
- package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
- package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
- package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
- package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
- package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
- package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
- package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
- package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
- package/src/__tests__/render-feature-order.unit.test.ts +0 -66
- package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
- package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
- package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
- package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
- package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
- package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
- package/src/__tests__/taa-history-store.unit.test.ts +0 -196
- package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
- package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
- package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
- package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
- package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
- package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
- package/src/components/__tests__/atmosphere-red.test.ts +0 -51
- package/src/components/__tests__/atmosphere.test.ts +0 -79
- package/src/components/__tests__/fog.test-d.ts +0 -49
- package/src/components/__tests__/fog.test.ts +0 -60
- package/src/components/atmosphere.ts +0 -64
- package/src/deferred-lighting.ts +0 -92
- package/src/dynamic-texture-store.ts +0 -111
- package/src/environment/README.md +0 -76
- package/src/environment/__tests__/failure-injection.test.ts +0 -50
- package/src/environment/__tests__/generation-red.test.ts +0 -64
- package/src/environment/__tests__/generation.test.ts +0 -37
- package/src/environment/__tests__/graph-transaction.test.ts +0 -85
- package/src/environment/__tests__/inspection-red.test.ts +0 -53
- package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
- package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
- package/src/environment/__tests__/readiness.test.ts +0 -42
- package/src/environment/__tests__/recovery.test.ts +0 -62
- package/src/environment/__tests__/resize-dispose.test.ts +0 -30
- package/src/environment/__tests__/signature-red.test.ts +0 -45
- package/src/environment/__tests__/signature.test.ts +0 -60
- package/src/environment/descriptors.ts +0 -7
- package/src/environment/extracted-environment.ts +0 -239
- package/src/environment/generation.ts +0 -158
- package/src/environment/gpu-bundle.ts +0 -144
- package/src/environment/graph.ts +0 -588
- package/src/environment/inspection.ts +0 -107
- package/src/environment/lifecycle.ts +0 -124
- package/src/environment/readiness.ts +0 -76
- package/src/environment/signature.ts +0 -185
- package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
- package/src/extract/__tests__/environment-source.test.ts +0 -105
- package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
- package/src/extract/directional-csm.ts +0 -959
- package/src/extract/index.ts +0 -10
- package/src/extract/material-interface.ts +0 -604
- package/src/extract/schema-readers.ts +0 -27
- package/src/features/graph-contribution.ts +0 -577
- package/src/features/index.ts +0 -100
- package/src/features/morph/index.ts +0 -24
- package/src/features/morph/morph-bounds.ts +0 -123
- package/src/features/scene-temporal.ts +0 -274
- package/src/features/taa-resolve.ts +0 -244
- package/src/frame-chain.ts +0 -21
- package/src/hdrp-cluster-membership.ts +0 -70
- package/src/ibl/cubemap-projection.ts +0 -60
- package/src/ibl/face-uniforms.ts +0 -150
- package/src/mesh-update-errors.ts +0 -113
- package/src/mipmap-generator.ts +0 -244
- package/src/param-schema-projection-census.ts +0 -73
- package/src/persistent-render-scene.ts +0 -1752
- package/src/pipeline/index.ts +0 -40
- package/src/pipeline-errors.ts +0 -172
- package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
- package/src/prepare/index.ts +0 -8
- package/src/prepare/schema-readers.ts +0 -20
- package/src/record/__tests__/environment-record.test.ts +0 -35
- package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
- package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
- package/src/record/__tests__/render-submission.integration.test.ts +0 -76
- package/src/record/__tests__/render-submission.perf.test.ts +0 -141
- package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
- package/src/record/frame-observation.ts +0 -122
- package/src/record/index.ts +0 -15
- package/src/record/main-pass-skin.ts +0 -51
- package/src/record/main-pass-sprite.ts +0 -166
- package/src/record/material-payload.ts +0 -292
- package/src/record/material-slot-plan.ts +0 -68
- package/src/record/membership-timing.ts +0 -1012
- package/src/record/shadow-caster-uniform.ts +0 -37
- package/src/record/shadow-submit-mode.ts +0 -277
- package/src/render-dispatch-membership.ts +0 -155
- package/src/render-pipeline-context.ts +0 -332
- package/src/render-pipeline-target.ts +0 -96
- package/src/render-scene-projection.ts +0 -1738
- package/src/render-system-fold.ts +0 -531
- package/src/renderer/asset-service.ts +0 -32
- package/src/renderer/backend-selection.ts +0 -121
- package/src/renderer/environment-classify.ts +0 -30
- package/src/renderer/environment-error.ts +0 -19
- package/src/renderer/material/pipeline-projection.ts +0 -140
- package/src/renderer.ts +0 -940
- package/src/scene-utils/collect-subtree.ts +0 -40
- package/src/ssao-data.ts +0 -106
- package/src/surface-format.ts +0 -37
- package/src/taa-history-store.ts +0 -429
- package/src/temporal-coverage.ts +0 -106
- package/src/temporal-frame-transaction.ts +0 -301
- package/src/temporal-inspection.ts +0 -194
- package/src/temporal-view.ts +0 -174
- package/src/tilemap/resolve-tileset-runtime.ts +0 -72
|
@@ -1,959 +0,0 @@
|
|
|
1
|
-
import { type Mat4, mat4, type Vec3, vec3 } from '@forgeax/engine-math';
|
|
2
|
-
import { ShadowInvalidConfigError } from '../errors/render';
|
|
3
|
-
|
|
4
|
-
const DEFAULT_PCF_KERNEL_SIZE = 3;
|
|
5
|
-
|
|
6
|
-
export interface CsmCameraData {
|
|
7
|
-
readonly world: Float32Array;
|
|
8
|
-
readonly fov: number;
|
|
9
|
-
readonly aspect: number;
|
|
10
|
-
readonly near: number;
|
|
11
|
-
readonly far: number;
|
|
12
|
-
readonly projection: 'perspective' | 'orthographic';
|
|
13
|
-
readonly orthoLeft: number;
|
|
14
|
-
readonly orthoRight: number;
|
|
15
|
-
readonly orthoBottom: number;
|
|
16
|
-
readonly orthoTop: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface DirectionalCsmConfig {
|
|
20
|
-
readonly cascadeCount: number;
|
|
21
|
-
readonly splitLambda: number;
|
|
22
|
-
readonly cascadeBlend: number;
|
|
23
|
-
readonly mapSize: number;
|
|
24
|
-
readonly shadowDistance: number;
|
|
25
|
-
/** Optional only for old internal callers; DirectionalLight supplies it. */
|
|
26
|
-
readonly pcfKernelSize?: number;
|
|
27
|
-
/** @internal Collect producer-owned per-candidate decisions for RHI evidence. */
|
|
28
|
-
readonly collectCandidateDecisions?: boolean;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface CascadeRasterViewport {
|
|
32
|
-
readonly x: number;
|
|
33
|
-
readonly y: number;
|
|
34
|
-
readonly w: number;
|
|
35
|
-
readonly h: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface CascadeVolume {
|
|
39
|
-
readonly cascadeIndex: number;
|
|
40
|
-
readonly revision: number;
|
|
41
|
-
readonly lightViewProj: Float32Array;
|
|
42
|
-
readonly receiverViewDepth: readonly [number, number];
|
|
43
|
-
readonly receiverLightBounds: Float32Array;
|
|
44
|
-
readonly clipLightBounds: Float32Array;
|
|
45
|
-
/** Raster bounds are the exact clip array consumed by the matrix fit. */
|
|
46
|
-
readonly rasterLightBounds: Float32Array;
|
|
47
|
-
readonly depthLightRange: readonly [number, number];
|
|
48
|
-
/** Conservative world-space AABB used by static and dynamic broadphase owners. */
|
|
49
|
-
readonly casterBroadphaseWorldAabb: Float32Array;
|
|
50
|
-
readonly rasterViewport: CascadeRasterViewport;
|
|
51
|
-
/** Stable X/Y extent; casters never enlarge this receiver-driven domain. */
|
|
52
|
-
readonly stableExtent: number;
|
|
53
|
-
/** Receiver sphere center before texel-grid snapping. */
|
|
54
|
-
readonly unsnappedCenter: readonly [number, number];
|
|
55
|
-
readonly snappedCenter: readonly [number, number];
|
|
56
|
-
readonly halfExtent: number;
|
|
57
|
-
readonly worldUnitsPerTexel: number;
|
|
58
|
-
readonly guardBandTexels: number;
|
|
59
|
-
/** Candidate indices are stable before main-view culling. */
|
|
60
|
-
readonly casterRenderableIndices: Uint32Array;
|
|
61
|
-
/** Optional complete CPU decision stream, enabled only for debug capture. */
|
|
62
|
-
readonly candidateDecisions?: readonly DirectionalCsmCandidateDecision[];
|
|
63
|
-
readonly unboundedFallback: readonly DirectionalCsmFallback[];
|
|
64
|
-
readonly unboundedFallbackCount: number;
|
|
65
|
-
/** Historical whole-frustum away-light extent retained for fallback casters. */
|
|
66
|
-
readonly lightSpaceMinZFull: number;
|
|
67
|
-
/** Historical whole-frustum toward-light reach retained for fallback casters. */
|
|
68
|
-
readonly lightSpaceMaxZFull: number;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Compatibility name for existing record and debug consumers. */
|
|
72
|
-
export type DirectionalCsmCascadePlan = CascadeVolume;
|
|
73
|
-
|
|
74
|
-
export interface DirectionalCsmFallback {
|
|
75
|
-
readonly renderableIndex: number;
|
|
76
|
-
readonly reason: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface DirectionalCsmCasterCandidate {
|
|
80
|
-
readonly renderableIndex: number;
|
|
81
|
-
readonly worldId: number;
|
|
82
|
-
readonly entityKey: number;
|
|
83
|
-
readonly worldAabb: Float32Array | null;
|
|
84
|
-
readonly bounded: boolean;
|
|
85
|
-
readonly shadowCaster: boolean;
|
|
86
|
-
readonly fallbackReason?: string;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface DirectionalCsmCandidateSource {
|
|
90
|
-
readonly renderableIndex: number;
|
|
91
|
-
readonly worldId: number;
|
|
92
|
-
readonly entityKey: number;
|
|
93
|
-
readonly localAabb?: Float32Array | undefined;
|
|
94
|
-
readonly transformWorld: Float32Array;
|
|
95
|
-
readonly instanceTransforms?: Float32Array | undefined;
|
|
96
|
-
/** Skin/morph bounds are feature-owned; do not infer them from a static mesh AABB. */
|
|
97
|
-
readonly featureOwnedBoundsUnavailable?: boolean;
|
|
98
|
-
readonly shadowCaster: boolean;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export interface DirectionalCsmCandidateDecision {
|
|
102
|
-
readonly renderableIndex: number;
|
|
103
|
-
readonly worldId: number;
|
|
104
|
-
readonly entityKey: number;
|
|
105
|
-
readonly selected: boolean;
|
|
106
|
-
readonly reason: string;
|
|
107
|
-
readonly lightSpaceBounds?: Float32Array;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Optional persistent-scene broadphase owner. Returned indices address the
|
|
112
|
-
* stable candidate domain supplied to the CSM builder; the builder still owns
|
|
113
|
-
* the exact light-space membership test.
|
|
114
|
-
*/
|
|
115
|
-
export type DirectionalCsmCandidateBroadphase = (worldAabb: Float32Array) => readonly number[];
|
|
116
|
-
|
|
117
|
-
export interface CascadeVolumeSet {
|
|
118
|
-
readonly revision: number;
|
|
119
|
-
readonly volumes: readonly CascadeVolume[];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface DirectionalCsmResult extends CascadeVolumeSet {
|
|
123
|
-
readonly lightViewProj: Float32Array[];
|
|
124
|
-
readonly splitPlanes: Float32Array;
|
|
125
|
-
readonly cascadeCount: number;
|
|
126
|
-
readonly cascadeBlend: number;
|
|
127
|
-
readonly shadowMapSize: number;
|
|
128
|
-
readonly cascades: readonly DirectionalCsmCascadePlan[];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function directionalCascadeRasterViewport(
|
|
132
|
-
cascadeIndex: number,
|
|
133
|
-
cascadeCount: number,
|
|
134
|
-
mapSize: number,
|
|
135
|
-
): CascadeRasterViewport {
|
|
136
|
-
const count = Math.max(1, Math.min(4, Math.round(cascadeCount)));
|
|
137
|
-
const index = Math.max(0, Math.min(count - 1, Math.round(cascadeIndex)));
|
|
138
|
-
const tileSize = Math.max(1, mapSize);
|
|
139
|
-
const tilesPerSide = Math.ceil(Math.sqrt(count));
|
|
140
|
-
return {
|
|
141
|
-
x: (index % tilesPerSide) * tileSize,
|
|
142
|
-
y: Math.floor(index / tilesPerSide) * tileSize,
|
|
143
|
-
w: tileSize,
|
|
144
|
-
h: tileSize,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/** Exact depth-atlas dimensions for the raster viewport layout. */
|
|
149
|
-
export function directionalCascadeAtlasSize(
|
|
150
|
-
cascadeCount: number,
|
|
151
|
-
mapSize: number,
|
|
152
|
-
): { readonly width: number; readonly height: number } {
|
|
153
|
-
const count = Math.max(1, Math.min(4, Math.round(cascadeCount)));
|
|
154
|
-
const tileSize = Math.max(1, mapSize);
|
|
155
|
-
const tilesPerSide = Math.ceil(Math.sqrt(count));
|
|
156
|
-
return {
|
|
157
|
-
width: tilesPerSide * tileSize,
|
|
158
|
-
height: Math.ceil(count / tilesPerSide) * tileSize,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
interface Sphere {
|
|
163
|
-
readonly center: Vec3;
|
|
164
|
-
readonly radius: number;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function dot(a: Vec3, b: Vec3): number {
|
|
168
|
-
return (a[0] ?? 0) * (b[0] ?? 0) + (a[1] ?? 0) * (b[1] ?? 0) + (a[2] ?? 0) * (b[2] ?? 0);
|
|
169
|
-
}
|
|
170
|
-
function unprojectNDC(invVP: Mat4, ndcX: number, ndcY: number, ndcZ: number): Vec3 {
|
|
171
|
-
const ws = vec3.create();
|
|
172
|
-
mat4.unproject(ws, vec3.create(ndcX, ndcY, ndcZ), invVP);
|
|
173
|
-
return ws;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function computeFrustumCorners(
|
|
177
|
-
vp: Mat4,
|
|
178
|
-
camNear: number,
|
|
179
|
-
camFar: number,
|
|
180
|
-
nearZ: number,
|
|
181
|
-
farZ: number,
|
|
182
|
-
projection: 'perspective' | 'orthographic',
|
|
183
|
-
): Vec3[] {
|
|
184
|
-
const invVP = mat4.create();
|
|
185
|
-
mat4.invert(invVP, vp);
|
|
186
|
-
const span = camFar - camNear;
|
|
187
|
-
const ndcNear =
|
|
188
|
-
projection === 'orthographic'
|
|
189
|
-
? (nearZ - camNear) / span
|
|
190
|
-
: (camFar * (nearZ - camNear)) / (nearZ * span);
|
|
191
|
-
const ndcFar =
|
|
192
|
-
projection === 'orthographic'
|
|
193
|
-
? (farZ - camNear) / span
|
|
194
|
-
: (camFar * (farZ - camNear)) / (farZ * span);
|
|
195
|
-
const corners: Vec3[] = [];
|
|
196
|
-
for (const ndcZ of [ndcNear, ndcFar]) {
|
|
197
|
-
for (const ndcX of [-1, 1]) {
|
|
198
|
-
for (const ndcY of [-1, 1]) corners.push(unprojectNDC(invVP, ndcX, ndcY, ndcZ));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return corners;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function validateGuardConfig(config: DirectionalCsmConfig): {
|
|
205
|
-
readonly pcfKernelSize: number;
|
|
206
|
-
readonly guardBandTexels: number;
|
|
207
|
-
readonly halfExtentDenominator: number;
|
|
208
|
-
} {
|
|
209
|
-
const pcfKernelSize = config.pcfKernelSize ?? DEFAULT_PCF_KERNEL_SIZE;
|
|
210
|
-
if (
|
|
211
|
-
!Number.isFinite(pcfKernelSize) ||
|
|
212
|
-
!Number.isInteger(pcfKernelSize) ||
|
|
213
|
-
pcfKernelSize < 1 ||
|
|
214
|
-
pcfKernelSize % 2 === 0
|
|
215
|
-
) {
|
|
216
|
-
throw new ShadowInvalidConfigError('pcfKernelSize', pcfKernelSize, 1);
|
|
217
|
-
}
|
|
218
|
-
if (!Number.isFinite(config.mapSize) || config.mapSize <= 0) {
|
|
219
|
-
throw new ShadowInvalidConfigError('mapSize', config.mapSize, 1);
|
|
220
|
-
}
|
|
221
|
-
const radius = (pcfKernelSize - 1) / 2;
|
|
222
|
-
const guardBandTexels = radius + 1;
|
|
223
|
-
const halfExtentDenominator = 1 - (2 * guardBandTexels) / config.mapSize;
|
|
224
|
-
if (!(halfExtentDenominator > 0)) {
|
|
225
|
-
throw new Error(
|
|
226
|
-
`directional CSM guard formula is unsatisfiable: mapSize=${config.mapSize}, pcfKernelSize=${pcfKernelSize}`,
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
return { pcfKernelSize, guardBandTexels, halfExtentDenominator };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function createLightView(direction: Vec3): Mat4 {
|
|
233
|
-
const lengthSquared = dot(direction, direction);
|
|
234
|
-
if (!(lengthSquared > 0) || !Number.isFinite(lengthSquared)) {
|
|
235
|
-
throw new Error('directional CSM light direction must be finite and non-zero');
|
|
236
|
-
}
|
|
237
|
-
const lightDirection = vec3.normalize(vec3.create(), direction);
|
|
238
|
-
const axes: readonly Vec3[] = [vec3.create(1, 0, 0), vec3.create(0, 1, 0), vec3.create(0, 0, 1)];
|
|
239
|
-
const firstAxis = axes[0];
|
|
240
|
-
if (firstAxis === undefined) throw new Error('directional CSM light basis has no canonical axis');
|
|
241
|
-
let up = firstAxis;
|
|
242
|
-
let leastAlignment = Math.abs(dot(lightDirection, up));
|
|
243
|
-
for (let index = 1; index < axes.length; index++) {
|
|
244
|
-
const candidate = axes[index];
|
|
245
|
-
if (candidate === undefined) continue;
|
|
246
|
-
const alignment = Math.abs(dot(lightDirection, candidate));
|
|
247
|
-
if (alignment < leastAlignment) {
|
|
248
|
-
leastAlignment = alignment;
|
|
249
|
-
up = candidate;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
const target = vec3.clone(lightDirection);
|
|
253
|
-
const view = mat4.create();
|
|
254
|
-
mat4.lookAt(view, vec3.create(), target, up);
|
|
255
|
-
return view;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function transformBounds(
|
|
259
|
-
points: readonly Vec3[],
|
|
260
|
-
view: Mat4,
|
|
261
|
-
): {
|
|
262
|
-
readonly points: Vec3[];
|
|
263
|
-
readonly bounds: Float32Array;
|
|
264
|
-
} {
|
|
265
|
-
const transformed: Vec3[] = [];
|
|
266
|
-
let minX = Infinity;
|
|
267
|
-
let maxX = -Infinity;
|
|
268
|
-
let minY = Infinity;
|
|
269
|
-
let maxY = -Infinity;
|
|
270
|
-
let minZ = Infinity;
|
|
271
|
-
let maxZ = -Infinity;
|
|
272
|
-
for (const point of points) {
|
|
273
|
-
const lightPoint = vec3.create();
|
|
274
|
-
mat4.transformVec3(lightPoint, view, point);
|
|
275
|
-
transformed.push(lightPoint);
|
|
276
|
-
minX = Math.min(minX, lightPoint[0] ?? 0);
|
|
277
|
-
maxX = Math.max(maxX, lightPoint[0] ?? 0);
|
|
278
|
-
minY = Math.min(minY, lightPoint[1] ?? 0);
|
|
279
|
-
maxY = Math.max(maxY, lightPoint[1] ?? 0);
|
|
280
|
-
minZ = Math.min(minZ, lightPoint[2] ?? 0);
|
|
281
|
-
maxZ = Math.max(maxZ, lightPoint[2] ?? 0);
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
points: transformed,
|
|
285
|
-
bounds: new Float32Array([minX, maxX, minY, maxY, minZ, maxZ]),
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function finiteOrderedAabb(aabb: readonly number[] | Float32Array | undefined): boolean {
|
|
290
|
-
if (aabb === undefined || aabb.length < 6) return false;
|
|
291
|
-
const values = [aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]];
|
|
292
|
-
return (
|
|
293
|
-
values.every((value) => Number.isFinite(value)) &&
|
|
294
|
-
(values[0] ?? 0) <= (values[3] ?? 0) &&
|
|
295
|
-
(values[1] ?? 0) <= (values[4] ?? 0) &&
|
|
296
|
-
(values[2] ?? 0) <= (values[5] ?? 0)
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function finiteMatrix(matrix: Float32Array): boolean {
|
|
301
|
-
if (matrix.length < 16) return false;
|
|
302
|
-
for (let index = 0; index < 16; index += 1) {
|
|
303
|
-
if (!Number.isFinite(matrix[index])) return false;
|
|
304
|
-
}
|
|
305
|
-
return true;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function validCsmCamera(cameraData: CsmCameraData): boolean {
|
|
309
|
-
if (!finiteMatrix(cameraData.world)) return false;
|
|
310
|
-
if (
|
|
311
|
-
!Number.isFinite(cameraData.near) ||
|
|
312
|
-
!Number.isFinite(cameraData.far) ||
|
|
313
|
-
!(cameraData.near > 0) ||
|
|
314
|
-
!(cameraData.far > cameraData.near)
|
|
315
|
-
) {
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
if (cameraData.projection === 'orthographic') {
|
|
319
|
-
return (
|
|
320
|
-
Number.isFinite(cameraData.orthoLeft) &&
|
|
321
|
-
Number.isFinite(cameraData.orthoRight) &&
|
|
322
|
-
Number.isFinite(cameraData.orthoBottom) &&
|
|
323
|
-
Number.isFinite(cameraData.orthoTop) &&
|
|
324
|
-
cameraData.orthoRight > cameraData.orthoLeft &&
|
|
325
|
-
cameraData.orthoTop > cameraData.orthoBottom
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
return (
|
|
329
|
-
Number.isFinite(cameraData.fov) &&
|
|
330
|
-
Number.isFinite(cameraData.aspect) &&
|
|
331
|
-
cameraData.fov > 0 &&
|
|
332
|
-
cameraData.aspect > 0
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function transformBoundsToAabb(
|
|
337
|
-
xBounds: readonly [number, number],
|
|
338
|
-
yBounds: readonly [number, number],
|
|
339
|
-
zBounds: readonly [number, number],
|
|
340
|
-
transform: Mat4,
|
|
341
|
-
): Float32Array {
|
|
342
|
-
let minX = Infinity;
|
|
343
|
-
let minY = Infinity;
|
|
344
|
-
let minZ = Infinity;
|
|
345
|
-
let maxX = -Infinity;
|
|
346
|
-
let maxY = -Infinity;
|
|
347
|
-
let maxZ = -Infinity;
|
|
348
|
-
for (const x of xBounds) {
|
|
349
|
-
for (const y of yBounds) {
|
|
350
|
-
for (const z of zBounds) {
|
|
351
|
-
const point = vec3.create();
|
|
352
|
-
mat4.transformVec3(point, transform, vec3.create(x, y, z));
|
|
353
|
-
minX = Math.min(minX, point[0] ?? 0);
|
|
354
|
-
minY = Math.min(minY, point[1] ?? 0);
|
|
355
|
-
minZ = Math.min(minZ, point[2] ?? 0);
|
|
356
|
-
maxX = Math.max(maxX, point[0] ?? 0);
|
|
357
|
-
maxY = Math.max(maxY, point[1] ?? 0);
|
|
358
|
-
maxZ = Math.max(maxZ, point[2] ?? 0);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return new Float32Array([minX, minY, minZ, maxX, maxY, maxZ]);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function transformAabb(aabb: Float32Array, transform: Mat4): Float32Array {
|
|
366
|
-
return transformBoundsToAabb(
|
|
367
|
-
[aabb[0] ?? 0, aabb[3] ?? 0],
|
|
368
|
-
[aabb[1] ?? 0, aabb[4] ?? 0],
|
|
369
|
-
[aabb[2] ?? 0, aabb[5] ?? 0],
|
|
370
|
-
transform,
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
export function buildDirectionalCsmCasterCandidates(
|
|
375
|
-
sources: readonly DirectionalCsmCandidateSource[],
|
|
376
|
-
): DirectionalCsmCasterCandidate[] {
|
|
377
|
-
return sources.map((source) => {
|
|
378
|
-
if (!source.shadowCaster) {
|
|
379
|
-
return {
|
|
380
|
-
renderableIndex: source.renderableIndex,
|
|
381
|
-
worldId: source.worldId,
|
|
382
|
-
entityKey: source.entityKey,
|
|
383
|
-
worldAabb: null,
|
|
384
|
-
bounded: false,
|
|
385
|
-
shadowCaster: false,
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
if (source.featureOwnedBoundsUnavailable === true) {
|
|
389
|
-
return {
|
|
390
|
-
renderableIndex: source.renderableIndex,
|
|
391
|
-
worldId: source.worldId,
|
|
392
|
-
entityKey: source.entityKey,
|
|
393
|
-
worldAabb: null,
|
|
394
|
-
bounded: false,
|
|
395
|
-
shadowCaster: true,
|
|
396
|
-
fallbackReason: 'feature-owned-conservative-bounds-unavailable',
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
if (!finiteOrderedAabb(source.localAabb)) {
|
|
400
|
-
return {
|
|
401
|
-
renderableIndex: source.renderableIndex,
|
|
402
|
-
worldId: source.worldId,
|
|
403
|
-
entityKey: source.entityKey,
|
|
404
|
-
worldAabb: null,
|
|
405
|
-
bounded: false,
|
|
406
|
-
shadowCaster: true,
|
|
407
|
-
fallbackReason: 'missing-or-invalid-local-bounds',
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
const localAabb = source.localAabb;
|
|
411
|
-
if (localAabb === undefined) {
|
|
412
|
-
return {
|
|
413
|
-
renderableIndex: source.renderableIndex,
|
|
414
|
-
worldId: source.worldId,
|
|
415
|
-
entityKey: source.entityKey,
|
|
416
|
-
worldAabb: null,
|
|
417
|
-
bounded: false,
|
|
418
|
-
shadowCaster: true,
|
|
419
|
-
fallbackReason: 'missing-or-invalid-local-bounds',
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
if (!finiteMatrix(source.transformWorld)) {
|
|
423
|
-
return {
|
|
424
|
-
renderableIndex: source.renderableIndex,
|
|
425
|
-
worldId: source.worldId,
|
|
426
|
-
entityKey: source.entityKey,
|
|
427
|
-
worldAabb: null,
|
|
428
|
-
bounded: false,
|
|
429
|
-
shadowCaster: true,
|
|
430
|
-
fallbackReason: 'missing-or-invalid-world-transform',
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
let worldAabb = transformAabb(
|
|
434
|
-
localAabb,
|
|
435
|
-
source.transformWorld as unknown as Mat4, // brand-cast-ok
|
|
436
|
-
);
|
|
437
|
-
const instanceTransforms = source.instanceTransforms;
|
|
438
|
-
if (instanceTransforms !== undefined) {
|
|
439
|
-
if (instanceTransforms.length % 16 !== 0) {
|
|
440
|
-
return {
|
|
441
|
-
renderableIndex: source.renderableIndex,
|
|
442
|
-
worldId: source.worldId,
|
|
443
|
-
entityKey: source.entityKey,
|
|
444
|
-
worldAabb: null,
|
|
445
|
-
bounded: false,
|
|
446
|
-
shadowCaster: true,
|
|
447
|
-
fallbackReason: 'invalid-instance-transform-stride',
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
let aggregate: Float32Array | undefined;
|
|
451
|
-
for (let offset = 0; offset < instanceTransforms.length; offset += 16) {
|
|
452
|
-
const instanceWorld = mat4.create();
|
|
453
|
-
mat4.multiply(
|
|
454
|
-
instanceWorld,
|
|
455
|
-
source.transformWorld as unknown as Mat4, // brand-cast-ok
|
|
456
|
-
instanceTransforms.subarray(offset, offset + 16) as unknown as Mat4, // brand-cast-ok
|
|
457
|
-
);
|
|
458
|
-
const instanceAabb = transformAabb(localAabb, instanceWorld);
|
|
459
|
-
if (aggregate === undefined) aggregate = instanceAabb;
|
|
460
|
-
else {
|
|
461
|
-
aggregate = new Float32Array([
|
|
462
|
-
Math.min(aggregate[0] ?? 0, instanceAabb[0] ?? 0),
|
|
463
|
-
Math.min(aggregate[1] ?? 0, instanceAabb[1] ?? 0),
|
|
464
|
-
Math.min(aggregate[2] ?? 0, instanceAabb[2] ?? 0),
|
|
465
|
-
Math.max(aggregate[3] ?? 0, instanceAabb[3] ?? 0),
|
|
466
|
-
Math.max(aggregate[4] ?? 0, instanceAabb[4] ?? 0),
|
|
467
|
-
Math.max(aggregate[5] ?? 0, instanceAabb[5] ?? 0),
|
|
468
|
-
]);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
if (aggregate !== undefined) worldAabb = aggregate;
|
|
472
|
-
}
|
|
473
|
-
return {
|
|
474
|
-
renderableIndex: source.renderableIndex,
|
|
475
|
-
worldId: source.worldId,
|
|
476
|
-
entityKey: source.entityKey,
|
|
477
|
-
worldAabb,
|
|
478
|
-
bounded: true,
|
|
479
|
-
shadowCaster: true,
|
|
480
|
-
};
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
function aabbToPoints(aabb: Float32Array): Vec3[] {
|
|
485
|
-
const points: Vec3[] = [];
|
|
486
|
-
for (const x of [aabb[0] ?? 0, aabb[3] ?? 0]) {
|
|
487
|
-
for (const y of [aabb[1] ?? 0, aabb[4] ?? 0]) {
|
|
488
|
-
for (const z of [aabb[2] ?? 0, aabb[5] ?? 0]) points.push(vec3.create(x, y, z));
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
return points;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function lightBoundsToWorldAabb(bounds: Float32Array, lightView: Mat4): Float32Array {
|
|
495
|
-
const inverseLightView = mat4.create();
|
|
496
|
-
mat4.invert(inverseLightView, lightView);
|
|
497
|
-
return transformBoundsToAabb(
|
|
498
|
-
[bounds[0] ?? 0, bounds[1] ?? 0],
|
|
499
|
-
[bounds[2] ?? 0, bounds[3] ?? 0],
|
|
500
|
-
[bounds[4] ?? 0, bounds[5] ?? 0],
|
|
501
|
-
inverseLightView,
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function contentRevision(values: Iterable<number>): number {
|
|
506
|
-
let hash = 0x811c9dc5;
|
|
507
|
-
const bytes = new DataView(new ArrayBuffer(8));
|
|
508
|
-
for (const value of values) {
|
|
509
|
-
bytes.setFloat64(0, value, true);
|
|
510
|
-
for (let index = 0; index < 8; index += 1) {
|
|
511
|
-
hash ^= bytes.getUint8(index);
|
|
512
|
-
hash = Math.imul(hash, 0x01000193);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return hash >>> 0;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
function symmetricFrustumSphere(
|
|
519
|
-
cameraData: CsmCameraData,
|
|
520
|
-
nearDepth: number,
|
|
521
|
-
farDepth: number,
|
|
522
|
-
): Sphere {
|
|
523
|
-
let localX = 0;
|
|
524
|
-
let localY = 0;
|
|
525
|
-
let localDepth = (nearDepth + farDepth) * 0.5;
|
|
526
|
-
let radiusSquared: number;
|
|
527
|
-
if (cameraData.projection === 'orthographic') {
|
|
528
|
-
const halfWidth = (cameraData.orthoRight - cameraData.orthoLeft) * 0.5;
|
|
529
|
-
const halfHeight = (cameraData.orthoTop - cameraData.orthoBottom) * 0.5;
|
|
530
|
-
localX = (cameraData.orthoLeft + cameraData.orthoRight) * 0.5;
|
|
531
|
-
localY = (cameraData.orthoBottom + cameraData.orthoTop) * 0.5;
|
|
532
|
-
radiusSquared = halfWidth ** 2 + halfHeight ** 2 + ((farDepth - nearDepth) * 0.5) ** 2;
|
|
533
|
-
} else {
|
|
534
|
-
const tangent = Math.tan(cameraData.fov * 0.5);
|
|
535
|
-
const nearHalfWidth = tangent * cameraData.aspect * nearDepth;
|
|
536
|
-
const nearHalfHeight = tangent * nearDepth;
|
|
537
|
-
const farHalfWidth = tangent * cameraData.aspect * farDepth;
|
|
538
|
-
const farHalfHeight = tangent * farDepth;
|
|
539
|
-
const squaredDistance = (
|
|
540
|
-
depth: number,
|
|
541
|
-
planeDepth: number,
|
|
542
|
-
halfWidth: number,
|
|
543
|
-
halfHeight: number,
|
|
544
|
-
) => halfWidth ** 2 + halfHeight ** 2 + (depth - planeDepth) ** 2;
|
|
545
|
-
const intersectionDepth =
|
|
546
|
-
(farHalfWidth ** 2 +
|
|
547
|
-
farHalfHeight ** 2 +
|
|
548
|
-
farDepth ** 2 -
|
|
549
|
-
nearHalfWidth ** 2 -
|
|
550
|
-
nearHalfHeight ** 2 -
|
|
551
|
-
nearDepth ** 2) /
|
|
552
|
-
(2 * (farDepth - nearDepth));
|
|
553
|
-
const candidateDepths = [nearDepth, farDepth, intersectionDepth];
|
|
554
|
-
let bestScore = Infinity;
|
|
555
|
-
for (const candidateDepth of candidateDepths) {
|
|
556
|
-
if (!Number.isFinite(candidateDepth)) continue;
|
|
557
|
-
const score = Math.max(
|
|
558
|
-
squaredDistance(candidateDepth, nearDepth, nearHalfWidth, nearHalfHeight),
|
|
559
|
-
squaredDistance(candidateDepth, farDepth, farHalfWidth, farHalfHeight),
|
|
560
|
-
);
|
|
561
|
-
if (score < bestScore) {
|
|
562
|
-
bestScore = score;
|
|
563
|
-
localDepth = candidateDepth;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
radiusSquared = bestScore;
|
|
567
|
-
}
|
|
568
|
-
const localCenter = vec3.create(localX, localY, -localDepth);
|
|
569
|
-
const worldCenter = vec3.create();
|
|
570
|
-
mat4.transformVec3(
|
|
571
|
-
worldCenter,
|
|
572
|
-
cameraData.world as unknown as Mat4, // brand-cast-ok
|
|
573
|
-
localCenter,
|
|
574
|
-
);
|
|
575
|
-
return { center: worldCenter, radius: Math.sqrt(radiusSquared) };
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
export function pssmSplit(
|
|
579
|
-
nearPlane: number,
|
|
580
|
-
farPlane: number,
|
|
581
|
-
cascadeCount: number,
|
|
582
|
-
splitLambda: number,
|
|
583
|
-
): Float32Array {
|
|
584
|
-
const EPS = 1e-6;
|
|
585
|
-
if (farPlane <= nearPlane + EPS) {
|
|
586
|
-
throw new ShadowInvalidConfigError('shadowDistance', farPlane, nearPlane + EPS);
|
|
587
|
-
}
|
|
588
|
-
const result = new Float32Array(cascadeCount);
|
|
589
|
-
const ratio = farPlane / nearPlane;
|
|
590
|
-
for (let index = 1; index <= cascadeCount; index++) {
|
|
591
|
-
const t = index / cascadeCount;
|
|
592
|
-
const logPart = nearPlane * ratio ** t;
|
|
593
|
-
const uniformPart = nearPlane + t * (farPlane - nearPlane);
|
|
594
|
-
result[index - 1] = splitLambda * logPart + (1 - splitLambda) * uniformPart;
|
|
595
|
-
}
|
|
596
|
-
return result;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
function buildCascadeVolumeSet(
|
|
600
|
-
direction: Vec3,
|
|
601
|
-
config: DirectionalCsmConfig,
|
|
602
|
-
cameraData: CsmCameraData | undefined,
|
|
603
|
-
casterCandidates: readonly DirectionalCsmCasterCandidate[] = [],
|
|
604
|
-
candidateBroadphase: DirectionalCsmCandidateBroadphase | undefined = undefined,
|
|
605
|
-
): DirectionalCsmResult | null {
|
|
606
|
-
const cascadeCount = Math.round(config.cascadeCount);
|
|
607
|
-
const sNear = cameraData?.near ?? 0.1;
|
|
608
|
-
const sFar = config.shadowDistance;
|
|
609
|
-
const guard = validateGuardConfig(config);
|
|
610
|
-
const splits = pssmSplit(sNear, sFar, cascadeCount, config.splitLambda);
|
|
611
|
-
const paddedSplits = new Float32Array(4);
|
|
612
|
-
for (let index = 0; index < splits.length; index++) paddedSplits[index] = splits[index] ?? 0;
|
|
613
|
-
if (cameraData === undefined) return null;
|
|
614
|
-
// Match extract-stage frustum culling's malformed-camera contract: an
|
|
615
|
-
// incomplete camera is an always-visible/CSM-unavailable input, not a
|
|
616
|
-
// reason to poison the render frame with NaN matrices or a depth-fit throw.
|
|
617
|
-
// Valid cameras still use the receiver-driven stable clip domain below.
|
|
618
|
-
if (!validCsmCamera(cameraData)) return null;
|
|
619
|
-
|
|
620
|
-
const camProj = mat4.create();
|
|
621
|
-
if (cameraData.projection === 'orthographic') {
|
|
622
|
-
mat4.orthographic(
|
|
623
|
-
camProj,
|
|
624
|
-
cameraData.orthoLeft,
|
|
625
|
-
cameraData.orthoRight,
|
|
626
|
-
cameraData.orthoBottom,
|
|
627
|
-
cameraData.orthoTop,
|
|
628
|
-
cameraData.near,
|
|
629
|
-
cameraData.far,
|
|
630
|
-
);
|
|
631
|
-
} else {
|
|
632
|
-
mat4.perspective(camProj, cameraData.fov, cameraData.aspect, cameraData.near, cameraData.far);
|
|
633
|
-
}
|
|
634
|
-
const camView = mat4.create();
|
|
635
|
-
mat4.invert(camView, cameraData.world as unknown as mat4.Mat4Like);
|
|
636
|
-
const cameraVP = mat4.create();
|
|
637
|
-
mat4.multiply(cameraVP, camProj, camView);
|
|
638
|
-
const lightView = createLightView(direction);
|
|
639
|
-
|
|
640
|
-
const fullCorners = computeFrustumCorners(
|
|
641
|
-
cameraVP,
|
|
642
|
-
cameraData.near,
|
|
643
|
-
cameraData.far,
|
|
644
|
-
sNear,
|
|
645
|
-
sFar,
|
|
646
|
-
cameraData.projection,
|
|
647
|
-
);
|
|
648
|
-
const fullBounds = transformBounds(fullCorners, lightView).bounds;
|
|
649
|
-
const fullSphere = symmetricFrustumSphere(cameraData, sNear, sFar);
|
|
650
|
-
const candidateLightBounds = new Map<number, Float32Array>();
|
|
651
|
-
let casterSceneMinZ = fullBounds[4] ?? 0;
|
|
652
|
-
let casterSceneMaxZ = fullBounds[5] ?? 0;
|
|
653
|
-
for (const candidate of casterCandidates) {
|
|
654
|
-
if (!candidate.shadowCaster || !candidate.bounded || candidate.worldAabb === null) continue;
|
|
655
|
-
const bounds = transformBounds(aabbToPoints(candidate.worldAabb), lightView).bounds;
|
|
656
|
-
candidateLightBounds.set(candidate.renderableIndex, bounds);
|
|
657
|
-
casterSceneMinZ = Math.min(casterSceneMinZ, bounds[4] ?? casterSceneMinZ);
|
|
658
|
-
casterSceneMaxZ = Math.max(casterSceneMaxZ, bounds[5] ?? casterSceneMaxZ);
|
|
659
|
-
}
|
|
660
|
-
const resultLightViewProjs: Float32Array[] = [];
|
|
661
|
-
const cascades: CascadeVolume[] = [];
|
|
662
|
-
|
|
663
|
-
for (let cascadeIndex = 0; cascadeIndex < 4; cascadeIndex++) {
|
|
664
|
-
if (cascadeIndex >= cascadeCount) {
|
|
665
|
-
resultLightViewProjs.push(new Float32Array(16));
|
|
666
|
-
continue;
|
|
667
|
-
}
|
|
668
|
-
const cascadeNear = cascadeIndex === 0 ? sNear : (splits[cascadeIndex - 1] ?? sFar);
|
|
669
|
-
const cascadeFar = splits[cascadeIndex] ?? sFar;
|
|
670
|
-
const receiverNear =
|
|
671
|
-
cascadeIndex === 0
|
|
672
|
-
? sNear
|
|
673
|
-
: Math.max(sNear, cascadeNear - (splits[cascadeIndex - 1] ?? sFar) * config.cascadeBlend);
|
|
674
|
-
const receiverCorners = computeFrustumCorners(
|
|
675
|
-
cameraVP,
|
|
676
|
-
cameraData.near,
|
|
677
|
-
cameraData.far,
|
|
678
|
-
receiverNear,
|
|
679
|
-
cascadeFar,
|
|
680
|
-
cameraData.projection,
|
|
681
|
-
);
|
|
682
|
-
const transformed = transformBounds(receiverCorners, lightView);
|
|
683
|
-
const sphere = symmetricFrustumSphere(cameraData, receiverNear, cascadeFar);
|
|
684
|
-
const sphereCenterLight = vec3.create();
|
|
685
|
-
mat4.transformVec3(sphereCenterLight, lightView, sphere.center);
|
|
686
|
-
const halfExtent = sphere.radius / guard.halfExtentDenominator;
|
|
687
|
-
const worldUnitsPerTexel = (2 * halfExtent) / config.mapSize;
|
|
688
|
-
const snappedX =
|
|
689
|
-
Math.round((sphereCenterLight[0] ?? 0) / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
690
|
-
const snappedY =
|
|
691
|
-
Math.round((sphereCenterLight[1] ?? 0) / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
692
|
-
const unsnappedClipMaxZ = Math.max(transformed.bounds[5] ?? 0, fullBounds[5] ?? 0);
|
|
693
|
-
const clipMaxZ = Math.ceil(unsnappedClipMaxZ / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
694
|
-
const clipMinZ =
|
|
695
|
-
Math.floor((clipMaxZ - fullSphere.radius * 2) / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
696
|
-
if (!(clipMaxZ > clipMinZ)) {
|
|
697
|
-
throw new Error(`directional CSM receiver depth is degenerate for cascade ${cascadeIndex}`);
|
|
698
|
-
}
|
|
699
|
-
const clipBounds = new Float32Array([
|
|
700
|
-
snappedX - halfExtent,
|
|
701
|
-
snappedX + halfExtent,
|
|
702
|
-
snappedY - halfExtent,
|
|
703
|
-
snappedY + halfExtent,
|
|
704
|
-
clipMinZ,
|
|
705
|
-
clipMaxZ,
|
|
706
|
-
]);
|
|
707
|
-
const casterBroadphaseLightBounds = new Float32Array([
|
|
708
|
-
clipBounds[0] ?? 0,
|
|
709
|
-
clipBounds[1] ?? 0,
|
|
710
|
-
clipBounds[2] ?? 0,
|
|
711
|
-
clipBounds[3] ?? 0,
|
|
712
|
-
Math.min(clipBounds[4] ?? 0, casterSceneMinZ),
|
|
713
|
-
Math.max(clipBounds[5] ?? 0, casterSceneMaxZ),
|
|
714
|
-
]);
|
|
715
|
-
const casterBroadphaseWorldAabb = lightBoundsToWorldAabb(
|
|
716
|
-
casterBroadphaseLightBounds,
|
|
717
|
-
lightView,
|
|
718
|
-
);
|
|
719
|
-
const boundedMembers: number[] = [];
|
|
720
|
-
const unboundedFallback: DirectionalCsmFallback[] = [];
|
|
721
|
-
const candidateDecisions: DirectionalCsmCandidateDecision[] | undefined =
|
|
722
|
-
config.collectCandidateDecisions ? [] : undefined;
|
|
723
|
-
let boundedMemberMaxZ = -Infinity;
|
|
724
|
-
const broadphaseIndices = candidateBroadphase?.(casterBroadphaseWorldAabb);
|
|
725
|
-
const candidateDomain =
|
|
726
|
-
broadphaseIndices === undefined
|
|
727
|
-
? casterCandidates
|
|
728
|
-
: broadphaseIndices.flatMap((index) => {
|
|
729
|
-
const candidate = casterCandidates[index];
|
|
730
|
-
return candidate === undefined ? [] : [candidate];
|
|
731
|
-
});
|
|
732
|
-
for (const candidate of candidateDomain) {
|
|
733
|
-
if (!candidate.shadowCaster) {
|
|
734
|
-
if (candidateDecisions !== undefined) {
|
|
735
|
-
candidateDecisions.push({
|
|
736
|
-
renderableIndex: candidate.renderableIndex,
|
|
737
|
-
worldId: candidate.worldId,
|
|
738
|
-
entityKey: candidate.entityKey,
|
|
739
|
-
selected: false,
|
|
740
|
-
reason: 'no-shadow-caster-pass',
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
continue;
|
|
744
|
-
}
|
|
745
|
-
if (!candidate.bounded || candidate.worldAabb === null) {
|
|
746
|
-
unboundedFallback.push({
|
|
747
|
-
renderableIndex: candidate.renderableIndex,
|
|
748
|
-
reason: candidate.fallbackReason ?? 'missing-or-invalid-world-bounds',
|
|
749
|
-
});
|
|
750
|
-
candidateDecisions?.push({
|
|
751
|
-
renderableIndex: candidate.renderableIndex,
|
|
752
|
-
worldId: candidate.worldId,
|
|
753
|
-
entityKey: candidate.entityKey,
|
|
754
|
-
selected: true,
|
|
755
|
-
reason: 'unbounded-fallback',
|
|
756
|
-
});
|
|
757
|
-
continue;
|
|
758
|
-
}
|
|
759
|
-
const casterLightBounds =
|
|
760
|
-
candidateLightBounds.get(candidate.renderableIndex) ??
|
|
761
|
-
transformBounds(aabbToPoints(candidate.worldAabb), lightView).bounds;
|
|
762
|
-
// Membership must use the same final XY domain that owns the cascade
|
|
763
|
-
// map. Testing against the raw frustum AABB is narrower than the
|
|
764
|
-
// receiver-driven sphere fit: a caster can still project into the
|
|
765
|
-
// stable map while falling just outside the current frustum corner
|
|
766
|
-
// bounds. That mismatch is the camera-crossing door-frame failure mode:
|
|
767
|
-
// the map remains valid, but the caster is culled before the depth pass.
|
|
768
|
-
// `halfExtent` already includes the PCF/snapping guard in clipBounds, so
|
|
769
|
-
// do not apply a second guard expansion here; the final clip is the sole
|
|
770
|
-
// XY truth for membership and raster coverage.
|
|
771
|
-
const overlapsStableClipXY =
|
|
772
|
-
(casterLightBounds[1] ?? -Infinity) >= (clipBounds[0] ?? -Infinity) &&
|
|
773
|
-
(casterLightBounds[0] ?? Infinity) <= (clipBounds[1] ?? Infinity) &&
|
|
774
|
-
(casterLightBounds[3] ?? -Infinity) >= (clipBounds[2] ?? -Infinity) &&
|
|
775
|
-
(casterLightBounds[2] ?? Infinity) <= (clipBounds[3] ?? Infinity);
|
|
776
|
-
const reachesReceiver =
|
|
777
|
-
(casterLightBounds[5] ?? -Infinity) >= (transformed.bounds[4] ?? Infinity);
|
|
778
|
-
if (overlapsStableClipXY && reachesReceiver) {
|
|
779
|
-
boundedMembers.push(candidate.renderableIndex);
|
|
780
|
-
boundedMemberMaxZ = Math.max(boundedMemberMaxZ, casterLightBounds[5] ?? -Infinity);
|
|
781
|
-
candidateDecisions?.push({
|
|
782
|
-
renderableIndex: candidate.renderableIndex,
|
|
783
|
-
worldId: candidate.worldId,
|
|
784
|
-
entityKey: candidate.entityKey,
|
|
785
|
-
selected: true,
|
|
786
|
-
reason: 'stable-clip-xy-overlap-and-toward-light',
|
|
787
|
-
lightSpaceBounds: new Float32Array(casterLightBounds),
|
|
788
|
-
});
|
|
789
|
-
} else {
|
|
790
|
-
candidateDecisions?.push({
|
|
791
|
-
renderableIndex: candidate.renderableIndex,
|
|
792
|
-
worldId: candidate.worldId,
|
|
793
|
-
entityKey: candidate.entityKey,
|
|
794
|
-
selected: false,
|
|
795
|
-
reason: overlapsStableClipXY
|
|
796
|
-
? 'behind-receiver-toward-light-test'
|
|
797
|
-
: 'outside-stable-clip-xy',
|
|
798
|
-
lightSpaceBounds: new Float32Array(casterLightBounds),
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
if (candidateDecisions !== undefined && broadphaseIndices !== undefined) {
|
|
803
|
-
const domain = new Set(candidateDomain.map((candidate) => candidate.renderableIndex));
|
|
804
|
-
for (const candidate of casterCandidates) {
|
|
805
|
-
if (domain.has(candidate.renderableIndex)) continue;
|
|
806
|
-
candidateDecisions.push({
|
|
807
|
-
renderableIndex: candidate.renderableIndex,
|
|
808
|
-
worldId: candidate.worldId,
|
|
809
|
-
entityKey: candidate.entityKey,
|
|
810
|
-
selected: false,
|
|
811
|
-
reason: 'outside-spatial-broadphase',
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
candidateDecisions.sort((left, right) => left.renderableIndex - right.renderableIndex);
|
|
815
|
-
}
|
|
816
|
-
const casterRenderableIndices = new Uint32Array(
|
|
817
|
-
[
|
|
818
|
-
...new Set([...boundedMembers, ...unboundedFallback.map((entry) => entry.renderableIndex)]),
|
|
819
|
-
].sort((left, right) => left - right),
|
|
820
|
-
);
|
|
821
|
-
const receiverMaxZ = transformed.bounds[5] ?? 0;
|
|
822
|
-
const historicalMinZ = fullBounds[4] ?? transformed.bounds[4] ?? receiverMaxZ;
|
|
823
|
-
const historicalMaxZ = fullBounds[5] ?? receiverMaxZ;
|
|
824
|
-
const hasWholeFrustumFallback = casterCandidates.length === 0 || unboundedFallback.length > 0;
|
|
825
|
-
// An empty candidate domain is the legacy standalone math API: without a
|
|
826
|
-
// producer snapshot there is no trustworthy caster census, so retain the
|
|
827
|
-
// historical conservative depth. The render extract path always supplies
|
|
828
|
-
// the author-visible candidate domain and therefore uses receiver-plus-
|
|
829
|
-
// bounded-member fitting unless an explicit unbounded fallback exists.
|
|
830
|
-
const fallbackMaxZ = hasWholeFrustumFallback ? historicalMaxZ : -Infinity;
|
|
831
|
-
// Keep the complete XYZ fit on the same temporal grid. X/Y snapping alone
|
|
832
|
-
// is insufficient: receiver/caster Z bounds move with the camera and can
|
|
833
|
-
// otherwise continuously change the orthographic depth scale/translation,
|
|
834
|
-
// reintroducing shadow shimmer even when the lateral matrix is stable.
|
|
835
|
-
// Round outward so the quantization is conservative and never clips a
|
|
836
|
-
// receiver or a bounded caster at a grid boundary.
|
|
837
|
-
const rawClipMaxZWithCasters = Math.max(fallbackMaxZ, receiverMaxZ, boundedMemberMaxZ);
|
|
838
|
-
const clipMaxZWithCasters =
|
|
839
|
-
Math.ceil(rawClipMaxZWithCasters / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
840
|
-
const receiverMinZ = transformed.bounds[4] ?? clipMaxZWithCasters;
|
|
841
|
-
const rawClipMinZWithReceiver = hasWholeFrustumFallback
|
|
842
|
-
? Math.min(receiverMinZ, historicalMinZ)
|
|
843
|
-
: receiverMinZ;
|
|
844
|
-
const clipMinZWithReceiver =
|
|
845
|
-
Math.floor(rawClipMinZWithReceiver / worldUnitsPerTexel) * worldUnitsPerTexel;
|
|
846
|
-
clipBounds[4] = clipMinZWithReceiver;
|
|
847
|
-
clipBounds[5] = clipMaxZWithCasters;
|
|
848
|
-
const orthoProj = mat4.create();
|
|
849
|
-
const clipMax = clipBounds[5] ?? 0;
|
|
850
|
-
const clipMin = clipBounds[4] ?? 0;
|
|
851
|
-
mat4.orthographic(
|
|
852
|
-
orthoProj,
|
|
853
|
-
clipBounds[0] ?? 0,
|
|
854
|
-
clipBounds[1] ?? 0,
|
|
855
|
-
clipBounds[2] ?? 0,
|
|
856
|
-
clipBounds[3] ?? 0,
|
|
857
|
-
-clipMax,
|
|
858
|
-
-clipMin,
|
|
859
|
-
);
|
|
860
|
-
const lightViewProj = new Float32Array(mat4.multiply(mat4.create(), orthoProj, lightView));
|
|
861
|
-
resultLightViewProjs.push(lightViewProj);
|
|
862
|
-
const rasterViewport = directionalCascadeRasterViewport(
|
|
863
|
-
cascadeIndex,
|
|
864
|
-
cascadeCount,
|
|
865
|
-
config.mapSize,
|
|
866
|
-
);
|
|
867
|
-
const depthLightRange = [clipBounds[4] ?? 0, clipBounds[5] ?? 0] as const;
|
|
868
|
-
const revision = contentRevision([
|
|
869
|
-
cascadeIndex,
|
|
870
|
-
...lightViewProj,
|
|
871
|
-
...clipBounds,
|
|
872
|
-
...casterBroadphaseWorldAabb,
|
|
873
|
-
...casterRenderableIndices,
|
|
874
|
-
rasterViewport.x,
|
|
875
|
-
rasterViewport.y,
|
|
876
|
-
rasterViewport.w,
|
|
877
|
-
rasterViewport.h,
|
|
878
|
-
]);
|
|
879
|
-
cascades.push({
|
|
880
|
-
cascadeIndex,
|
|
881
|
-
revision,
|
|
882
|
-
lightViewProj,
|
|
883
|
-
receiverViewDepth: [receiverNear, cascadeFar],
|
|
884
|
-
receiverLightBounds: transformed.bounds,
|
|
885
|
-
clipLightBounds: clipBounds,
|
|
886
|
-
rasterLightBounds: clipBounds,
|
|
887
|
-
depthLightRange,
|
|
888
|
-
casterBroadphaseWorldAabb,
|
|
889
|
-
rasterViewport,
|
|
890
|
-
stableExtent: halfExtent,
|
|
891
|
-
unsnappedCenter: [sphereCenterLight[0] ?? 0, sphereCenterLight[1] ?? 0],
|
|
892
|
-
snappedCenter: [snappedX, snappedY],
|
|
893
|
-
halfExtent,
|
|
894
|
-
worldUnitsPerTexel,
|
|
895
|
-
guardBandTexels: guard.guardBandTexels,
|
|
896
|
-
casterRenderableIndices,
|
|
897
|
-
...(candidateDecisions === undefined ? {} : { candidateDecisions }),
|
|
898
|
-
unboundedFallback,
|
|
899
|
-
unboundedFallbackCount: unboundedFallback.length,
|
|
900
|
-
lightSpaceMinZFull: historicalMinZ,
|
|
901
|
-
lightSpaceMaxZFull: historicalMaxZ,
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
const revision = contentRevision([
|
|
906
|
-
cascadeCount,
|
|
907
|
-
config.mapSize,
|
|
908
|
-
...paddedSplits,
|
|
909
|
-
...cascades.map((cascade) => cascade.revision),
|
|
910
|
-
]);
|
|
911
|
-
return {
|
|
912
|
-
revision,
|
|
913
|
-
volumes: cascades,
|
|
914
|
-
lightViewProj: resultLightViewProjs,
|
|
915
|
-
splitPlanes: paddedSplits,
|
|
916
|
-
cascadeCount,
|
|
917
|
-
cascadeBlend: config.cascadeBlend,
|
|
918
|
-
shadowMapSize: config.mapSize,
|
|
919
|
-
cascades,
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
/** Sole producer for directional cascade matrices, bounds, raster, depth, and membership. */
|
|
924
|
-
export class CascadeVolumeSetBuilder {
|
|
925
|
-
build(
|
|
926
|
-
direction: Vec3,
|
|
927
|
-
config: DirectionalCsmConfig,
|
|
928
|
-
cameraData: CsmCameraData | undefined,
|
|
929
|
-
casterCandidates: readonly DirectionalCsmCasterCandidate[] = [],
|
|
930
|
-
candidateBroadphase: DirectionalCsmCandidateBroadphase | undefined = undefined,
|
|
931
|
-
): DirectionalCsmResult | null {
|
|
932
|
-
return buildCascadeVolumeSet(
|
|
933
|
-
direction,
|
|
934
|
-
config,
|
|
935
|
-
cameraData,
|
|
936
|
-
casterCandidates,
|
|
937
|
-
candidateBroadphase,
|
|
938
|
-
);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
const CASCADE_VOLUME_SET_BUILDER = new CascadeVolumeSetBuilder();
|
|
943
|
-
|
|
944
|
-
/** Compatibility entry backed by the canonical CascadeVolumeSet producer. */
|
|
945
|
-
export function computeDirectionalCsm(
|
|
946
|
-
direction: Vec3,
|
|
947
|
-
config: DirectionalCsmConfig,
|
|
948
|
-
cameraData: CsmCameraData | undefined,
|
|
949
|
-
casterCandidates: readonly DirectionalCsmCasterCandidate[] = [],
|
|
950
|
-
candidateBroadphase: DirectionalCsmCandidateBroadphase | undefined = undefined,
|
|
951
|
-
): DirectionalCsmResult | null {
|
|
952
|
-
return CASCADE_VOLUME_SET_BUILDER.build(
|
|
953
|
-
direction,
|
|
954
|
-
config,
|
|
955
|
-
cameraData,
|
|
956
|
-
casterCandidates,
|
|
957
|
-
candidateBroadphase,
|
|
958
|
-
);
|
|
959
|
-
}
|