@forgeax/engine-render 0.1.20 → 0.1.21
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 +215 -0
- package/dist/.tsbuildinfo +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 +21 -18
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +9 -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 +3 -0
- 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-4XINDLAY.mjs → chunk-5YADUCA7.mjs} +1552 -1361
- package/dist/chunk-5YADUCA7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-6OPXDQ2E.mjs} +364 -51
- package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
- package/dist/{chunk-M2MP4ZOU.mjs → chunk-BXBQQKFQ.mjs} +3 -9
- package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FS2KNUQH.mjs} +548 -6
- package/dist/chunk-FS2KNUQH.mjs.map +1 -0
- 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 +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +5826 -1003
- package/dist/construct-renderer.mjs.map +1 -1
- 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/render.d.ts +141 -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/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.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +0 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +19 -17
- 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 +28 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +51 -0
- 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.mjs +1 -1
- package/dist/light-buffer-layout.d.ts +10 -1
- package/dist/light-buffer-layout.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 +14 -4
- 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-spec.d.ts +40 -7
- package/dist/pipeline-spec.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/record/frame-lighting.d.ts +27 -32
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +28 -14
- 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 +10 -4
- 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 +8 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +22 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +43 -2
- 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 +72 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -4
- 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/projection.d.ts +91 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/render-contract.d.ts +49 -7
- 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 +42 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +58 -17
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +17 -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/render-scene.d.ts +14 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- 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/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/index.mjs +3 -3
- package/dist/typed-render-graph-primitives.d.ts +1 -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 +2 -2
- 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 +7 -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__/device-feature-admission.unit.test.ts +73 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/factory-contract.integration.test.ts +255 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
- 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__/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__/material-observation.integration.test.ts +101 -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__/public-surface.test-d.ts +10 -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-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -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 +18 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
- 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 +48 -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 +132 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +11 -2
- 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 +232 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -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 +377 -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__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/assembly/device-feature-admission.ts +73 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +877 -286
- package/src/assembly/host-contract.ts +25 -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/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 +2 -0
- package/src/components/light-helpers.ts +81 -7
- package/src/components/reflection-probe.ts +49 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +12 -0
- package/src/errors/render.ts +286 -142
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/visibility.ts +25 -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 +1 -0
- package/src/gpu-driven/production-raster.ts +1 -3
- package/src/gpu-scene.ts +8 -1
- package/src/hdrp-buffers.ts +165 -59
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +148 -0
- package/src/inspection-types.ts +56 -0
- package/src/instances-derived-bounds.ts +171 -0
- package/src/light-buffer-layout.ts +20 -5
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +106 -17
- package/src/pipeline/standard-forward-lane.ts +46 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +157 -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 +34 -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 +77 -0
- package/src/pipeline/standard-pipeline.ts +122 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-spec.ts +84 -21
- package/src/point-shadow-inspection.ts +55 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +367 -427
- package/src/record/frame-snapshot.ts +35 -27
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +261 -74
- 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 +21 -12
- package/src/record/main-pass-geometry.ts +120 -80
- package/src/record/main-pass-material.ts +95 -9
- package/src/record/main-pass-sprite-draws.ts +54 -25
- package/src/record/main-pass.ts +71 -15
- package/src/record/render-context.ts +72 -0
- package/src/record/shadow-pass.ts +17 -28
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +893 -44
- package/src/record/view-ubo.ts +63 -28
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/projection.ts +281 -0
- package/src/render-contract.ts +76 -5
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +117 -2
- package/src/render-system-extract.ts +557 -100
- package/src/render-system.ts +1095 -66
- package/src/renderer.ts +222 -0
- package/src/scene/render-scene.ts +115 -9
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- 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/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +5 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +15 -9
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Texture, TextureView } from '@forgeax/engine-rhi';
|
|
2
|
+
import type { RenderTargetDescriptor } from './contracts';
|
|
3
|
+
|
|
4
|
+
/** Renderer-private physical storage for one logical target generation. */
|
|
5
|
+
export interface RenderTargetPhysical {
|
|
6
|
+
readonly generation: number;
|
|
7
|
+
readonly descriptor: RenderTargetDescriptor;
|
|
8
|
+
readonly texture: Texture;
|
|
9
|
+
readonly view: TextureView;
|
|
10
|
+
readonly mipViews: readonly TextureView[];
|
|
11
|
+
readonly colorTextures: readonly Texture[];
|
|
12
|
+
readonly faceViews: readonly TextureView[];
|
|
13
|
+
readonly depthTextures: readonly Texture[];
|
|
14
|
+
readonly depthViews: readonly TextureView[];
|
|
15
|
+
readonly resolveTexture?: Texture;
|
|
16
|
+
readonly resolveView: TextureView;
|
|
17
|
+
readonly resolveFaceViews: readonly TextureView[];
|
|
18
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { RenderError } from '../errors/render';
|
|
2
|
+
import { RenderTargetOperationFailedError, RenderTargetStateInvalidError } from '../errors/render';
|
|
3
|
+
import type { RenderResult } from '../render-contract';
|
|
4
|
+
import type { RenderTarget } from './contracts';
|
|
5
|
+
|
|
6
|
+
export interface RenderTargetReadbackReceipt {
|
|
7
|
+
readonly frameId: number;
|
|
8
|
+
readonly deviceGeneration: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderTargetReadbackTicketInput {
|
|
12
|
+
readonly frameId?: number;
|
|
13
|
+
deviceGeneration: number;
|
|
14
|
+
readonly mipLevel: number;
|
|
15
|
+
readonly face?: number;
|
|
16
|
+
readonly width: number;
|
|
17
|
+
readonly height: number;
|
|
18
|
+
readonly bytesPerPixel: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RenderTargetReadbackTicket {
|
|
22
|
+
readonly target: RenderTarget;
|
|
23
|
+
frameId: number | undefined;
|
|
24
|
+
deviceGeneration: number;
|
|
25
|
+
readonly mipLevel: number;
|
|
26
|
+
readonly face?: number;
|
|
27
|
+
readonly width: number;
|
|
28
|
+
readonly height: number;
|
|
29
|
+
readonly bytesPerRow: number;
|
|
30
|
+
readonly byteLength: number;
|
|
31
|
+
consumed: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RenderTargetReadbackResult {
|
|
35
|
+
readonly bytes: Uint8Array;
|
|
36
|
+
readonly frameId: number;
|
|
37
|
+
readonly deviceGeneration: number;
|
|
38
|
+
readonly mipLevel: number;
|
|
39
|
+
readonly face?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function invalidTicket(
|
|
43
|
+
ticket: RenderTargetReadbackTicket,
|
|
44
|
+
reason: 'uninitialized' | 'generation-mismatch' | 'destroyed',
|
|
45
|
+
): RenderResult<never, RenderError> {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: new RenderTargetStateInvalidError({
|
|
49
|
+
operation: 'readback',
|
|
50
|
+
reason,
|
|
51
|
+
state: reason === 'destroyed' ? 'destroyed' : 'active',
|
|
52
|
+
generation: ticket.deviceGeneration,
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function bindRenderTargetReadbackTicket(
|
|
58
|
+
ticket: RenderTargetReadbackTicket,
|
|
59
|
+
receipt: RenderTargetReadbackReceipt,
|
|
60
|
+
): RenderResult<void, RenderError> {
|
|
61
|
+
if (ticket.consumed) return invalidTicket(ticket, 'destroyed');
|
|
62
|
+
if (ticket.frameId !== undefined) {
|
|
63
|
+
return invalidTicket(ticket, 'generation-mismatch');
|
|
64
|
+
}
|
|
65
|
+
ticket.frameId = receipt.frameId;
|
|
66
|
+
ticket.deviceGeneration = receipt.deviceGeneration;
|
|
67
|
+
return { ok: true, value: undefined };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function createRenderTargetReadbackTicket(
|
|
71
|
+
target: RenderTarget,
|
|
72
|
+
input: RenderTargetReadbackTicketInput,
|
|
73
|
+
): RenderResult<RenderTargetReadbackTicket, RenderError> {
|
|
74
|
+
if (
|
|
75
|
+
(input.frameId !== undefined && (!Number.isInteger(input.frameId) || input.frameId < 0)) ||
|
|
76
|
+
!Number.isInteger(input.deviceGeneration) ||
|
|
77
|
+
input.deviceGeneration < 0 ||
|
|
78
|
+
!Number.isInteger(input.mipLevel) ||
|
|
79
|
+
input.mipLevel < 0 ||
|
|
80
|
+
!Number.isInteger(input.width) ||
|
|
81
|
+
input.width < 1 ||
|
|
82
|
+
!Number.isInteger(input.height) ||
|
|
83
|
+
input.height < 1 ||
|
|
84
|
+
!Number.isInteger(input.bytesPerPixel) ||
|
|
85
|
+
input.bytesPerPixel < 1
|
|
86
|
+
) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
error: new RenderTargetOperationFailedError({
|
|
90
|
+
operation: 'readback',
|
|
91
|
+
stage: 'copy',
|
|
92
|
+
generation: input.deviceGeneration,
|
|
93
|
+
cause: new Error('readback dimensions and identity must be non-negative integers'),
|
|
94
|
+
recovery: 'retry',
|
|
95
|
+
}),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const unalignedRowBytes = input.width * input.bytesPerPixel;
|
|
99
|
+
const bytesPerRow = Math.ceil(unalignedRowBytes / 256) * 256;
|
|
100
|
+
return {
|
|
101
|
+
ok: true,
|
|
102
|
+
value: {
|
|
103
|
+
target,
|
|
104
|
+
frameId: input.frameId,
|
|
105
|
+
deviceGeneration: input.deviceGeneration,
|
|
106
|
+
mipLevel: input.mipLevel,
|
|
107
|
+
...(input.face === undefined ? {} : { face: input.face }),
|
|
108
|
+
width: input.width,
|
|
109
|
+
height: input.height,
|
|
110
|
+
bytesPerRow,
|
|
111
|
+
byteLength: bytesPerRow * input.height,
|
|
112
|
+
consumed: false,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function completeRenderTargetReadback(
|
|
118
|
+
ticket: RenderTargetReadbackTicket,
|
|
119
|
+
receipt: RenderTargetReadbackReceipt,
|
|
120
|
+
bytes: Uint8Array,
|
|
121
|
+
): RenderResult<RenderTargetReadbackResult, RenderError> {
|
|
122
|
+
if (ticket.consumed) return invalidTicket(ticket, 'destroyed');
|
|
123
|
+
if (
|
|
124
|
+
ticket.frameId === undefined ||
|
|
125
|
+
receipt.frameId !== ticket.frameId ||
|
|
126
|
+
receipt.deviceGeneration !== ticket.deviceGeneration
|
|
127
|
+
) {
|
|
128
|
+
return invalidTicket(ticket, 'generation-mismatch');
|
|
129
|
+
}
|
|
130
|
+
if (bytes.byteLength !== ticket.byteLength) {
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
error: new RenderTargetOperationFailedError({
|
|
134
|
+
operation: 'readback',
|
|
135
|
+
stage: 'copy',
|
|
136
|
+
generation: ticket.deviceGeneration,
|
|
137
|
+
cause: new Error(`expected ${ticket.byteLength} bytes, received ${bytes.byteLength}`),
|
|
138
|
+
recovery: 'retry',
|
|
139
|
+
}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
ticket.consumed = true;
|
|
143
|
+
return {
|
|
144
|
+
ok: true,
|
|
145
|
+
value: {
|
|
146
|
+
bytes,
|
|
147
|
+
frameId: ticket.frameId,
|
|
148
|
+
deviceGeneration: ticket.deviceGeneration,
|
|
149
|
+
mipLevel: ticket.mipLevel,
|
|
150
|
+
...(ticket.face === undefined ? {} : { face: ticket.face }),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
DirectionalLight,
|
|
15
15
|
MeshFilter,
|
|
16
16
|
MeshRenderer,
|
|
17
|
+
PointLight,
|
|
17
18
|
TONEMAP_LINEAR,
|
|
18
19
|
} from '../../components';
|
|
19
20
|
import { constructRendererHost, type RhiBackendPack } from '../../construct-renderer';
|
|
@@ -57,8 +58,10 @@ interface TransmissionCase {
|
|
|
57
58
|
readonly thicknessTexture?: number;
|
|
58
59
|
readonly masked?: boolean;
|
|
59
60
|
readonly overlap?: boolean;
|
|
60
|
-
readonly
|
|
61
|
+
readonly renderPath?: 'forward' | 'deferred';
|
|
61
62
|
readonly surfaceQuat?: readonly [number, number, number, number];
|
|
63
|
+
readonly directionalLight?: boolean;
|
|
64
|
+
readonly localLight?: boolean;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
function textureAsset(value: number): TextureAsset {
|
|
@@ -106,6 +109,7 @@ async function renderCase(testCase: TransmissionCase): Promise<{
|
|
|
106
109
|
readonly pixel: readonly [number, number, number, number];
|
|
107
110
|
readonly passNames: readonly string[];
|
|
108
111
|
readonly observation: boolean;
|
|
112
|
+
readonly errors: readonly string[];
|
|
109
113
|
}> {
|
|
110
114
|
let device: GPUDevice | undefined;
|
|
111
115
|
let configuredDevice: GPUDevice | undefined;
|
|
@@ -157,7 +161,7 @@ async function renderCase(testCase: TransmissionCase): Promise<{
|
|
|
157
161
|
{
|
|
158
162
|
standardProfile: {
|
|
159
163
|
...DEFAULT_STANDARD_PROFILE,
|
|
160
|
-
|
|
164
|
+
renderPath: testCase.renderPath ?? DEFAULT_STANDARD_PROFILE.renderPath,
|
|
161
165
|
},
|
|
162
166
|
},
|
|
163
167
|
{ shaderManifestUrl: ENGINE_MANIFEST_URL },
|
|
@@ -172,6 +176,10 @@ async function renderCase(testCase: TransmissionCase): Promise<{
|
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
const { renderer } = host.value;
|
|
179
|
+
const errors: string[] = [];
|
|
180
|
+
const unsubscribe = renderer.subscribe((event) => {
|
|
181
|
+
if (event.kind === 'error') errors.push(event.error.code);
|
|
182
|
+
});
|
|
175
183
|
const world = new World();
|
|
176
184
|
const lease = renderer.attach(world);
|
|
177
185
|
if (!lease.ok) throw lease.error;
|
|
@@ -277,12 +285,22 @@ async function renderCase(testCase: TransmissionCase): Promise<{
|
|
|
277
285
|
);
|
|
278
286
|
expect(cameraEntity.ok, `${testCase.name}: camera spawn must succeed`).toBe(true);
|
|
279
287
|
if (!cameraEntity.ok) throw cameraEntity.error;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
288
|
+
if (testCase.directionalLight !== false) {
|
|
289
|
+
const lightEntity = world.spawn({
|
|
290
|
+
component: DirectionalLight,
|
|
291
|
+
data: { direction: [0, 0, -1], color: [1, 1, 1], intensity: 1, castShadow: false },
|
|
292
|
+
});
|
|
293
|
+
expect(lightEntity.ok, `${testCase.name}: light spawn must succeed`).toBe(true);
|
|
294
|
+
if (!lightEntity.ok) throw lightEntity.error;
|
|
295
|
+
}
|
|
296
|
+
if (testCase.localLight === true) {
|
|
297
|
+
const localLightEntity = world.spawn(
|
|
298
|
+
{ component: Transform, data: { pos: [0, 0, 1] } },
|
|
299
|
+
{ component: PointLight, data: { intensity: 8, range: 10 } },
|
|
300
|
+
);
|
|
301
|
+
expect(localLightEntity.ok, `${testCase.name}: local light spawn must succeed`).toBe(true);
|
|
302
|
+
if (!localLightEntity.ok) throw localLightEntity.error;
|
|
303
|
+
}
|
|
286
304
|
world.update().unwrap();
|
|
287
305
|
const drawn = renderer.draw({
|
|
288
306
|
leases: [lease.value],
|
|
@@ -299,10 +317,12 @@ async function renderCase(testCase: TransmissionCase): Promise<{
|
|
|
299
317
|
const renderDevice = configuredDevice ?? device;
|
|
300
318
|
const passNames = renderer.inspect().perFramePassNames;
|
|
301
319
|
expect(renderer.inspect().renderScene.projectionRecords).toBeGreaterThanOrEqual(1);
|
|
320
|
+
unsubscribe();
|
|
302
321
|
return {
|
|
303
322
|
pixel: await readCenter(renderDevice, target),
|
|
304
323
|
passNames,
|
|
305
324
|
observation: observation.ok,
|
|
325
|
+
errors,
|
|
306
326
|
};
|
|
307
327
|
}
|
|
308
328
|
|
|
@@ -403,9 +423,9 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
403
423
|
);
|
|
404
424
|
}, 120_000);
|
|
405
425
|
|
|
406
|
-
it('exercises
|
|
407
|
-
const
|
|
408
|
-
name: '
|
|
426
|
+
it('exercises both Standard render paths and transmission-before-BLEND overlap order', async () => {
|
|
427
|
+
const forward = await renderCase({
|
|
428
|
+
name: 'forward',
|
|
409
429
|
transmission: 1,
|
|
410
430
|
ior: 1.5,
|
|
411
431
|
thickness: 0.5,
|
|
@@ -413,10 +433,10 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
413
433
|
attenuationColor: [0.7, 0.8, 0.9],
|
|
414
434
|
attenuationDistance: 2,
|
|
415
435
|
overlap: true,
|
|
416
|
-
|
|
436
|
+
renderPath: 'forward',
|
|
417
437
|
});
|
|
418
|
-
const
|
|
419
|
-
name: '
|
|
438
|
+
const deferred = await renderCase({
|
|
439
|
+
name: 'deferred',
|
|
420
440
|
transmission: 1,
|
|
421
441
|
ior: 1.5,
|
|
422
442
|
thickness: 0.5,
|
|
@@ -424,14 +444,33 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
424
444
|
attenuationColor: [0.7, 0.8, 0.9],
|
|
425
445
|
attenuationDistance: 2,
|
|
426
446
|
overlap: true,
|
|
427
|
-
|
|
447
|
+
renderPath: 'deferred',
|
|
428
448
|
});
|
|
429
|
-
const transmissionIndex =
|
|
430
|
-
const transparentIndex =
|
|
449
|
+
const transmissionIndex = forward.passNames.indexOf('transmission-forward');
|
|
450
|
+
const transparentIndex = forward.passNames.indexOf('transparent');
|
|
431
451
|
expect(transmissionIndex).toBeGreaterThanOrEqual(0);
|
|
432
452
|
expect(transparentIndex).toBeGreaterThan(transmissionIndex);
|
|
433
|
-
expect(
|
|
434
|
-
expect(
|
|
435
|
-
|
|
453
|
+
expect(deferred.pixel.every(Number.isFinite)).toBe(true);
|
|
454
|
+
expect(forward.pixel.every(Number.isFinite)).toBe(true);
|
|
455
|
+
}, 120_000);
|
|
456
|
+
|
|
457
|
+
it('submits a real clustered local-light frame through the Standard front door', async () => {
|
|
458
|
+
const clustered = await renderCase({
|
|
459
|
+
name: 'clustered-local-light',
|
|
460
|
+
transmission: 0,
|
|
461
|
+
ior: 1.5,
|
|
462
|
+
thickness: 0,
|
|
463
|
+
roughness: 0.4,
|
|
464
|
+
attenuationColor: [1, 1, 1],
|
|
465
|
+
directionalLight: false,
|
|
466
|
+
localLight: true,
|
|
467
|
+
renderPath: 'forward',
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
expect(clustered.passNames).toEqual(
|
|
471
|
+
expect.arrayContaining(['cluster-membership-producer', 'main', 'output-transform']),
|
|
472
|
+
);
|
|
473
|
+
expect(clustered.observation).toBe(true);
|
|
474
|
+
expect(clustered.errors).toEqual([]);
|
|
436
475
|
}, 120_000);
|
|
437
476
|
});
|
|
@@ -222,6 +222,8 @@ export function addTypedScenePass(
|
|
|
222
222
|
projectorSampler:
|
|
223
223
|
internal.spotLightProjector?.sampler ?? internal.volumetricFog?.projectorSampler,
|
|
224
224
|
},
|
|
225
|
+
true,
|
|
226
|
+
internal.standardLighting,
|
|
225
227
|
);
|
|
226
228
|
if (groups.viewBindGroup !== null) {
|
|
227
229
|
options.gpuDriven?.encode(groups.viewBindGroup, pass, resources);
|
|
@@ -696,7 +698,7 @@ export function addTypedOutputTransformPass(
|
|
|
696
698
|
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
697
699
|
input: RenderPipelineTarget,
|
|
698
700
|
output: RenderPipelineTarget,
|
|
699
|
-
options: { readonly outputOnly?: boolean; readonly
|
|
701
|
+
options: { readonly outputOnly?: boolean; readonly dither?: boolean } = {},
|
|
700
702
|
): Result<void, RenderGraphError> {
|
|
701
703
|
const outputOnly = options.outputOnly ?? false;
|
|
702
704
|
return addTypedFullscreenPass(graph, {
|
|
@@ -706,7 +708,7 @@ export function addTypedOutputTransformPass(
|
|
|
706
708
|
output,
|
|
707
709
|
outputOnly,
|
|
708
710
|
rawSwapchainOutput: outputOnly,
|
|
709
|
-
...(options.
|
|
711
|
+
...(options.dither !== undefined
|
|
710
712
|
? {
|
|
711
713
|
paramsTransform: (params: Uint8Array | undefined): Uint8Array | undefined => {
|
|
712
714
|
if (params === undefined || params.byteLength !== 16) return params;
|
|
@@ -715,7 +717,7 @@ export function addTypedOutputTransformPass(
|
|
|
715
717
|
transformed.buffer,
|
|
716
718
|
transformed.byteOffset,
|
|
717
719
|
transformed.byteLength,
|
|
718
|
-
).setFloat32(12, 1, true);
|
|
720
|
+
).setFloat32(12, options.dither === true ? 1 : 0, true);
|
|
719
721
|
return transformed;
|
|
720
722
|
},
|
|
721
723
|
}
|
|
@@ -13,7 +13,7 @@ import { createRenderPipelineTarget, type RenderPipelineTarget } from './render-
|
|
|
13
13
|
import { resolveDirectionalShadowAtlasGrid } from './typed-shadow-atlas';
|
|
14
14
|
|
|
15
15
|
export interface TypedShadowTargets {
|
|
16
|
-
readonly directional
|
|
16
|
+
readonly directional?: RenderPipelineTarget | undefined;
|
|
17
17
|
readonly spot: RenderPipelineTarget;
|
|
18
18
|
readonly point?: RenderPipelineTarget | undefined;
|
|
19
19
|
}
|
|
@@ -44,44 +44,50 @@ export function addTypedShadowPasses(
|
|
|
44
44
|
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
45
45
|
topology: RenderPipelineTopology,
|
|
46
46
|
): Result<TypedShadowTargets, RenderGraphError> {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
let directional: RenderPipelineTarget | undefined;
|
|
48
|
+
if (topology.shadow.directional !== 'disabled') {
|
|
49
|
+
const { mapSize, cascadeCount } = topology.shadow.directional;
|
|
50
|
+
const atlasGrid = resolveDirectionalShadowAtlasGrid(cascadeCount);
|
|
51
|
+
const target = createRenderPipelineTarget(graph, 'directional-shadow-depth', {
|
|
52
|
+
format: 'depth32float',
|
|
53
|
+
size: {
|
|
54
|
+
width: mapSize * atlasGrid.columns,
|
|
55
|
+
height: mapSize * atlasGrid.rows,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
if (!target.ok) return target;
|
|
59
|
+
const directionalTarget = target.value;
|
|
60
|
+
directional = directionalTarget;
|
|
61
|
+
for (let cascade = 0; cascade < cascadeCount; cascade += 1) {
|
|
62
|
+
const col = cascade % atlasGrid.columns;
|
|
63
|
+
const row = Math.floor(cascade / atlasGrid.columns);
|
|
64
|
+
const added = recordShadowPass(
|
|
65
|
+
graph,
|
|
66
|
+
`shadowCascade${cascade}`,
|
|
67
|
+
directionalTarget,
|
|
68
|
+
cascade === 0 ? 'clear' : 'load',
|
|
69
|
+
({ pass, frame }) =>
|
|
70
|
+
encodeDirectionalShadowPass(frame as never, pass, cascade, {
|
|
71
|
+
x: col * mapSize,
|
|
72
|
+
y: row * mapSize,
|
|
73
|
+
w: mapSize,
|
|
74
|
+
h: mapSize,
|
|
75
|
+
}),
|
|
76
|
+
(frame) => !(frame as _InternalRenderPipelineContext).directionalShadowCacheReuse,
|
|
77
|
+
);
|
|
78
|
+
if (!added.ok) return added;
|
|
79
|
+
}
|
|
80
|
+
const observation = graph.addCopyPass('directional-shadow-observation', {
|
|
81
|
+
accesses: [{ resource: directionalTarget.view, usage: 'copy-src' }],
|
|
82
|
+
encode: ({ frame, resources }) => {
|
|
83
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
84
|
+
const texture = resources.texture(directionalTarget.texture);
|
|
85
|
+
if (!texture.ok) throw texture.error;
|
|
86
|
+
internal.pipelineState.perPassResources.shadowTexture = texture.value;
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
if (!observation.ok) return observation;
|
|
74
90
|
}
|
|
75
|
-
const observation = graph.addCopyPass('directional-shadow-observation', {
|
|
76
|
-
accesses: [{ resource: directional.value.view, usage: 'copy-src' }],
|
|
77
|
-
encode: ({ frame, resources }) => {
|
|
78
|
-
const internal = frame as _InternalRenderPipelineContext;
|
|
79
|
-
const texture = resources.texture(directional.value.texture);
|
|
80
|
-
if (!texture.ok) throw texture.error;
|
|
81
|
-
internal.pipelineState.perPassResources.shadowTexture = texture.value;
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
if (!observation.ok) return observation;
|
|
85
91
|
|
|
86
92
|
let point: RenderPipelineTarget | undefined;
|
|
87
93
|
if (topology.shadow.pointCount > 0) {
|
|
@@ -148,7 +154,7 @@ export function addTypedShadowPasses(
|
|
|
148
154
|
|
|
149
155
|
const spot = createRenderPipelineTarget(graph, 'spot-shadow-depth', {
|
|
150
156
|
format: 'depth32float',
|
|
151
|
-
size: { width: topology.shadow.
|
|
157
|
+
size: { width: topology.shadow.spotMapSize * 2, height: topology.shadow.spotMapSize * 2 },
|
|
152
158
|
});
|
|
153
159
|
if (!spot.ok) return spot;
|
|
154
160
|
for (let spotIndex = 0; spotIndex < Math.max(1, topology.shadow.spotCount); spotIndex += 1) {
|
|
@@ -162,5 +168,5 @@ export function addTypedShadowPasses(
|
|
|
162
168
|
if (!added.ok) return added;
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
return ok({ directional
|
|
171
|
+
return ok({ directional, spot: spot.value, point });
|
|
166
172
|
}
|
package/src/volume/passes.ts
CHANGED
|
@@ -89,7 +89,7 @@ export interface VolumetricFogPassInputs {
|
|
|
89
89
|
readonly density: GraphTextureView;
|
|
90
90
|
readonly params: GraphBuffer;
|
|
91
91
|
readonly view: GraphBuffer;
|
|
92
|
-
readonly directionalShadow
|
|
92
|
+
readonly directionalShadow?: GraphTextureView;
|
|
93
93
|
readonly spotShadow: GraphTextureView;
|
|
94
94
|
readonly pointLights: GraphBuffer;
|
|
95
95
|
readonly spotLights: GraphBuffer;
|
|
@@ -166,7 +166,7 @@ function importVolumeInputs(
|
|
|
166
166
|
topology: RenderPipelineTopology,
|
|
167
167
|
linearHdr: RenderPipelineTarget,
|
|
168
168
|
sceneDepth: GraphTextureView,
|
|
169
|
-
directionalShadow: GraphTextureView,
|
|
169
|
+
directionalShadow: GraphTextureView | undefined,
|
|
170
170
|
spotShadow: GraphTextureView,
|
|
171
171
|
selectedLightKind: 'directional' | 'point' | 'spot' | undefined,
|
|
172
172
|
): Result<ImportedVolumeInputs | undefined, RenderGraphError> {
|
|
@@ -268,7 +268,7 @@ function importVolumeInputs(
|
|
|
268
268
|
density: density.value,
|
|
269
269
|
params: params.value,
|
|
270
270
|
view: view.value,
|
|
271
|
-
directionalShadow,
|
|
271
|
+
...(directionalShadow === undefined ? {} : { directionalShadow }),
|
|
272
272
|
spotShadow,
|
|
273
273
|
pointLights: pointLights.value,
|
|
274
274
|
spotLights: spotLights.value,
|
|
@@ -281,7 +281,7 @@ export function addAuthoredVolumetricFogPasses(
|
|
|
281
281
|
topology: RenderPipelineTopology,
|
|
282
282
|
linearHdr: RenderPipelineTarget,
|
|
283
283
|
sceneDepth: GraphTextureView,
|
|
284
|
-
directionalShadow: GraphTextureView,
|
|
284
|
+
directionalShadow: GraphTextureView | undefined,
|
|
285
285
|
spotShadow: GraphTextureView,
|
|
286
286
|
): Result<void, RenderGraphError> {
|
|
287
287
|
// A paired Point+Spot volume stores the Spot shadow lane as well. The
|
|
@@ -320,6 +320,15 @@ export function addVolumetricFogPasses(
|
|
|
320
320
|
const packedLayers = Math.ceil(inputs.resources.extent.depth / VOLUME_PACKING_Z);
|
|
321
321
|
const resolvedDispatchX = Math.ceil(inputs.resources.resolvedExtent.width / 8);
|
|
322
322
|
const resolvedDispatchY = Math.ceil(inputs.resources.resolvedExtent.height / 8);
|
|
323
|
+
// Point-light volume injection has no cube-array shadow sampler. It keeps
|
|
324
|
+
// the directional cascade count at zero and therefore needs only a valid
|
|
325
|
+
// 2D depth binding; use the always-present spot target as the inert binding
|
|
326
|
+
// when directional shadows are disabled. Directional selection still uses
|
|
327
|
+
// its own target whenever one exists, and spot selection uses spotShadow.
|
|
328
|
+
const shadowResource =
|
|
329
|
+
inputs.selectedLightKind === 'spot'
|
|
330
|
+
? inputs.spotShadow
|
|
331
|
+
: (inputs.directionalShadow ?? inputs.spotShadow);
|
|
323
332
|
let inject: ComputeState | undefined;
|
|
324
333
|
let integrate: ComputeState | undefined;
|
|
325
334
|
let temporal: ComputeState | undefined;
|
|
@@ -330,8 +339,7 @@ export function addVolumetricFogPasses(
|
|
|
330
339
|
{ resource: inputs.params, usage: 'uniform-read' },
|
|
331
340
|
{ resource: inputs.view, usage: 'uniform-read' },
|
|
332
341
|
{
|
|
333
|
-
resource:
|
|
334
|
-
inputs.selectedLightKind === 'spot' ? inputs.spotShadow : inputs.directionalShadow,
|
|
342
|
+
resource: shadowResource,
|
|
335
343
|
usage: 'sampled-read',
|
|
336
344
|
},
|
|
337
345
|
{ resource: inputs.spotLights, usage: 'storage-read' },
|
|
@@ -359,9 +367,7 @@ export function addVolumetricFogPasses(
|
|
|
359
367
|
{ binding: 7, visibility: 4, buffer: { type: 'read-only-storage' } },
|
|
360
368
|
{ binding: 8, visibility: 4, buffer: { type: 'read-only-storage' } },
|
|
361
369
|
]);
|
|
362
|
-
const shadow = resources.textureView(
|
|
363
|
-
inputs.selectedLightKind === 'spot' ? inputs.spotShadow : inputs.directionalShadow,
|
|
364
|
-
);
|
|
370
|
+
const shadow = resources.textureView(shadowResource);
|
|
365
371
|
const params = resources.buffer(inputs.params);
|
|
366
372
|
const view = resources.buffer(inputs.view);
|
|
367
373
|
const spotLights = resources.buffer(inputs.spotLights);
|