@forgeax/engine-render 0.1.20 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +365 -29
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +30 -19
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +19 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +4 -1
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
- package/dist/chunk-4L3P6DT5.mjs.map +1 -0
- package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
- package/dist/chunk-4NPUASZR.mjs.map +1 -0
- package/dist/chunk-DIYW3M5D.mjs +5085 -0
- package/dist/chunk-DIYW3M5D.mjs.map +1 -0
- package/dist/chunk-FBC4R44J.mjs +1003 -0
- package/dist/chunk-FBC4R44J.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
- package/dist/chunk-FF7K3FSO.mjs.map +1 -0
- package/dist/chunk-HZUPSYW7.mjs +1104 -0
- package/dist/chunk-HZUPSYW7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
- package/dist/chunk-QODA5UKU.mjs.map +1 -0
- package/dist/chunk-YALPS44A.mjs +296 -0
- package/dist/chunk-YALPS44A.mjs.map +1 -0
- package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
- package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +4 -0
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/light-probe.d.ts +9 -0
- package/dist/components/light-probe.d.ts.map +1 -0
- package/dist/components/rect-area-light.d.ts +12 -0
- package/dist/components/rect-area-light.d.ts.map +1 -0
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +4 -0
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/spot-light.d.ts +3 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +14836 -9620
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +8 -1
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/lifecycle-transaction.d.ts +2 -0
- package/dist/device/lifecycle-transaction.d.ts.map +1 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/gpu-driven.d.ts +26 -0
- package/dist/errors/gpu-driven.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +9 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +166 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -0
- package/dist/extract/gpu-driven.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +63 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +97 -2
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +64 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +14 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +8 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +0 -1
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +21 -19
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +39 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +91 -6
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +214 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +23 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/light-buffer-layout.d.ts +58 -140
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +38 -14
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +5 -26
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/resources.d.ts +72 -0
- package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/state.d.ts +24 -0
- package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +33 -36
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +78 -24
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +16 -6
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +20 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +0 -20
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +25 -2
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +98 -6
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +119 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -5
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/inspection.d.ts +10 -0
- package/dist/reflection/inspection.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +140 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +60 -0
- package/dist/reflection/record-owner.d.ts.map +1 -0
- package/dist/render-contract.d.ts +62 -14
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +49 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +160 -31
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +28 -2
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/probe-blend-record.d.ts +22 -0
- package/dist/scene/probe-blend-record.d.ts.map +1 -0
- package/dist/scene/probe-blend.d.ts +142 -0
- package/dist/scene/probe-blend.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +0 -6
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +117 -9
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/visibility/bounds.d.ts +20 -0
- package/dist/scene/visibility/bounds.d.ts.map +1 -0
- package/dist/scene/visibility/budget.d.ts +16 -0
- package/dist/scene/visibility/budget.d.ts.map +1 -0
- package/dist/scene/visibility/facet.d.ts +73 -0
- package/dist/scene/visibility/facet.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-lod.d.ts +46 -0
- package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
- package/dist/scene/visibility/inspection.d.ts +132 -0
- package/dist/scene/visibility/inspection.d.ts.map +1 -0
- package/dist/scene/visibility/lod-selector.d.ts +25 -0
- package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
- package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
- package/dist/scene/visibility/types.d.ts +34 -0
- package/dist/scene/visibility/types.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/ssr/admission.d.ts +122 -0
- package/dist/ssr/admission.d.ts.map +1 -0
- package/dist/ssr/composition.d.ts +32 -0
- package/dist/ssr/composition.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +39 -0
- package/dist/ssr/errors.d.ts.map +1 -0
- package/dist/ssr/identity.d.ts +13 -0
- package/dist/ssr/identity.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/frame-coordinator.d.ts +13 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +2 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -5
- package/dist/temporal/view.d.ts +7 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts +5 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +9 -5
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/environment-generation.integration.test.ts +16 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
- package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
- package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
- package/src/__tests__/factory-contract.integration.test.ts +288 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
- package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
- package/src/__tests__/gpu-lod-evidence.ts +188 -0
- package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
- package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
- package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
- package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
- package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
- package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
- package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
- package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
- package/src/__tests__/gpu-scene.unit.test.ts +49 -3
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
- package/src/__tests__/light-inspection.unit.test.ts +55 -0
- package/src/__tests__/light-resource-error.unit.test.ts +43 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
- package/src/__tests__/lod-bounds.unit.test.ts +42 -0
- package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
- package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
- package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
- package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
- package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
- package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
- package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
- package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
- package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
- package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
- package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
- package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
- package/src/__tests__/lod-selector.profile.test.ts +35 -0
- package/src/__tests__/lod-selector.unit.test.ts +68 -0
- package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
- package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
- package/src/__tests__/ltc-resources.unit.test.ts +32 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
- package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
- package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
- package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
- package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
- package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
- package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
- package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
- package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
- package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
- package/src/__tests__/occlusion-query.evidence.ts +178 -0
- package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
- package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/probe-bindings.unit.test.ts +200 -0
- package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
- package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
- package/src/__tests__/probe-capacity.integration.test.ts +97 -0
- package/src/__tests__/probe-recovery.integration.test.ts +104 -0
- package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
- package/src/__tests__/profiler-phase-token.test.ts +1 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
- package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
- package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
- package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
- package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
- package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
- package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
- package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
- package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
- package/src/__tests__/ssr-composition.unit.test.ts +46 -0
- package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
- package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
- package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
- package/src/__tests__/temporal-view.unit.test.ts +3 -3
- package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-budget.integration.test.ts +140 -0
- package/src/__tests__/visibility-budget.unit.test.ts +70 -0
- package/src/__tests__/visibility-extract.integration.test.ts +11 -6
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +80 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +1411 -366
- package/src/assembly/host-contract.ts +35 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/cluster-binner.ts +31 -0
- package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
- package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +5 -0
- package/src/components/light-helpers.ts +133 -8
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/reflection-probe.ts +49 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/gpu-residency.ts +140 -9
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +20 -1
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +32 -0
- package/src/errors/render.ts +341 -143
- package/src/extract/camera.ts +3 -3
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +2 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +207 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +953 -43
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +140 -64
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +169 -63
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +222 -0
- package/src/inspection-types.ts +276 -1
- package/src/instances-derived-bounds.ts +171 -0
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +155 -310
- package/src/materials.ts +16 -2
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +255 -60
- package/src/pipeline/standard-forward-lane.ts +93 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +158 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +35 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +78 -0
- package/src/pipeline/standard-pipeline.ts +124 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +95 -21
- package/src/plugin.ts +4 -0
- package/src/point-shadow-inspection.ts +55 -0
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
- package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
- package/src/prepare/extended-lighting/resources.ts +389 -0
- package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
- package/src/prepare/extended-lighting/state.ts +92 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +591 -452
- package/src/record/frame-snapshot.ts +92 -39
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +662 -158
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +112 -39
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +324 -119
- package/src/record/main-pass-material.ts +103 -10
- package/src/record/main-pass-sprite-draws.ts +99 -103
- package/src/record/main-pass.ts +71 -15
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +136 -3
- package/src/record/shadow-pass.ts +83 -68
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +1034 -43
- package/src/record/view-ubo.ts +72 -47
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +476 -0
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +93 -10
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +122 -2
- package/src/render-system-extract.ts +1041 -225
- package/src/render-system.ts +1310 -85
- package/src/renderer.ts +222 -0
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
- package/src/scene/probe-blend-record.ts +54 -0
- package/src/scene/probe-blend.ts +813 -0
- package/src/scene/render-scene-types.ts +0 -7
- package/src/scene/render-scene.ts +942 -171
- package/src/scene/visibility/bounds.ts +57 -0
- package/src/scene/visibility/budget.ts +40 -0
- package/src/scene/visibility/facet.ts +400 -0
- package/src/scene/visibility/gpu-frame-timing.ts +101 -0
- package/src/scene/visibility/gpu-lod.ts +119 -0
- package/src/scene/visibility/inspection.ts +313 -0
- package/src/scene/visibility/lod-selector.ts +84 -0
- package/src/scene/visibility/occlusion-confidence.ts +478 -0
- package/src/scene/visibility/occlusion-pass.ts +165 -0
- package/src/scene/visibility/occlusion-query-pool.ts +178 -0
- package/src/scene/visibility/occlusion-runtime.ts +672 -0
- package/src/scene/visibility/types.ts +50 -0
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/ssr/admission.ts +451 -0
- package/src/ssr/composition.ts +73 -0
- package/src/ssr/errors.ts +76 -0
- package/src/ssr/identity.ts +12 -0
- package/src/systems/skin-palette-allocator.ts +1 -1
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/temporal/frame-coordinator.ts +26 -0
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +4 -4
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +53 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +61 -58
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs +0 -73
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @forgeax/engine-render - closed Directional shadow filter vocabulary.
|
|
2
|
+
|
|
3
|
+
/** Stable serialized labels for Directional shadow filtering. */
|
|
4
|
+
export const DirectionalShadowFilterValue = Object.freeze({
|
|
5
|
+
pcf1: 1,
|
|
6
|
+
pcf3: 2,
|
|
7
|
+
pcf5: 3,
|
|
8
|
+
pcssMedium: 4,
|
|
9
|
+
pcssHigh: 5,
|
|
10
|
+
} as const);
|
|
11
|
+
|
|
12
|
+
export type DirectionalShadowFilterLabel = keyof typeof DirectionalShadowFilterValue;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Extract-side semantic projection of the serialized Directional filter.
|
|
16
|
+
* `shadowAngularRadius` is radians and `maxPenumbraTexels` is a finite integer.
|
|
17
|
+
*/
|
|
18
|
+
export type DirectionalShadowQuality =
|
|
19
|
+
| { readonly kind: 'pcf'; readonly kernel: 1 | 3 | 5 }
|
|
20
|
+
| {
|
|
21
|
+
readonly kind: 'pcss';
|
|
22
|
+
readonly preset: 'medium' | 'high';
|
|
23
|
+
readonly angularRadiusRadians: number;
|
|
24
|
+
readonly maxPenumbraTexels: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Resolve the closed serialized label to the receiver-facing semantic union. */
|
|
28
|
+
export function directionalShadowQualityFromF32(
|
|
29
|
+
value: number,
|
|
30
|
+
angularRadiusRadians: number,
|
|
31
|
+
maxPenumbraTexels: number,
|
|
32
|
+
): DirectionalShadowQuality | undefined {
|
|
33
|
+
switch (value) {
|
|
34
|
+
case DirectionalShadowFilterValue.pcf1:
|
|
35
|
+
return { kind: 'pcf', kernel: 1 };
|
|
36
|
+
case DirectionalShadowFilterValue.pcf3:
|
|
37
|
+
return { kind: 'pcf', kernel: 3 };
|
|
38
|
+
case DirectionalShadowFilterValue.pcf5:
|
|
39
|
+
return { kind: 'pcf', kernel: 5 };
|
|
40
|
+
case DirectionalShadowFilterValue.pcssMedium:
|
|
41
|
+
return {
|
|
42
|
+
kind: 'pcss',
|
|
43
|
+
preset: 'medium',
|
|
44
|
+
angularRadiusRadians,
|
|
45
|
+
maxPenumbraTexels,
|
|
46
|
+
};
|
|
47
|
+
case DirectionalShadowFilterValue.pcssHigh:
|
|
48
|
+
return {
|
|
49
|
+
kind: 'pcss',
|
|
50
|
+
preset: 'high',
|
|
51
|
+
angularRadiusRadians,
|
|
52
|
+
maxPenumbraTexels,
|
|
53
|
+
};
|
|
54
|
+
default:
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export * from './atmosphere';
|
|
2
2
|
export * from './camera';
|
|
3
|
+
export * from './cube-camera';
|
|
3
4
|
export * from './directional-light';
|
|
4
5
|
export * from './fog';
|
|
5
6
|
export { Instances, type InstancesData } from './instances';
|
|
6
7
|
export { Layer } from './layer';
|
|
8
|
+
export * from './light-helpers';
|
|
9
|
+
export { LightProbe } from './light-probe';
|
|
7
10
|
export { Lines } from './lines';
|
|
8
11
|
export * from './mesh-filter';
|
|
9
12
|
export * from './mesh-renderer';
|
|
@@ -17,6 +20,8 @@ export {
|
|
|
17
20
|
pointShapeFromU32,
|
|
18
21
|
} from './points';
|
|
19
22
|
export { PostProcessParams } from './post-process-params';
|
|
23
|
+
export { RectAreaLight } from './rect-area-light';
|
|
24
|
+
export * from './reflection-probe';
|
|
20
25
|
export {
|
|
21
26
|
SceneInstance,
|
|
22
27
|
type SceneInstanceOverrideRecord,
|
|
@@ -14,15 +14,20 @@
|
|
|
14
14
|
// transparent to AI users) + D-S5 (Layer 1 host-side range = 0 ->
|
|
15
15
|
// invRangeSquared = 1e8 protects the 0 * Infinity = NaN intermediate).
|
|
16
16
|
|
|
17
|
-
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
17
|
+
import { err, ok, R_MIN, type Result } from '@forgeax/engine-types';
|
|
18
18
|
import { SpawnLightInvalidBoundsError } from '../errors/ecs-validation';
|
|
19
19
|
import { ShadowInvalidConfigError } from '../errors/render';
|
|
20
|
+
import { DirectionalShadowFilterValue } from './directional-shadow-filter';
|
|
20
21
|
|
|
21
22
|
export type LightValidationError = SpawnLightInvalidBoundsError | ShadowInvalidConfigError;
|
|
22
23
|
export type LightValidationResult = Result<void, LightValidationError>;
|
|
23
24
|
|
|
24
25
|
const RANGE_ZERO_FALLBACK_INV_R2 = 1e8;
|
|
25
26
|
const DEG_TO_RAD = Math.PI / 180;
|
|
27
|
+
const PCSS_RADIUS_MIN = 0.0001;
|
|
28
|
+
const PCSS_RADIUS_MAX = 0.05;
|
|
29
|
+
const PCSS_PENUMBRA_MIN = 1;
|
|
30
|
+
const PCSS_PENUMBRA_MAX = 64;
|
|
26
31
|
|
|
27
32
|
/**
|
|
28
33
|
* Convert SpotLight cone half-angle (degrees) to its cosine.
|
|
@@ -97,7 +102,9 @@ export function validateDirectionalLightData(
|
|
|
97
102
|
if (data.castShadow === false) return ok(undefined);
|
|
98
103
|
|
|
99
104
|
const mapSize = (data.mapSize as number | undefined) ?? 2048;
|
|
100
|
-
if (mapSize < 1)
|
|
105
|
+
if (mapSize < 1) {
|
|
106
|
+
return err(new ShadowInvalidConfigError('mapSize', mapSize, 1));
|
|
107
|
+
}
|
|
101
108
|
const cascadeCount = (data.cascadeCount as number | undefined) ?? 4;
|
|
102
109
|
if (cascadeCount < 1 || cascadeCount > 4 || !Number.isInteger(cascadeCount)) {
|
|
103
110
|
return err(new ShadowInvalidConfigError('cascadeCount', cascadeCount, 1, 4));
|
|
@@ -110,14 +117,65 @@ export function validateDirectionalLightData(
|
|
|
110
117
|
if (cascadeBlend < 0 || cascadeBlend > 0.5) {
|
|
111
118
|
return err(new ShadowInvalidConfigError('cascadeBlend', cascadeBlend, 0, 0.5));
|
|
112
119
|
}
|
|
113
|
-
const pcfKernelSize = (data.pcfKernelSize as number | undefined) ?? 3;
|
|
114
|
-
if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
|
|
115
|
-
return err(new ShadowInvalidConfigError('pcfKernelSize', pcfKernelSize, 1));
|
|
116
|
-
}
|
|
117
120
|
const shadowDistance = (data.shadowDistance as number | undefined) ?? 200;
|
|
118
121
|
if (shadowDistance <= 0) {
|
|
119
122
|
return err(new ShadowInvalidConfigError('shadowDistance', shadowDistance, 0, '>'));
|
|
120
123
|
}
|
|
124
|
+
const shadowFilter =
|
|
125
|
+
(data.shadowFilter as number | undefined) ?? DirectionalShadowFilterValue.pcf3;
|
|
126
|
+
const allowedFilters = Object.values(DirectionalShadowFilterValue);
|
|
127
|
+
if (!Number.isFinite(shadowFilter) || !allowedFilters.includes(shadowFilter as never)) {
|
|
128
|
+
return err(
|
|
129
|
+
new ShadowInvalidConfigError(
|
|
130
|
+
'shadowFilter',
|
|
131
|
+
shadowFilter,
|
|
132
|
+
{ kind: 'allowed-values', values: allowedFilters },
|
|
133
|
+
undefined,
|
|
134
|
+
'one of [pcf1, pcf3, pcf5, pcssMedium, pcssHigh]',
|
|
135
|
+
),
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (
|
|
139
|
+
shadowFilter === DirectionalShadowFilterValue.pcssMedium ||
|
|
140
|
+
shadowFilter === DirectionalShadowFilterValue.pcssHigh
|
|
141
|
+
) {
|
|
142
|
+
const shadowAngularRadius = (data.shadowAngularRadius as number | undefined) ?? 0.00465;
|
|
143
|
+
if (!Number.isFinite(shadowAngularRadius)) {
|
|
144
|
+
return err(
|
|
145
|
+
new ShadowInvalidConfigError('shadowAngularRadius', shadowAngularRadius, {
|
|
146
|
+
kind: 'range',
|
|
147
|
+
min: PCSS_RADIUS_MIN,
|
|
148
|
+
max: PCSS_RADIUS_MAX,
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (shadowAngularRadius < PCSS_RADIUS_MIN || shadowAngularRadius > PCSS_RADIUS_MAX) {
|
|
153
|
+
return err(
|
|
154
|
+
new ShadowInvalidConfigError('shadowAngularRadius', shadowAngularRadius, {
|
|
155
|
+
kind: 'range',
|
|
156
|
+
min: PCSS_RADIUS_MIN,
|
|
157
|
+
max: PCSS_RADIUS_MAX,
|
|
158
|
+
}),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
const maxPenumbraTexels = (data.maxPenumbraTexels as number | undefined) ?? 32;
|
|
162
|
+
if (
|
|
163
|
+
!Number.isFinite(maxPenumbraTexels) ||
|
|
164
|
+
!Number.isInteger(maxPenumbraTexels) ||
|
|
165
|
+
maxPenumbraTexels < PCSS_PENUMBRA_MIN ||
|
|
166
|
+
maxPenumbraTexels > PCSS_PENUMBRA_MAX
|
|
167
|
+
) {
|
|
168
|
+
return err(
|
|
169
|
+
new ShadowInvalidConfigError(
|
|
170
|
+
'maxPenumbraTexels',
|
|
171
|
+
maxPenumbraTexels,
|
|
172
|
+
{ kind: 'range', min: PCSS_PENUMBRA_MIN, max: PCSS_PENUMBRA_MAX },
|
|
173
|
+
undefined,
|
|
174
|
+
'a finite integer in [1, 64]',
|
|
175
|
+
),
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
121
179
|
return ok(undefined);
|
|
122
180
|
}
|
|
123
181
|
|
|
@@ -153,7 +211,15 @@ export function validateSpotLightData(
|
|
|
153
211
|
}
|
|
154
212
|
const pcfKernelSize = (data.pcfKernelSize as number | undefined) ?? 3;
|
|
155
213
|
if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
|
|
156
|
-
return err(
|
|
214
|
+
return err(
|
|
215
|
+
new ShadowInvalidConfigError(
|
|
216
|
+
'pcfKernelSize',
|
|
217
|
+
pcfKernelSize,
|
|
218
|
+
{ kind: 'lower-bound', operator: '>=', value: 1 },
|
|
219
|
+
undefined,
|
|
220
|
+
'an odd integer >= 1',
|
|
221
|
+
),
|
|
222
|
+
);
|
|
157
223
|
}
|
|
158
224
|
const shadowIntensity = (data.shadowIntensity as number | undefined) ?? 1;
|
|
159
225
|
if (!Number.isFinite(shadowIntensity) || shadowIntensity < 0 || shadowIntensity > 1) {
|
|
@@ -186,7 +252,66 @@ export function validatePointLightShadowData(
|
|
|
186
252
|
}
|
|
187
253
|
const pcfKernelSize = (data.pcfKernelSize as number | undefined) ?? 3;
|
|
188
254
|
if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
|
|
189
|
-
return err(
|
|
255
|
+
return err(
|
|
256
|
+
new ShadowInvalidConfigError(
|
|
257
|
+
'pcfKernelSize',
|
|
258
|
+
pcfKernelSize,
|
|
259
|
+
{ kind: 'lower-bound', operator: '>=', value: 1 },
|
|
260
|
+
undefined,
|
|
261
|
+
'an odd integer >= 1',
|
|
262
|
+
),
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return ok(undefined);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Validate rectangular area-light authoring facts before renderer admission. */
|
|
269
|
+
export function validateRectAreaLightData(
|
|
270
|
+
data: Readonly<Record<string, unknown>>,
|
|
271
|
+
): LightValidationResult {
|
|
272
|
+
const intensity = (data.intensity as number | undefined) ?? 1;
|
|
273
|
+
if (typeof intensity !== 'number' || !Number.isFinite(intensity) || intensity < 0) {
|
|
274
|
+
return err(new SpawnLightInvalidBoundsError('RectAreaLight', 'intensity', intensity));
|
|
275
|
+
}
|
|
276
|
+
const color = (data.color as ArrayLike<number> | undefined) ?? [1, 1, 1];
|
|
277
|
+
if (
|
|
278
|
+
color.length !== 3 ||
|
|
279
|
+
Array.from(color).some(
|
|
280
|
+
(value) => typeof value !== 'number' || !Number.isFinite(value) || value < 0,
|
|
281
|
+
)
|
|
282
|
+
) {
|
|
283
|
+
return err(new SpawnLightInvalidBoundsError('RectAreaLight', 'color', Array.from(color)));
|
|
284
|
+
}
|
|
285
|
+
for (const field of ['width', 'height', 'range'] as const) {
|
|
286
|
+
const value = (data[field] as number | undefined) ?? (field === 'range' ? 10 : 1);
|
|
287
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
|
|
288
|
+
return err(new SpawnLightInvalidBoundsError('RectAreaLight', field, value));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return ok(undefined);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Validate the fixed 27-value SH payload and minimum finite radius. */
|
|
295
|
+
export function validateLightProbeData(
|
|
296
|
+
data: Readonly<Record<string, unknown>>,
|
|
297
|
+
): LightValidationResult {
|
|
298
|
+
const irradiance = data.irradiance as ArrayLike<number> | undefined;
|
|
299
|
+
if (
|
|
300
|
+
irradiance === undefined ||
|
|
301
|
+
irradiance.length !== 27 ||
|
|
302
|
+
Array.from(irradiance).some((value) => typeof value !== 'number' || !Number.isFinite(value))
|
|
303
|
+
) {
|
|
304
|
+
return err(
|
|
305
|
+
new SpawnLightInvalidBoundsError(
|
|
306
|
+
'LightProbe',
|
|
307
|
+
'irradiance',
|
|
308
|
+
irradiance === undefined ? [] : Array.from(irradiance),
|
|
309
|
+
),
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
const radius = (data.radius as number | undefined) ?? R_MIN;
|
|
313
|
+
if (typeof radius !== 'number' || !Number.isFinite(radius) || radius < R_MIN) {
|
|
314
|
+
return err(new SpawnLightInvalidBoundsError('LightProbe', 'radius', radius));
|
|
190
315
|
}
|
|
191
316
|
return ok(undefined);
|
|
192
317
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @forgeax/engine-render - local diffuse LightProbe authoring facts.
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from '@forgeax/engine-ecs';
|
|
4
|
+
import { R_MIN } from '@forgeax/engine-types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Local diffuse irradiance probe. Transform supplies position; the 27 SH
|
|
8
|
+
* values are nine RGB groups in the fixed real-SH order.
|
|
9
|
+
*/
|
|
10
|
+
export const LightProbe = defineComponent('LightProbe', {
|
|
11
|
+
irradiance: { type: 'array<f32, 27>' },
|
|
12
|
+
radius: { type: 'f32', default: R_MIN },
|
|
13
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @forgeax/engine-render - single-sided rectangular area-light authoring facts.
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from '@forgeax/engine-ecs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Single-sided rectangular area light. Transform supplies the center and
|
|
7
|
+
* world orientation; width and height remain authored emitter dimensions.
|
|
8
|
+
*/
|
|
9
|
+
export const RectAreaLight = defineComponent('RectAreaLight', {
|
|
10
|
+
color: { type: 'array<f32, 3>', default: new Float32Array([1, 1, 1]) },
|
|
11
|
+
intensity: { type: 'f32', default: 1 },
|
|
12
|
+
width: { type: 'f32', default: 1 },
|
|
13
|
+
height: { type: 'f32', default: 1 },
|
|
14
|
+
range: { type: 'f32', default: 10 },
|
|
15
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// @forgeax/engine-render - local reflection probe vocabulary.
|
|
2
|
+
//
|
|
3
|
+
// A ReflectionProbe is an ECS authoring fact. The renderer owns its six-face
|
|
4
|
+
// capture, PMREM output, box selection, and Skylight fallback; this component
|
|
5
|
+
// never carries a GPU handle or an authored material reference.
|
|
6
|
+
|
|
7
|
+
import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
|
|
8
|
+
import { RenderIntentInvalidError } from '../errors/render';
|
|
9
|
+
|
|
10
|
+
export const REFLECTION_PROBE_UPDATE_ONCE = 0;
|
|
11
|
+
export const REFLECTION_PROBE_UPDATE_ON_CHANGE = 1;
|
|
12
|
+
export const REFLECTION_PROBE_UPDATE_CONTINUOUS = 2;
|
|
13
|
+
|
|
14
|
+
export type ReflectionProbeUpdateIntent = 'once' | 'on-change' | 'continuous';
|
|
15
|
+
|
|
16
|
+
export function reflectionProbeUpdateIntentFromF32(value: number): ReflectionProbeUpdateIntent {
|
|
17
|
+
switch (value) {
|
|
18
|
+
case REFLECTION_PROBE_UPDATE_ONCE:
|
|
19
|
+
return 'once';
|
|
20
|
+
case REFLECTION_PROBE_UPDATE_ON_CHANGE:
|
|
21
|
+
return 'on-change';
|
|
22
|
+
case REFLECTION_PROBE_UPDATE_CONTINUOUS:
|
|
23
|
+
return 'continuous';
|
|
24
|
+
default:
|
|
25
|
+
throw new RenderIntentInvalidError('ReflectionProbe', value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function reflectionProbeUpdateIntentToF32(intent: ReflectionProbeUpdateIntent): number {
|
|
30
|
+
switch (intent) {
|
|
31
|
+
case 'once':
|
|
32
|
+
return REFLECTION_PROBE_UPDATE_ONCE;
|
|
33
|
+
case 'on-change':
|
|
34
|
+
return REFLECTION_PROBE_UPDATE_ON_CHANGE;
|
|
35
|
+
case 'continuous':
|
|
36
|
+
return REFLECTION_PROBE_UPDATE_CONTINUOUS;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const ReflectionProbe = defineComponent('ReflectionProbe', {
|
|
41
|
+
halfExtents: { type: 'array<f32, 3>', default: new Float32Array([1, 1, 1]) },
|
|
42
|
+
priority: { type: 'f32', default: 0 },
|
|
43
|
+
intensity: { type: 'f32', default: 1 },
|
|
44
|
+
resolution: { type: 'u32', default: 256 },
|
|
45
|
+
updateIntent: { type: 'f32', default: REFLECTION_PROBE_UPDATE_ONCE },
|
|
46
|
+
invalidationVersion: { type: 'u32', default: 0 },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export type ReflectionProbeData = ShapeOf<SchemaOf<typeof ReflectionProbe>>;
|
|
@@ -94,6 +94,12 @@ export interface SceneInstanceState {
|
|
|
94
94
|
*/
|
|
95
95
|
readonly source: import('@forgeax/engine-types').Handle<'SceneAsset', 'shared'>;
|
|
96
96
|
|
|
97
|
+
/** Author scene identity used by instance-relative SceneEntityRef resolution. */
|
|
98
|
+
readonly sceneSourceKey?: string;
|
|
99
|
+
|
|
100
|
+
/** Stable author bindingKey to live Entity mapping for this concrete instance. */
|
|
101
|
+
readonly bindings: Map<string, EntityHandle>;
|
|
102
|
+
|
|
97
103
|
/**
|
|
98
104
|
* Reverse mapping (live `Entity` -> source `LocalEntityId`). Used by
|
|
99
105
|
* `world.setSceneOverride` to validate the member entity belongs to this
|
|
@@ -124,6 +124,9 @@ export const SpotLight = defineComponent('SpotLight', {
|
|
|
124
124
|
range: { type: 'f32', default: 10.0 },
|
|
125
125
|
innerConeDeg: { type: 'f32', default: 0 },
|
|
126
126
|
outerConeDeg: { type: 'f32', default: 45 },
|
|
127
|
+
iesProfile: { type: 'shared<IesProfileAsset>' },
|
|
128
|
+
cookie: { type: 'shared<TextureAsset>' },
|
|
129
|
+
rollDeg: { type: 'f32', default: 0 },
|
|
127
130
|
// Shadow opt-out gate: defaults to true so zero-config spawns cast shadows.
|
|
128
131
|
castShadow: { type: 'bool', default: true },
|
|
129
132
|
// 7 shadow fields aligned with the shared light shadow vocabulary.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
createExtendedLightingResourceCandidate,
|
|
4
|
+
inspectExtendedLightingResources,
|
|
5
|
+
} from '../../prepare/extended-lighting/resources';
|
|
6
|
+
import { DeviceScope } from '../device-scope';
|
|
7
|
+
|
|
8
|
+
describe('extended lighting device recovery', () => {
|
|
9
|
+
it('retires the old scope and rebuilds one accepted resource generation', async () => {
|
|
10
|
+
const oldScope = DeviceScope.create(8, 'renderer');
|
|
11
|
+
const oldResource = oldScope.ref('texture', { id: 'old' });
|
|
12
|
+
const candidate = await createExtendedLightingResourceCandidate({
|
|
13
|
+
device: undefined,
|
|
14
|
+
scope: oldScope,
|
|
15
|
+
iesSliceCount: 0,
|
|
16
|
+
cookieSliceCount: 0,
|
|
17
|
+
cookieMatrices: 0,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(candidate.ok).toBe(false);
|
|
21
|
+
expect(oldResource.isCurrent(oldScope)).toBe(true);
|
|
22
|
+
expect(inspectExtendedLightingResources(oldScope).generation).toBe(8);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -324,6 +324,123 @@ interface CubemapGpuEntry {
|
|
|
324
324
|
faceViews: readonly TextureView[];
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
interface PackedMeshLodGeometry {
|
|
328
|
+
readonly vertices: Float32Array;
|
|
329
|
+
readonly indices: Uint16Array | Uint32Array | undefined;
|
|
330
|
+
readonly lodRanges: readonly (readonly MeshGpuRange[])[] | undefined;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function packMeshLodGeometry(
|
|
334
|
+
root: TypesMeshAsset,
|
|
335
|
+
rootData: MeshRenderData,
|
|
336
|
+
lowerMeshes: readonly TypesMeshAsset[],
|
|
337
|
+
): Result<PackedMeshLodGeometry, RhiError> {
|
|
338
|
+
if (lowerMeshes.length === 0) {
|
|
339
|
+
return ok({ vertices: root.vertices, indices: root.indices, lodRanges: undefined });
|
|
340
|
+
}
|
|
341
|
+
const rootStride = rootData.layoutProjection.arrayStride;
|
|
342
|
+
const allMeshes = [root, ...lowerMeshes];
|
|
343
|
+
const lowerData: MeshRenderData[] = [];
|
|
344
|
+
for (const lower of lowerMeshes) {
|
|
345
|
+
const projected = deriveRenderDataMesh(lower);
|
|
346
|
+
if (!projected.ok) {
|
|
347
|
+
return err(
|
|
348
|
+
new RhiError({
|
|
349
|
+
code: 'asset-not-registered',
|
|
350
|
+
expected: 'every MeshAsset LOD to project to a compatible GPU layout',
|
|
351
|
+
hint: 'repair the lower-detail MeshAsset attributes before drawing the LOD chain',
|
|
352
|
+
}),
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
lowerData.push(projected.value);
|
|
356
|
+
}
|
|
357
|
+
if (
|
|
358
|
+
lowerData.some(
|
|
359
|
+
(data) =>
|
|
360
|
+
data.layoutProjection.arrayStride !== rootStride ||
|
|
361
|
+
data.submeshes.length !== rootData.submeshes.length ||
|
|
362
|
+
data.indexFormat !== rootData.indexFormat,
|
|
363
|
+
)
|
|
364
|
+
) {
|
|
365
|
+
return err(
|
|
366
|
+
new RhiError({
|
|
367
|
+
code: 'asset-not-registered',
|
|
368
|
+
expected: 'LOD meshes to share vertex/index layout and material-slot topology',
|
|
369
|
+
hint: 'reimport LOD meshes with matching attributes, index format, and submesh slots',
|
|
370
|
+
}),
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
if (allMeshes.some((mesh) => (mesh.indices === undefined) !== (root.indices === undefined))) {
|
|
374
|
+
return err(
|
|
375
|
+
new RhiError({
|
|
376
|
+
code: 'asset-not-registered',
|
|
377
|
+
expected: 'all LOD meshes to use the same indexed or non-indexed draw mode',
|
|
378
|
+
hint: 'reimport the LOD chain with consistent index data',
|
|
379
|
+
}),
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
const vertices = new Float32Array(allMeshes.reduce((sum, mesh) => sum + mesh.vertices.length, 0));
|
|
383
|
+
const ranges: MeshGpuRange[][] = [];
|
|
384
|
+
let vertexCursor = 0;
|
|
385
|
+
let indexCursor = 0;
|
|
386
|
+
const indexed = root.indices !== undefined;
|
|
387
|
+
const sourceIndices: number[] = [];
|
|
388
|
+
let requiresUint32 = root.indices instanceof Uint32Array;
|
|
389
|
+
for (let level = 0; level < allMeshes.length; level += 1) {
|
|
390
|
+
const mesh = allMeshes[level];
|
|
391
|
+
const data = level === 0 ? rootData : lowerData[level - 1];
|
|
392
|
+
if (mesh === undefined || data === undefined) continue;
|
|
393
|
+
vertices.set(mesh.vertices, vertexCursor);
|
|
394
|
+
const levelRanges: MeshGpuRange[] = [];
|
|
395
|
+
for (let submeshIndex = 0; submeshIndex < data.submeshes.length; submeshIndex += 1) {
|
|
396
|
+
const submesh = data.submeshes[submeshIndex];
|
|
397
|
+
const rootSubmesh = rootData.submeshes[submeshIndex];
|
|
398
|
+
if (
|
|
399
|
+
submesh === undefined ||
|
|
400
|
+
rootSubmesh === undefined ||
|
|
401
|
+
submesh.materialSlot !== rootSubmesh.materialSlot ||
|
|
402
|
+
submesh.topology !== rootSubmesh.topology
|
|
403
|
+
) {
|
|
404
|
+
return err(
|
|
405
|
+
new RhiError({
|
|
406
|
+
code: 'asset-not-registered',
|
|
407
|
+
expected: 'LOD submeshes to preserve root material-slot and topology identity',
|
|
408
|
+
hint: 'repair LOD material slots and primitive topology before import',
|
|
409
|
+
}),
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
levelRanges.push(
|
|
413
|
+
indexed
|
|
414
|
+
? {
|
|
415
|
+
first: indexCursor + submesh.indexOffset,
|
|
416
|
+
count: submesh.indexCount,
|
|
417
|
+
baseVertex: vertexCursor / (rootStride / 4),
|
|
418
|
+
}
|
|
419
|
+
: { first: vertexCursor / (rootStride / 4), count: submesh.vertexCount, baseVertex: 0 },
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
ranges.push(levelRanges);
|
|
423
|
+
if (indexed) {
|
|
424
|
+
const indices = mesh.indices;
|
|
425
|
+
if (indices === undefined) continue;
|
|
426
|
+
for (const value of indices) {
|
|
427
|
+
// Each LOD range carries its vertex cursor as baseVertex, so keep
|
|
428
|
+
// indices local to that LOD and apply the offset exactly once at draw.
|
|
429
|
+
sourceIndices.push(value);
|
|
430
|
+
if (value > 0xffff || indices instanceof Uint32Array) requiresUint32 = true;
|
|
431
|
+
}
|
|
432
|
+
indexCursor += indices.length;
|
|
433
|
+
}
|
|
434
|
+
vertexCursor += mesh.vertices.length;
|
|
435
|
+
}
|
|
436
|
+
const indices = indexed
|
|
437
|
+
? requiresUint32
|
|
438
|
+
? Uint32Array.from(sourceIndices)
|
|
439
|
+
: Uint16Array.from(sourceIndices)
|
|
440
|
+
: undefined;
|
|
441
|
+
return ok({ vertices, indices, lodRanges: ranges });
|
|
442
|
+
}
|
|
443
|
+
|
|
327
444
|
export interface MeshGpuHandles {
|
|
328
445
|
readonly vertexBuffer: GpuBuffer;
|
|
329
446
|
/**
|
|
@@ -374,6 +491,14 @@ export interface MeshGpuHandles {
|
|
|
374
491
|
* For single-submesh meshes this is a 1-element array (byte-identical to pre-M4).
|
|
375
492
|
*/
|
|
376
493
|
readonly submeshes: readonly import('@forgeax/engine-types').Submesh[];
|
|
494
|
+
/** Packed root + lower-detail geometry ranges in the shared mesh buffers. */
|
|
495
|
+
readonly lodRanges?: readonly (readonly MeshGpuRange[])[];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export interface MeshGpuRange {
|
|
499
|
+
readonly first: number;
|
|
500
|
+
readonly count: number;
|
|
501
|
+
readonly baseVertex: number;
|
|
377
502
|
}
|
|
378
503
|
|
|
379
504
|
/**
|
|
@@ -951,6 +1076,7 @@ export class GpuResidencyCache {
|
|
|
951
1076
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
952
1077
|
pod: TypesMeshAsset,
|
|
953
1078
|
worldId?: World | number,
|
|
1079
|
+
lodMeshes?: readonly TypesMeshAsset[],
|
|
954
1080
|
): Result<MeshGpuHandles, RhiError | AssetError | ImageError>;
|
|
955
1081
|
ensureResident(
|
|
956
1082
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
@@ -961,6 +1087,7 @@ export class GpuResidencyCache {
|
|
|
961
1087
|
handle: Handle<'MeshAsset', 'shared'> | Handle<'TextureAsset', 'shared'>,
|
|
962
1088
|
pod: TypesMeshAsset | TextureAsset,
|
|
963
1089
|
worldId: World | number = 0,
|
|
1090
|
+
lodMeshes: readonly TypesMeshAsset[] = [],
|
|
964
1091
|
): Result<TextureGpuEntry | MeshGpuHandles, RhiError | AssetError | ImageError> {
|
|
965
1092
|
const id = handleSlot(handle);
|
|
966
1093
|
// Hit: O(1) cache lookup, never re-projects (AC-09 -- deriveRenderData*
|
|
@@ -977,7 +1104,7 @@ export class GpuResidencyCache {
|
|
|
977
1104
|
if (existing !== undefined) return ok(existing);
|
|
978
1105
|
const projected = deriveRenderDataMesh(pod);
|
|
979
1106
|
if (!projected.ok) return projected;
|
|
980
|
-
return this.uploadMeshById(key, pod, projected.value);
|
|
1107
|
+
return this.uploadMeshById(key, pod, projected.value, lodMeshes);
|
|
981
1108
|
}
|
|
982
1109
|
case 'texture': {
|
|
983
1110
|
const texKey = this.worldKey(id, worldId);
|
|
@@ -1702,6 +1829,7 @@ export class GpuResidencyCache {
|
|
|
1702
1829
|
id: string | number,
|
|
1703
1830
|
mesh: TypesMeshAsset,
|
|
1704
1831
|
renderData: MeshRenderData,
|
|
1832
|
+
lodMeshes: readonly TypesMeshAsset[] = [],
|
|
1705
1833
|
): Result<MeshGpuHandles, RhiError> {
|
|
1706
1834
|
const device = this.gpuDevice;
|
|
1707
1835
|
if (device === undefined) {
|
|
@@ -1714,13 +1842,15 @@ export class GpuResidencyCache {
|
|
|
1714
1842
|
);
|
|
1715
1843
|
}
|
|
1716
1844
|
|
|
1717
|
-
const
|
|
1845
|
+
const packed = packMeshLodGeometry(mesh, renderData, lodMeshes);
|
|
1846
|
+
if (!packed.ok) return packed;
|
|
1847
|
+
const { vertices, indices, lodRanges } = packed.value;
|
|
1718
1848
|
const indexBytesUnpadded = indices === undefined ? 0 : indices.byteLength;
|
|
1719
|
-
const indexBytes =
|
|
1849
|
+
const indexBytes = ((indexBytesUnpadded + 3) >> 2) << 2;
|
|
1720
1850
|
|
|
1721
1851
|
const vboResult = device.createBuffer({
|
|
1722
1852
|
label: `mesh-${id}-vbo`,
|
|
1723
|
-
size:
|
|
1853
|
+
size: vertices.byteLength,
|
|
1724
1854
|
usage: renderData.vertexUsage,
|
|
1725
1855
|
mappedAtCreation: false,
|
|
1726
1856
|
});
|
|
@@ -1740,7 +1870,7 @@ export class GpuResidencyCache {
|
|
|
1740
1870
|
ibo = iboResult.value;
|
|
1741
1871
|
}
|
|
1742
1872
|
|
|
1743
|
-
const vboWriteResult = device.queue.writeBuffer(vbo, 0,
|
|
1873
|
+
const vboWriteResult = device.queue.writeBuffer(vbo, 0, vertices);
|
|
1744
1874
|
if (!vboWriteResult.ok) return err(vboWriteResult.error);
|
|
1745
1875
|
|
|
1746
1876
|
if (indices !== undefined) {
|
|
@@ -1766,10 +1896,10 @@ export class GpuResidencyCache {
|
|
|
1766
1896
|
const entry: MeshGpuHandles = {
|
|
1767
1897
|
vertexBuffer: this.wrapBuf(vbo),
|
|
1768
1898
|
indexBuffer: ibo === null ? null : this.wrapBuf(ibo),
|
|
1769
|
-
vboBytes:
|
|
1899
|
+
vboBytes: vertices.byteLength,
|
|
1770
1900
|
iboBytes: indices === undefined ? 0 : indexBytes,
|
|
1771
|
-
indexCount:
|
|
1772
|
-
indexFormat:
|
|
1901
|
+
indexCount: mesh.indices === undefined ? 0 : mesh.indices.length,
|
|
1902
|
+
indexFormat: indices instanceof Uint32Array ? 'uint32' : 'uint16',
|
|
1773
1903
|
layout: renderData.layoutProjection.attributes.some(
|
|
1774
1904
|
(attribute) => attribute.key === 'skinIndex' || attribute.key === 'skinWeight',
|
|
1775
1905
|
)
|
|
@@ -1778,9 +1908,10 @@ export class GpuResidencyCache {
|
|
|
1778
1908
|
layoutProjection: renderData.layoutProjection,
|
|
1779
1909
|
uvSetCount: 1 + extraUvSets,
|
|
1780
1910
|
vertexCount: mesh.vertices.byteLength / renderData.layoutProjection.arrayStride,
|
|
1781
|
-
indexed: indices !== undefined,
|
|
1911
|
+
indexed: mesh.indices !== undefined,
|
|
1782
1912
|
topology: renderData.submeshes[0]?.topology ?? 'triangle-list',
|
|
1783
1913
|
submeshes: renderData.submeshes,
|
|
1914
|
+
...(lodRanges === undefined ? {} : { lodRanges }),
|
|
1784
1915
|
};
|
|
1785
1916
|
this.meshGpuHandles.set(id, entry);
|
|
1786
1917
|
this.meshResidencyEpoch += 1;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type DeviceResourceKind,
|
|
3
|
+
DeviceResourceRef,
|
|
4
|
+
DeviceScope,
|
|
5
|
+
type DeviceScopeReceipt,
|
|
6
|
+
type DeviceScopeState,
|
|
7
|
+
type LifecycleFailure,
|
|
8
|
+
type LifecycleResourceSpec,
|
|
9
|
+
type LifecycleResult,
|
|
10
|
+
LifecycleTransaction,
|
|
11
|
+
type ResourceRef,
|
|
12
|
+
} from './device-scope';
|