@forgeax/engine-render 0.1.29 → 0.1.31
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 +248 -21
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +1 -1
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +4 -3
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-host.d.ts +6 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +6 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +26 -3
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +24 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/recovery-attempt.d.ts +1 -6
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/capture/scene-projection.d.ts +41 -0
- package/dist/capture/scene-projection.d.ts.map +1 -0
- package/dist/{chunk-BQVQOQJH.mjs → chunk-7MQ3XBSP.mjs} +20 -14
- package/dist/chunk-7MQ3XBSP.mjs.map +1 -0
- package/dist/{chunk-S4DNKQYQ.mjs → chunk-C3DDSXYK.mjs} +86 -33
- package/dist/chunk-C3DDSXYK.mjs.map +1 -0
- package/dist/{chunk-BTWH7BP4.mjs → chunk-FUUO4UND.mjs} +73 -29
- package/dist/chunk-FUUO4UND.mjs.map +1 -0
- package/dist/{chunk-NRNXBLIJ.mjs → chunk-JRBDO2KB.mjs} +46 -6
- package/dist/chunk-JRBDO2KB.mjs.map +1 -0
- package/dist/{chunk-NICXSHAT.mjs → chunk-MDQJPY3T.mjs} +8 -6
- package/dist/chunk-MDQJPY3T.mjs.map +1 -0
- package/dist/{chunk-JQTSEI3Z.mjs → chunk-NO4WZCAH.mjs} +3 -3
- package/dist/chunk-NO4WZCAH.mjs.map +1 -0
- package/dist/{chunk-FUODTTIA.mjs → chunk-PSEQ6QPH.mjs} +621 -108
- package/dist/chunk-PSEQ6QPH.mjs.map +1 -0
- package/dist/{chunk-33XZFTQU.mjs → chunk-S5UE2T5P.mjs} +48 -6
- package/dist/chunk-S5UE2T5P.mjs.map +1 -0
- package/dist/components/directional-light.d.ts +2 -2
- package/dist/components/dynamic-resolution.d.ts +15 -0
- package/dist/components/dynamic-resolution.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -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 +1 -0
- package/dist/components/reflection-probe.d.ts.map +1 -1
- package/dist/components/skylight.d.ts +4 -1
- package/dist/components/skylight.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +2172 -796
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +2 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +2 -2
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/background.d.ts +3 -2
- package/dist/environment/background.d.ts.map +1 -1
- package/dist/environment/ibl.d.ts +11 -0
- package/dist/environment/ibl.d.ts.map +1 -0
- package/dist/environment/storage.d.ts +14 -0
- package/dist/environment/storage.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +2 -2
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +35 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +7 -0
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +18 -1
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +24 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -0
- package/dist/gpu-driven/material-bindings.d.ts +7 -0
- package/dist/gpu-driven/material-bindings.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts +2 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +27 -6
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-resource.d.ts +5 -2
- package/dist/gpu-resource.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +2 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +3 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +83 -81
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7 -5
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +16 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/internal.mjs +6 -6
- package/dist/material-row.d.ts +10 -0
- package/dist/material-row.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +3 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-extent.d.ts +51 -0
- package/dist/pipeline/render-extent.d.ts.map +1 -0
- package/dist/pipeline/standard-build-context.d.ts +7 -0
- package/dist/pipeline/standard-build-context.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts +3 -2
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +2 -1
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +3 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/post-process-errors.d.ts +9 -2
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/extended-lighting/resources.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +3 -8
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +3 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +6 -3
- package/dist/record/main-pass-material.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/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +9 -1
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -3
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -2
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +5 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/background.d.ts +14 -0
- package/dist/reflection/background.d.ts.map +1 -0
- package/dist/reflection/filter.d.ts.map +1 -1
- package/dist/reflection/projection.d.ts +1 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts +4 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +47 -32
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +17 -1
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +9 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +29 -2
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +2 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-config.d.ts +8 -6
- package/dist/ssao-config.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts +15 -0
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -0
- package/dist/temporal/temporal-view.d.ts +6 -2
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +6 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +1 -0
- package/dist/volume/component.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/__tests__/capture-scene-projection.unit.test.ts +24 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +15 -24
- package/src/__tests__/device-loss-fanout.unit.test.ts +43 -0
- package/src/__tests__/dynamic-geometry-batch.unit.test.ts +157 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +36 -0
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +81 -0
- package/src/__tests__/factory-contract.integration.test.ts +164 -1
- package/src/__tests__/frame-observation.contract.test.ts +21 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +1 -1
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +20 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +11 -6
- package/src/__tests__/gpu-driven-production.integration.test.ts +13 -25
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +15 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +14 -1
- package/src/__tests__/gpu-resource-scope.unit.test.ts +71 -0
- package/src/__tests__/gpu-scene.unit.test.ts +55 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +5 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +8 -0
- package/src/__tests__/morph-neutral-admission.unit.test.ts +19 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +6 -1
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -5
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +216 -5
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +68 -1
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +12 -10
- package/src/__tests__/reflection-probe-box.dawn.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +9 -0
- package/src/__tests__/reflection-probe-orientation.dawn.test.ts +294 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +5 -15
- package/src/__tests__/reflection-probe-updates.unit.test.ts +129 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +3 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +5 -1
- package/src/__tests__/render-extent.unit.test.ts +63 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +3 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +173 -9
- package/src/__tests__/shader-manifest-fixture.ts +6 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +8 -1
- package/src/__tests__/specular-environment-scale.dawn.test.ts +4 -2
- package/src/__tests__/ssao-config.unit.test.ts +7 -0
- package/src/__tests__/ssao-surface.dawn.test.ts +252 -0
- package/src/__tests__/ssr-cube-silhouette.dawn.test.ts +270 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +51 -43
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +4 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +10 -5
- package/src/__tests__/ssr-graph-topology.unit.test.ts +2 -2
- package/src/__tests__/ssr-hiz.browser.test.ts +1 -1
- package/src/__tests__/ssr-hiz.dawn.test.ts +1 -1
- package/src/__tests__/ssr-spatial.integration.test.ts +1 -1
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +40 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +238 -1
- package/src/__tests__/standard-profile-oracle.unit.test.ts +27 -0
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +6 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +5 -1
- package/src/__tests__/taa-stability-feedback.ts +1 -0
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +2 -2
- package/src/__tests__/temporal-view.unit.test.ts +17 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +57 -0
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +62 -13
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +7 -7
- package/src/assembly/atmosphere-shader-prewarm.ts +3 -2
- package/src/assembly/device-feature-admission.ts +9 -4
- package/src/assembly/dynamic-geometry-host.ts +236 -163
- package/src/assembly/host-contract.ts +9 -0
- package/src/assembly/material/assembly.ts +350 -6
- package/src/assembly/material/pipeline-helpers.ts +100 -0
- package/src/assembly/material-shader-policy.ts +39 -18
- package/src/assembly/recovery/device-loss-fanout.ts +5 -0
- package/src/assembly/recovery/recovery-attempt.ts +2 -29
- package/src/assembly/recovery/renderer-recover.ts +6 -9
- package/src/assembly/renderer-facade.ts +22 -1
- package/src/assembly/shader-prewarm-policy.ts +14 -1
- package/src/assembly/webgpu-ready.ts +28 -19
- package/src/assembly/webgpu-renderer.ts +95 -95
- package/src/capture/scene-projection.ts +37 -0
- package/src/components/__tests__/dynamic-resolution-schema.unit.test.ts +65 -0
- package/src/components/__tests__/light-radius.integration.test.ts +59 -0
- package/src/components/directional-light.ts +3 -3
- package/src/components/dynamic-resolution.ts +67 -0
- package/src/components/index.ts +1 -0
- package/src/components/light-helpers.ts +6 -1
- package/src/components/reflection-probe.ts +1 -0
- package/src/components/skylight.ts +4 -1
- package/src/device/device-scope.ts +13 -7
- package/src/device/gpu-residency.ts +11 -11
- package/src/dynamic-geometry.ts +13 -8
- package/src/environment/background.ts +30 -12
- package/src/environment/ibl.ts +211 -0
- package/src/environment/storage.ts +63 -0
- package/src/errors/gpu-driven.ts +10 -3
- package/src/errors/render.ts +64 -0
- package/src/extract/camera.ts +12 -1
- package/src/extract/contracts.ts +10 -0
- package/src/extract/gpu-driven.ts +72 -17
- package/src/gpu-driven/batch-topology.ts +33 -11
- package/src/gpu-driven/material-artifacts.ts +179 -0
- package/src/gpu-driven/material-bindings.ts +41 -0
- package/src/gpu-driven/prepared-draw.ts +13 -2
- package/src/gpu-driven/production-raster.ts +681 -164
- package/src/gpu-resource.ts +21 -2
- package/src/gpu-scene-schema.ts +11 -2
- package/src/gpu-scene.ts +14 -3
- package/src/hdrp-buffers.ts +69 -0
- package/src/ibl/IblPipelineCache.ts +5 -0
- package/src/ibl/skylight-bind-group.ts +27 -17
- package/src/index.ts +92 -81
- package/src/inspection-types.ts +16 -1
- package/src/material-row.ts +60 -11
- package/src/pbr-pipeline.ts +13 -2
- package/src/pipeline/render-extent.ts +111 -0
- package/src/pipeline/standard-build-context.ts +7 -0
- package/src/pipeline/standard-forward-lane.ts +41 -24
- package/src/pipeline/standard-pipeline.ts +47 -18
- package/src/pipeline/standard-post.ts +4 -0
- package/src/pipeline/standard-profile.ts +2 -1
- package/src/pipeline-builder.ts +12 -3
- package/src/plugin.ts +4 -0
- package/src/post-process-errors.ts +26 -18
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +2 -2
- package/src/prepare/extended-lighting/resources.ts +3 -3
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +68 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +45 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +9 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +47 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +7 -3
- package/src/record/__tests__/temporal-payload.unit.test.ts +2 -0
- package/src/record/frame-lighting.ts +3 -1
- package/src/record/frame-snapshot.ts +13 -11
- package/src/record/frame.ts +150 -74
- package/src/record/main-pass-geometry.ts +60 -9
- package/src/record/main-pass-material.ts +47 -19
- package/src/record/main-pass.ts +63 -4
- package/src/record/prepared-material-bindings.ts +4 -0
- package/src/record/recovery-pipeline.ts +56 -0
- package/src/record/render-context.ts +34 -3
- package/src/record/shadow-pass.ts +187 -50
- package/src/record/typed-frame-graph.ts +60 -3
- package/src/record/view-ubo.ts +1 -1
- package/src/recovery/render-system-candidate.ts +54 -11
- package/src/reflection/background.ts +151 -0
- package/src/reflection/filter.ts +3 -0
- package/src/reflection/projection.ts +16 -6
- package/src/reflection/record-owner.ts +282 -86
- package/src/render-contract.ts +50 -32
- package/src/render-graph-primitives.ts +28 -3
- package/src/render-pipeline.ts +20 -1
- package/src/render-system-extract-tail.ts +23 -3
- package/src/render-system-extract.ts +127 -42
- package/src/render-system.ts +35 -7
- package/src/scene/render-scene.ts +8 -0
- package/src/ssao-config.ts +25 -8
- package/src/ssr/graph.ts +78 -58
- package/src/temporal/gpu.ts +5 -0
- package/src/temporal/standard-scene-data.ts +7 -1
- package/src/temporal/target-coverage-attachment.ts +72 -0
- package/src/temporal/temporal-view.ts +10 -4
- package/src/temporal/view.ts +12 -2
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +24 -9
- package/src/typed-render-graph-primitives.ts +38 -0
- package/src/volume/component.ts +1 -0
- package/src/volume/passes.ts +3 -3
- package/dist/chunk-33XZFTQU.mjs.map +0 -1
- package/dist/chunk-BQVQOQJH.mjs.map +0 -1
- package/dist/chunk-BTWH7BP4.mjs.map +0 -1
- package/dist/chunk-FUODTTIA.mjs.map +0 -1
- package/dist/chunk-JQTSEI3Z.mjs.map +0 -1
- package/dist/chunk-NICXSHAT.mjs.map +0 -1
- package/dist/chunk-NRNXBLIJ.mjs.map +0 -1
- package/dist/chunk-S4DNKQYQ.mjs.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** Immutable dimensions shared by every Standard graph consumer. */
|
|
2
|
+
export interface RenderExtent {
|
|
3
|
+
readonly outputWidth: number;
|
|
4
|
+
readonly outputHeight: number;
|
|
5
|
+
readonly internalWidth: number;
|
|
6
|
+
readonly internalHeight: number;
|
|
7
|
+
readonly scale: number;
|
|
8
|
+
readonly generation: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderExtentInput {
|
|
12
|
+
readonly outputWidth: number;
|
|
13
|
+
readonly outputHeight: number;
|
|
14
|
+
readonly requestedScale: number;
|
|
15
|
+
readonly generation: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type RenderExtentDomain = 'internal' | 'output' | 'authoring';
|
|
19
|
+
|
|
20
|
+
/** Project the immutable extent into a graph texture descriptor size. */
|
|
21
|
+
export function renderExtentSize(
|
|
22
|
+
extent: RenderExtent,
|
|
23
|
+
domain: RenderExtentDomain,
|
|
24
|
+
): { readonly width: number; readonly height: number } {
|
|
25
|
+
if (domain === 'internal') {
|
|
26
|
+
return { width: extent.internalWidth, height: extent.internalHeight };
|
|
27
|
+
}
|
|
28
|
+
return { width: extent.outputWidth, height: extent.outputHeight };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type StandardLightingLane = 'direct' | 'clustered' | 'cpu-webgl2';
|
|
32
|
+
|
|
33
|
+
export interface StandardExtentDomainPlan {
|
|
34
|
+
readonly extent: RenderExtent;
|
|
35
|
+
readonly lane: StandardLightingLane;
|
|
36
|
+
readonly topologyKey: string;
|
|
37
|
+
readonly dynamicDelta: 0 | 1;
|
|
38
|
+
readonly domains: {
|
|
39
|
+
readonly internal: { readonly width: number; readonly height: number };
|
|
40
|
+
readonly output: { readonly width: number; readonly height: number };
|
|
41
|
+
readonly authoring: { readonly width: number; readonly height: number };
|
|
42
|
+
};
|
|
43
|
+
readonly resources: readonly {
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly domain: 'internal' | 'output' | 'authoring';
|
|
46
|
+
}[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const MIN_SCALE = 0.5;
|
|
50
|
+
const MAX_SCALE = 1;
|
|
51
|
+
const SCALE_STEPS = 32;
|
|
52
|
+
const AXIS_ALIGNMENT = 8;
|
|
53
|
+
|
|
54
|
+
function alignedAxis(output: number, scale: number): number {
|
|
55
|
+
return Math.max(AXIS_ALIGNMENT, Math.floor((output * scale) / AXIS_ALIGNMENT) * AXIS_ALIGNMENT);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function finiteDimension(value: number): number {
|
|
59
|
+
return Math.max(1, Math.floor(value));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Derive the one immutable Standard extent before graph construction. */
|
|
63
|
+
export function deriveRenderExtent(input: RenderExtentInput): RenderExtent {
|
|
64
|
+
const outputWidth = finiteDimension(input.outputWidth);
|
|
65
|
+
const outputHeight = finiteDimension(input.outputHeight);
|
|
66
|
+
const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, input.requestedScale));
|
|
67
|
+
const scale = Math.round(clamped * SCALE_STEPS) / SCALE_STEPS;
|
|
68
|
+
const nativeSurface = outputWidth < AXIS_ALIGNMENT || outputHeight < AXIS_ALIGNMENT;
|
|
69
|
+
const internalWidth = nativeSurface ? outputWidth : alignedAxis(outputWidth, scale);
|
|
70
|
+
const internalHeight = nativeSurface ? outputHeight : alignedAxis(outputHeight, scale);
|
|
71
|
+
return Object.freeze({
|
|
72
|
+
outputWidth,
|
|
73
|
+
outputHeight,
|
|
74
|
+
internalWidth,
|
|
75
|
+
internalHeight,
|
|
76
|
+
scale: nativeSurface ? 1 : scale,
|
|
77
|
+
generation: input.generation,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Describe Standard's shared internal/output/authoring domain assignment. */
|
|
82
|
+
export function standardExtentDomainPlan(
|
|
83
|
+
extent: RenderExtent,
|
|
84
|
+
lane: StandardLightingLane,
|
|
85
|
+
): StandardExtentDomainPlan {
|
|
86
|
+
const domains = {
|
|
87
|
+
internal: { width: extent.internalWidth, height: extent.internalHeight },
|
|
88
|
+
output: { width: extent.outputWidth, height: extent.outputHeight },
|
|
89
|
+
authoring: { width: extent.outputWidth, height: extent.outputHeight },
|
|
90
|
+
} as const;
|
|
91
|
+
return Object.freeze({
|
|
92
|
+
extent,
|
|
93
|
+
lane,
|
|
94
|
+
topologyKey: `standard:${extent.internalWidth}x${extent.internalHeight}:${extent.outputWidth}x${extent.outputHeight}:g${extent.generation}`,
|
|
95
|
+
dynamicDelta: extent.scale === 1 ? 0 : 1,
|
|
96
|
+
domains,
|
|
97
|
+
resources: Object.freeze([
|
|
98
|
+
{ name: 'scene', domain: 'internal' },
|
|
99
|
+
{ name: 'depth', domain: 'internal' },
|
|
100
|
+
{ name: 'g-buffer', domain: 'internal' },
|
|
101
|
+
{ name: 'scene-temporal', domain: 'internal' },
|
|
102
|
+
{ name: 'ssao', domain: 'internal' },
|
|
103
|
+
{ name: 'taa-history', domain: 'output' },
|
|
104
|
+
{ name: 'bloom', domain: 'output' },
|
|
105
|
+
{ name: 'output', domain: 'output' },
|
|
106
|
+
{ name: 'overlay', domain: 'output' },
|
|
107
|
+
{ name: 'observation', domain: 'output' },
|
|
108
|
+
{ name: 'shadow', domain: 'authoring' },
|
|
109
|
+
] satisfies StandardExtentDomainPlan['resources']),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RenderPipelineBuildContext, RenderPipelineFrame } from '../render-pipeline';
|
|
2
|
+
import type { TargetCoverageAttachment } from '../temporal/target-coverage-attachment';
|
|
3
|
+
|
|
4
|
+
/** Standard-only graph input; custom pipeline consumers never see coverage. */
|
|
5
|
+
export type StandardPipelineBuildContext = RenderPipelineBuildContext<RenderPipelineFrame> & {
|
|
6
|
+
readonly targetCoverage?: TargetCoverageAttachment;
|
|
7
|
+
};
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
} from '../gpu-texture-usage';
|
|
14
14
|
import type {
|
|
15
15
|
RenderPipeline,
|
|
16
|
-
RenderPipelineBuildContext,
|
|
17
16
|
RenderPipelineFrame,
|
|
18
17
|
RenderPipelineTopology,
|
|
19
18
|
} from '../render-pipeline';
|
|
@@ -28,6 +27,7 @@ import {
|
|
|
28
27
|
createStandardSceneDataTarget,
|
|
29
28
|
standardTemporalLaneAdmission,
|
|
30
29
|
} from '../temporal/standard-scene-data';
|
|
30
|
+
import { addTargetCoveragePass } from '../temporal/target-coverage-attachment';
|
|
31
31
|
import {
|
|
32
32
|
addTransmissionBackdropPasses,
|
|
33
33
|
addTransmissionBackdropTemporalPass,
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
} from '../typed-render-graph-primitives';
|
|
43
43
|
import { addTypedShadowPasses } from '../typed-shadow-passes';
|
|
44
44
|
import { addAuthoredVolumetricFogPasses } from '../volume/passes';
|
|
45
|
+
import { renderExtentSize } from './render-extent';
|
|
46
|
+
import type { StandardPipelineBuildContext } from './standard-build-context';
|
|
45
47
|
import {
|
|
46
48
|
addStandardClusterMembershipPass,
|
|
47
49
|
importStandardClusterBuffers,
|
|
@@ -59,7 +61,7 @@ function target(
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
function buildUrp(
|
|
62
|
-
context:
|
|
64
|
+
context: StandardPipelineBuildContext,
|
|
63
65
|
topology: RenderPipelineTopology,
|
|
64
66
|
lighting: StandardTopologyInputValue,
|
|
65
67
|
): ReturnType<RenderPipeline['build']> {
|
|
@@ -67,6 +69,9 @@ function buildUrp(
|
|
|
67
69
|
const surface = importRenderPipelineSurface(graph, topology);
|
|
68
70
|
if (!surface.ok) return surface;
|
|
69
71
|
|
|
72
|
+
const internalSize =
|
|
73
|
+
topology.extent === undefined ? 'surface' : renderExtentSize(topology.extent, 'internal');
|
|
74
|
+
|
|
70
75
|
const clearOnly = topology.clearOnly === true;
|
|
71
76
|
const msaa = !clearOnly && topology.camera.antialias === 'msaa' && topology.lane.multisample;
|
|
72
77
|
const hdr =
|
|
@@ -94,7 +99,7 @@ function buildUrp(
|
|
|
94
99
|
|
|
95
100
|
const depth = target(graph, 'scene-depth', {
|
|
96
101
|
format: 'depth24plus-stencil8',
|
|
97
|
-
size:
|
|
102
|
+
size: internalSize,
|
|
98
103
|
sampleCount: msaa ? 4 : 1,
|
|
99
104
|
});
|
|
100
105
|
if (!depth.ok) return depth;
|
|
@@ -111,7 +116,7 @@ function buildUrp(
|
|
|
111
116
|
: hdr || fxaa || linearLdr || msaa || rawOnly || needsTemporalIntermediate
|
|
112
117
|
? target(graph, 'scene-color', {
|
|
113
118
|
format: sceneFormat,
|
|
114
|
-
size:
|
|
119
|
+
size: internalSize,
|
|
115
120
|
sampleCount: 1,
|
|
116
121
|
domain: 'linear-ldr',
|
|
117
122
|
...(sceneFormat === topology.surface.storageFormat &&
|
|
@@ -131,7 +136,7 @@ function buildUrp(
|
|
|
131
136
|
const scene = msaa
|
|
132
137
|
? target(graph, 'scene-color-msaa', {
|
|
133
138
|
format: sceneFormat,
|
|
134
|
-
size:
|
|
139
|
+
size: internalSize,
|
|
135
140
|
sampleCount: 4,
|
|
136
141
|
domain: 'linear-ldr',
|
|
137
142
|
...(sceneFormat === topology.surface.storageFormat &&
|
|
@@ -145,7 +150,7 @@ function buildUrp(
|
|
|
145
150
|
const reflectionFallback = topology.reflectionFallback?.enabled
|
|
146
151
|
? target(graph, 'reflection-fallback-linear-hdr', {
|
|
147
152
|
format: 'rgba16float',
|
|
148
|
-
size:
|
|
153
|
+
size: internalSize,
|
|
149
154
|
sampleCount: scene.value.sampleCount,
|
|
150
155
|
domain: 'linear-hdr',
|
|
151
156
|
usage:
|
|
@@ -191,22 +196,22 @@ function buildUrp(
|
|
|
191
196
|
const clusterReads =
|
|
192
197
|
clusterBuffers.value === null ? [] : standardClusterReadAccesses(clusterBuffers.value);
|
|
193
198
|
|
|
194
|
-
const
|
|
195
|
-
topology.atmosphere === true
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
reflectionFallback.value === undefined
|
|
205
|
-
?
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
})
|
|
209
|
-
|
|
199
|
+
const atmosphere =
|
|
200
|
+
topology.atmosphere === true ? addAtmosphereBackground(graph, scene.value) : ok(undefined);
|
|
201
|
+
if (!atmosphere.ok) return atmosphere;
|
|
202
|
+
if (atmosphere.value === undefined) {
|
|
203
|
+
const skybox = addTypedSkyboxPass(graph, scene.value);
|
|
204
|
+
if (!skybox.ok) return skybox;
|
|
205
|
+
}
|
|
206
|
+
const gpuDriven = context.projectGpuDriven({
|
|
207
|
+
format: scene.value.format,
|
|
208
|
+
sampleCount: scene.value.sampleCount,
|
|
209
|
+
...(reflectionFallback.value === undefined
|
|
210
|
+
? {}
|
|
211
|
+
: {
|
|
212
|
+
additionalColorFormats: [reflectionFallback.value.format],
|
|
213
|
+
}),
|
|
214
|
+
});
|
|
210
215
|
if (!gpuDriven.ok) return gpuDriven;
|
|
211
216
|
const transmissionDemand = transmissionDemandForTopology(topology);
|
|
212
217
|
const transmissionActive = resolveTransmissionBackdropTopology({
|
|
@@ -214,6 +219,7 @@ function buildUrp(
|
|
|
214
219
|
sourceSampleCount: scene.value.sampleCount,
|
|
215
220
|
}).active;
|
|
216
221
|
const main = addTypedScenePass(graph, {
|
|
222
|
+
environment: atmosphere.value,
|
|
217
223
|
name: 'main',
|
|
218
224
|
color: scene.value,
|
|
219
225
|
...(reflectionFallback.value === undefined
|
|
@@ -265,12 +271,18 @@ function buildUrp(
|
|
|
265
271
|
);
|
|
266
272
|
}
|
|
267
273
|
const temporal =
|
|
268
|
-
temporalDemand.targetCount === 1
|
|
274
|
+
temporalDemand.targetCount === 1
|
|
275
|
+
? createStandardSceneDataTarget(graph, topology.extent)
|
|
276
|
+
: ok(undefined);
|
|
269
277
|
if (!temporal.ok) return temporal;
|
|
270
278
|
if (temporal.value !== undefined) {
|
|
271
279
|
const producer = addStandardSceneDataPass(graph, temporal.value.temporal, depth.value);
|
|
272
280
|
if (!producer.ok) return producer;
|
|
273
281
|
}
|
|
282
|
+
if (context.targetCoverage !== undefined) {
|
|
283
|
+
const coverage = addTargetCoveragePass(graph, context.targetCoverage);
|
|
284
|
+
if (!coverage.ok) return coverage;
|
|
285
|
+
}
|
|
274
286
|
|
|
275
287
|
const transmission = addTransmissionBackdropPasses({
|
|
276
288
|
graph,
|
|
@@ -283,6 +295,7 @@ function buildUrp(
|
|
|
283
295
|
if (!transmission.ok) return transmission;
|
|
284
296
|
if (transmission.value.topology.active) {
|
|
285
297
|
const transmissionPass = addTypedScenePass(graph, {
|
|
298
|
+
environment: atmosphere.value,
|
|
286
299
|
name: 'transmission-forward',
|
|
287
300
|
color: scene.value,
|
|
288
301
|
depth: depth.value,
|
|
@@ -307,6 +320,7 @@ function buildUrp(
|
|
|
307
320
|
if (!transmissionPass.ok) return transmissionPass;
|
|
308
321
|
|
|
309
322
|
const transparentPass = addTypedScenePass(graph, {
|
|
323
|
+
environment: atmosphere.value,
|
|
310
324
|
name: 'transparent',
|
|
311
325
|
color: scene.value,
|
|
312
326
|
depth: depth.value,
|
|
@@ -401,9 +415,12 @@ function buildUrp(
|
|
|
401
415
|
depth.value,
|
|
402
416
|
surface.value,
|
|
403
417
|
temporal.value?.temporal,
|
|
418
|
+
undefined,
|
|
419
|
+
context.targetCoverage?.coverage,
|
|
420
|
+
context.targetCoverage?.depth,
|
|
404
421
|
);
|
|
405
422
|
if (!post.ok) return post;
|
|
406
|
-
const cubeCaptures = context.contributeCubeCaptures?.();
|
|
423
|
+
const cubeCaptures = context.contributeCubeCaptures?.(atmosphere.value);
|
|
407
424
|
if (cubeCaptures !== undefined && !cubeCaptures.ok) return cubeCaptures;
|
|
408
425
|
return ok(undefined);
|
|
409
426
|
}
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
createStandardSceneDataTarget,
|
|
32
32
|
standardTemporalLaneAdmission,
|
|
33
33
|
} from '../temporal/standard-scene-data';
|
|
34
|
+
import { addTargetCoveragePass } from '../temporal/target-coverage-attachment';
|
|
34
35
|
import {
|
|
35
36
|
addTransmissionBackdropPasses,
|
|
36
37
|
addTransmissionBackdropTemporalPass,
|
|
@@ -46,6 +47,8 @@ import {
|
|
|
46
47
|
} from '../typed-render-graph-primitives';
|
|
47
48
|
import { addTypedShadowPasses } from '../typed-shadow-passes';
|
|
48
49
|
import { addAuthoredVolumetricFogPasses } from '../volume/passes';
|
|
50
|
+
import { renderExtentSize } from './render-extent';
|
|
51
|
+
import type { StandardPipelineBuildContext } from './standard-build-context';
|
|
49
52
|
import { buildStandardForwardLane } from './standard-forward-lane';
|
|
50
53
|
import {
|
|
51
54
|
addStandardClusterMembershipPass,
|
|
@@ -160,13 +163,15 @@ function target(
|
|
|
160
163
|
}
|
|
161
164
|
|
|
162
165
|
function buildStandardDeferredLane(
|
|
163
|
-
context:
|
|
166
|
+
context: StandardPipelineBuildContext,
|
|
164
167
|
topology: RenderPipelineTopology,
|
|
165
168
|
lighting: StandardTopologyInputValue,
|
|
166
169
|
): ReturnType<RenderPipeline['build']> {
|
|
167
170
|
const graph = context.graph;
|
|
168
171
|
const surface = importRenderPipelineSurface(graph, topology);
|
|
169
172
|
if (!surface.ok) return surface;
|
|
173
|
+
const internalSize =
|
|
174
|
+
topology.extent === undefined ? 'surface' : renderExtentSize(topology.extent, 'internal');
|
|
170
175
|
const buffers = importStandardClusterBuffers(graph, lighting);
|
|
171
176
|
if (!buffers.ok) return buffers;
|
|
172
177
|
const membership =
|
|
@@ -186,7 +191,7 @@ function buildStandardDeferredLane(
|
|
|
186
191
|
|
|
187
192
|
const depth = target(graph, 'hdrp-depth', {
|
|
188
193
|
format: 'depth24plus-stencil8',
|
|
189
|
-
size:
|
|
194
|
+
size: internalSize,
|
|
190
195
|
});
|
|
191
196
|
if (!depth.ok) return depth;
|
|
192
197
|
const depthSample = graph.view(depth.value.texture, {
|
|
@@ -197,26 +202,26 @@ function buildStandardDeferredLane(
|
|
|
197
202
|
if (!depthSample.ok) return depthSample;
|
|
198
203
|
const gbuffer0 = target(graph, 'gbuffer-normal-roughness', {
|
|
199
204
|
format: DEFERRED_COLOR_FORMATS[0] ?? 'rgba16float',
|
|
200
|
-
size:
|
|
205
|
+
size: internalSize,
|
|
201
206
|
});
|
|
202
207
|
if (!gbuffer0.ok) return gbuffer0;
|
|
203
208
|
const gbuffer1 = target(graph, 'gbuffer-albedo-metallic', {
|
|
204
209
|
format: DEFERRED_COLOR_FORMATS[1] ?? 'rgba8unorm',
|
|
205
|
-
size:
|
|
210
|
+
size: internalSize,
|
|
206
211
|
});
|
|
207
212
|
if (!gbuffer1.ok) return gbuffer1;
|
|
208
213
|
const gbuffer2 = target(graph, 'gbuffer-specular-response-ao', {
|
|
209
214
|
format: DEFERRED_COLOR_FORMATS[2] ?? 'rgba16float',
|
|
210
|
-
size:
|
|
215
|
+
size: internalSize,
|
|
211
216
|
});
|
|
212
217
|
if (!gbuffer2.ok) return gbuffer2;
|
|
213
|
-
const scene = target(graph, 'hdrp-scene-color', { format: 'rgba16float', size:
|
|
218
|
+
const scene = target(graph, 'hdrp-scene-color', { format: 'rgba16float', size: internalSize });
|
|
214
219
|
if (!scene.ok) return scene;
|
|
215
220
|
const reflectionFallback =
|
|
216
221
|
topology.reflectionFallback?.enabled === true || topology.ssr?.status === 'admitted'
|
|
217
222
|
? target(graph, 'reflection-fallback-linear-hdr', {
|
|
218
223
|
format: 'rgba16float',
|
|
219
|
-
size:
|
|
224
|
+
size: internalSize,
|
|
220
225
|
domain: 'linear-hdr',
|
|
221
226
|
})
|
|
222
227
|
: ok(undefined);
|
|
@@ -252,6 +257,11 @@ function buildStandardDeferredLane(
|
|
|
252
257
|
const gpuDriven = context.projectGpuDriven({
|
|
253
258
|
format: scene.value.format,
|
|
254
259
|
sampleCount: scene.value.sampleCount,
|
|
260
|
+
...(reflectionFallback.value === undefined
|
|
261
|
+
? {}
|
|
262
|
+
: {
|
|
263
|
+
additionalColorFormats: [reflectionFallback.value.format],
|
|
264
|
+
}),
|
|
255
265
|
});
|
|
256
266
|
if (!gpuDriven.ok) return gpuDriven;
|
|
257
267
|
const gbuffer = addTypedScenePass(graph, {
|
|
@@ -283,11 +293,13 @@ function buildStandardDeferredLane(
|
|
|
283
293
|
|
|
284
294
|
// Initialize the background before receiver lighting. The skybox recorder
|
|
285
295
|
// has no depth attachment, so placing it later would cover lit geometry.
|
|
286
|
-
const
|
|
287
|
-
topology.atmosphere === true
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
296
|
+
const atmosphere =
|
|
297
|
+
topology.atmosphere === true ? addAtmosphereBackground(graph, scene.value) : ok(undefined);
|
|
298
|
+
if (!atmosphere.ok) return atmosphere;
|
|
299
|
+
if (atmosphere.value === undefined) {
|
|
300
|
+
const skybox = addTypedSkyboxPass(graph, scene.value);
|
|
301
|
+
if (!skybox.ok) return skybox;
|
|
302
|
+
}
|
|
291
303
|
|
|
292
304
|
// The lighting lane is the deferred Standard receiver. It deliberately
|
|
293
305
|
// selects Forward passes for the same material handles that wrote the
|
|
@@ -297,6 +309,7 @@ function buildStandardDeferredLane(
|
|
|
297
309
|
// the later forward lane excludes these handles so SSR composition is not
|
|
298
310
|
// overwritten by a second draw.
|
|
299
311
|
const lightingPass = addTypedScenePass(graph, {
|
|
312
|
+
environment: atmosphere.value,
|
|
300
313
|
name: 'lighting',
|
|
301
314
|
color: scene.value,
|
|
302
315
|
colorTargets: [
|
|
@@ -333,12 +346,18 @@ function buildStandardDeferredLane(
|
|
|
333
346
|
// blur. Insert it before the spatial chain so the graph dependency order is
|
|
334
347
|
// explicit and one producer serves every temporal consumer.
|
|
335
348
|
const temporal =
|
|
336
|
-
temporalDemand.targetCount === 1
|
|
349
|
+
temporalDemand.targetCount === 1
|
|
350
|
+
? createStandardSceneDataTarget(graph, topology.extent)
|
|
351
|
+
: ok(undefined);
|
|
337
352
|
if (!temporal.ok) return temporal;
|
|
338
353
|
if (temporal.value !== undefined) {
|
|
339
354
|
const producer = addStandardSceneDataPass(graph, temporal.value.temporal, depth.value);
|
|
340
355
|
if (!producer.ok) return producer;
|
|
341
356
|
}
|
|
357
|
+
if (context.targetCoverage !== undefined) {
|
|
358
|
+
const coverage = addTargetCoveragePass(graph, context.targetCoverage);
|
|
359
|
+
if (!coverage.ok) return coverage;
|
|
360
|
+
}
|
|
342
361
|
|
|
343
362
|
const sceneOutput: RenderPipelineTarget = scene.value;
|
|
344
363
|
let secondaryReactivity: GraphTextureView | undefined;
|
|
@@ -409,6 +428,7 @@ function buildStandardDeferredLane(
|
|
|
409
428
|
buffers.value === null ? [] : [...standardClusterReadAccesses(buffers.value)];
|
|
410
429
|
|
|
411
430
|
const forward = addTypedScenePass(graph, {
|
|
431
|
+
environment: atmosphere.value,
|
|
412
432
|
name: 'forward',
|
|
413
433
|
color: sceneOutput,
|
|
414
434
|
depth: depth.value,
|
|
@@ -449,6 +469,7 @@ function buildStandardDeferredLane(
|
|
|
449
469
|
if (!transmission.ok) return transmission;
|
|
450
470
|
if (transmission.value.topology.active) {
|
|
451
471
|
const transmissionPass = addTypedScenePass(graph, {
|
|
472
|
+
environment: atmosphere.value,
|
|
452
473
|
name: 'transmission-forward',
|
|
453
474
|
color: sceneOutput,
|
|
454
475
|
depth: depth.value,
|
|
@@ -478,6 +499,7 @@ function buildStandardDeferredLane(
|
|
|
478
499
|
if (!transmissionPass.ok) return transmissionPass;
|
|
479
500
|
|
|
480
501
|
const transparentPass = addTypedScenePass(graph, {
|
|
502
|
+
environment: atmosphere.value,
|
|
481
503
|
name: 'transparent',
|
|
482
504
|
color: sceneOutput,
|
|
483
505
|
depth: depth.value,
|
|
@@ -570,9 +592,11 @@ function buildStandardDeferredLane(
|
|
|
570
592
|
surface.value,
|
|
571
593
|
temporal.value?.temporal,
|
|
572
594
|
secondaryReactivity,
|
|
595
|
+
context.targetCoverage?.coverage,
|
|
596
|
+
context.targetCoverage?.depth,
|
|
573
597
|
);
|
|
574
598
|
if (!post.ok) return post;
|
|
575
|
-
const cubeCaptures = context.contributeCubeCaptures?.();
|
|
599
|
+
const cubeCaptures = context.contributeCubeCaptures?.(atmosphere.value);
|
|
576
600
|
if (cubeCaptures !== undefined && !cubeCaptures.ok) return cubeCaptures;
|
|
577
601
|
return ok(undefined);
|
|
578
602
|
}
|
|
@@ -634,7 +658,11 @@ function standardTopology(
|
|
|
634
658
|
): RenderPipelineTopology {
|
|
635
659
|
const config = {
|
|
636
660
|
...(topology.config ?? {}),
|
|
637
|
-
ssao: {
|
|
661
|
+
ssao: {
|
|
662
|
+
...(topology.config?.ssao ?? {}),
|
|
663
|
+
...(typeof profile.ssao === 'object' ? profile.ssao : {}),
|
|
664
|
+
enabled: profile.ssao !== false,
|
|
665
|
+
},
|
|
638
666
|
};
|
|
639
667
|
return {
|
|
640
668
|
...topology,
|
|
@@ -653,6 +681,7 @@ function buildStandard(
|
|
|
653
681
|
context: RenderPipelineBuildContext<RenderPipelineFrame>,
|
|
654
682
|
topology: RenderPipelineTopology,
|
|
655
683
|
): ReturnType<RenderPipeline['build']> {
|
|
684
|
+
const standardContext = context as StandardPipelineBuildContext;
|
|
656
685
|
const profile = profileFor(topology);
|
|
657
686
|
if (!STANDARD_LIGHT_COUNTS.some((count) => count === profile.lightCount)) {
|
|
658
687
|
return err(
|
|
@@ -675,11 +704,11 @@ function buildStandard(
|
|
|
675
704
|
// A missing Camera is an intentional clear-only frame. Keep it on the
|
|
676
705
|
// forward raster lane so clustered resources cannot introduce work.
|
|
677
706
|
if (effective.clearOnly === true) {
|
|
678
|
-
return buildStandardForwardLane(
|
|
707
|
+
return buildStandardForwardLane(standardContext, effective, lighting.value);
|
|
679
708
|
}
|
|
680
709
|
return profile.renderPath === 'forward'
|
|
681
|
-
? buildStandardForwardLane(
|
|
682
|
-
: buildStandardDeferredLane(
|
|
710
|
+
? buildStandardForwardLane(standardContext, effective, lighting.value)
|
|
711
|
+
: buildStandardDeferredLane(standardContext, effective, lighting.value);
|
|
683
712
|
}
|
|
684
713
|
|
|
685
714
|
export const standardPipeline: StandardPipeline = Object.freeze({
|
|
@@ -170,6 +170,8 @@ export function addStandardPost(
|
|
|
170
170
|
surface: StandardPostSurface,
|
|
171
171
|
sceneTemporal?: RenderPipelineTarget,
|
|
172
172
|
secondaryReactivity?: GraphTextureView,
|
|
173
|
+
coverage?: RenderPipelineTarget,
|
|
174
|
+
coverageDepth?: RenderPipelineTarget,
|
|
173
175
|
): Result<void, RenderPipelineBuildError> {
|
|
174
176
|
const clearOnly = topology.clearOnly === true;
|
|
175
177
|
const outputPlan = createStandardOutputPlan({
|
|
@@ -240,6 +242,8 @@ export function addStandardPost(
|
|
|
240
242
|
scene,
|
|
241
243
|
depth,
|
|
242
244
|
currentTemporal: sceneTemporal,
|
|
245
|
+
...(coverage === undefined ? {} : { coverage }),
|
|
246
|
+
...(coverageDepth === undefined ? {} : { coverageDepth }),
|
|
243
247
|
...(secondaryReactivity === undefined ? {} : { secondaryReactivity }),
|
|
244
248
|
historyColor: history.previousColor,
|
|
245
249
|
historyTemporal: history.previousTemporal,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SsaoParameterConfig } from '../ssao-config';
|
|
1
2
|
export const STANDARD_PIPELINE_ID = 'forgeax::standard' as const;
|
|
2
3
|
export const STANDARD_LIGHT_COUNTS = [1, 32, 256] as const;
|
|
3
4
|
export {
|
|
@@ -34,7 +35,7 @@ export interface StandardProfile {
|
|
|
34
35
|
readonly shadows: StandardShadowMode;
|
|
35
36
|
readonly pbr: boolean;
|
|
36
37
|
readonly ibl: boolean;
|
|
37
|
-
readonly ssao: boolean;
|
|
38
|
+
readonly ssao: boolean | SsaoParameterConfig;
|
|
38
39
|
/** Renderer-owned 1080p volume profile; tile width/height remain surface-derived. */
|
|
39
40
|
readonly volumetricFog?: StandardVolumetricFogProfile | undefined;
|
|
40
41
|
readonly postStages: typeof STANDARD_POST_STAGE_NAMES;
|
package/src/pipeline-builder.ts
CHANGED
|
@@ -161,6 +161,8 @@ export interface PipelineBuilderContext {
|
|
|
161
161
|
readonly storageBuffer: boolean;
|
|
162
162
|
readonly rgba16floatRenderable: boolean;
|
|
163
163
|
};
|
|
164
|
+
/** The output-domain binary coverage variant uses an r8unorm attachment. */
|
|
165
|
+
readonly coverageOnly?: boolean | undefined;
|
|
164
166
|
}
|
|
165
167
|
|
|
166
168
|
/**
|
|
@@ -175,7 +177,10 @@ export interface PipelineBuilderContext {
|
|
|
175
177
|
*/
|
|
176
178
|
export function validateTemporalPipelineContract(
|
|
177
179
|
source: string,
|
|
178
|
-
ctx: Pick<
|
|
180
|
+
ctx: Pick<
|
|
181
|
+
PipelineBuilderContext,
|
|
182
|
+
'colorFormat' | 'depthFormat' | 'capabilities' | 'coverageOnly'
|
|
183
|
+
>,
|
|
179
184
|
): Result<void, RhiError> {
|
|
180
185
|
if (!source.includes('fn vs_temporal') || !source.includes('fn fs_temporal')) {
|
|
181
186
|
return err(
|
|
@@ -186,12 +191,16 @@ export function validateTemporalPipelineContract(
|
|
|
186
191
|
}),
|
|
187
192
|
);
|
|
188
193
|
}
|
|
189
|
-
|
|
194
|
+
const validCoverageTarget = ctx.coverageOnly === true && ctx.colorFormat === 'r8unorm';
|
|
195
|
+
if (ctx.colorFormat !== 'rgba16float' && !validCoverageTarget) {
|
|
190
196
|
return err(
|
|
191
197
|
new RhiError({
|
|
192
198
|
code: 'shader-compile-failed',
|
|
193
199
|
expected: 'temporal material target format is rgba16float',
|
|
194
|
-
hint:
|
|
200
|
+
hint:
|
|
201
|
+
ctx.coverageOnly === true
|
|
202
|
+
? `coverage temporal producer received unsupported color format ${ctx.colorFormat}; use r8unorm`
|
|
203
|
+
: `temporal producer received color format ${ctx.colorFormat}; use its physical rgba16float target`,
|
|
195
204
|
}),
|
|
196
205
|
);
|
|
197
206
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -3,12 +3,14 @@ import type { Plugin } from '@forgeax/engine-plugin';
|
|
|
3
3
|
import { Atmosphere } from './components/atmosphere';
|
|
4
4
|
import { Camera } from './components/camera';
|
|
5
5
|
import { DirectionalLight } from './components/directional-light';
|
|
6
|
+
import { DynamicResolution } from './components/dynamic-resolution';
|
|
6
7
|
import { Instances } from './components/instances';
|
|
7
8
|
import { Layer } from './components/layer';
|
|
8
9
|
import { LightProbe } from './components/light-probe';
|
|
9
10
|
import { Lines } from './components/lines';
|
|
10
11
|
import { MeshFilter } from './components/mesh-filter';
|
|
11
12
|
import { MeshRenderer } from './components/mesh-renderer';
|
|
13
|
+
import { MotionBlur } from './components/motion-blur';
|
|
12
14
|
import { PointLight } from './components/point-light';
|
|
13
15
|
import { PointLightShadow } from './components/point-light-shadow';
|
|
14
16
|
import { Points } from './components/points';
|
|
@@ -30,11 +32,13 @@ const RENDER_COMPONENTS: readonly Component[] = [
|
|
|
30
32
|
Atmosphere,
|
|
31
33
|
Camera,
|
|
32
34
|
DirectionalLight,
|
|
35
|
+
DynamicResolution,
|
|
33
36
|
Instances,
|
|
34
37
|
Layer,
|
|
35
38
|
LightProbe,
|
|
36
39
|
MeshFilter,
|
|
37
40
|
MeshRenderer,
|
|
41
|
+
MotionBlur,
|
|
38
42
|
PointLight,
|
|
39
43
|
PointLightShadow,
|
|
40
44
|
Points,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// feat-20260609-learn-render-4-5-framebuffers-demo-offscreen-rt-an M1 / T-2
|
|
4
4
|
// added 'fullscreen-input-not-found').
|
|
5
5
|
//
|
|
6
|
-
// Closed
|
|
6
|
+
// Closed PostProcessErrorCode union + PostProcessError discriminated-union class.
|
|
7
7
|
// - 'post-process-already-registered' (programmer error) -> fullscreen effect registration THROWS a
|
|
8
8
|
// PostProcessError, mirroring ShaderCatalog.installMaterialArtifact's Map.has -> throw
|
|
9
9
|
// fail-fast (research Finding M2-4). A second register under the same id is a coding
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
/**
|
|
39
39
|
* Closed union of fullscreen post-process error codes.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
41
|
+
* AI users perform exhaustive `switch (err.code)` without a default
|
|
42
42
|
* and TS guards completeness (AC-08).
|
|
43
43
|
*
|
|
44
44
|
* | code | channel | trigger |
|
|
@@ -134,21 +134,23 @@ export interface PostProcessParamsUpdateSizeMismatchDetail {
|
|
|
134
134
|
* `detail` parameter to the variant payload at compile time.
|
|
135
135
|
*/
|
|
136
136
|
export type PostProcessErrorDetailFor<C extends PostProcessErrorCode> =
|
|
137
|
-
C extends '
|
|
138
|
-
?
|
|
139
|
-
: C extends 'post-process-
|
|
140
|
-
?
|
|
141
|
-
: C extends '
|
|
142
|
-
?
|
|
143
|
-
: C extends '
|
|
144
|
-
?
|
|
145
|
-
: C extends 'ssao-
|
|
146
|
-
?
|
|
147
|
-
: C extends '
|
|
148
|
-
?
|
|
149
|
-
: C extends 'params-
|
|
150
|
-
?
|
|
151
|
-
:
|
|
137
|
+
C extends 'ssao-parameter-invalid'
|
|
138
|
+
? { readonly paramName: string; readonly value: unknown }
|
|
139
|
+
: C extends 'post-process-already-registered'
|
|
140
|
+
? PostProcessPreviouslyRegisteredDetail
|
|
141
|
+
: C extends 'post-process-not-found'
|
|
142
|
+
? PostProcessNotFoundDetail
|
|
143
|
+
: C extends 'fullscreen-input-not-found'
|
|
144
|
+
? FullscreenInputNotFoundDetail
|
|
145
|
+
: C extends 'ssao-radius-non-positive'
|
|
146
|
+
? SsaoRadiusNonPositiveDetail
|
|
147
|
+
: C extends 'ssao-bias-negative'
|
|
148
|
+
? SsaoBiasNegativeDetail
|
|
149
|
+
: C extends 'params-size-mismatch'
|
|
150
|
+
? PostProcessParamsSizeMismatchDetail
|
|
151
|
+
: C extends 'params-update-size-mismatch'
|
|
152
|
+
? PostProcessParamsUpdateSizeMismatchDetail
|
|
153
|
+
: never;
|
|
152
154
|
|
|
153
155
|
/**
|
|
154
156
|
* Tagged union of `.detail` payloads. The variants are unique by structural fields
|
|
@@ -170,7 +172,8 @@ const POST_PROCESS_POLICY = {
|
|
|
170
172
|
expected: 'typed fullscreen plan references a registered post-process id',
|
|
171
173
|
hint: (detail) =>
|
|
172
174
|
`no post-process is registered for id '${(detail as PostProcessNotFoundDetail).id}'. ` +
|
|
173
|
-
|
|
175
|
+
'For Engine-owned effects, rebuild the shader manifest with that Engine entry enabled. ' +
|
|
176
|
+
`For custom effects, register '${(detail as PostProcessNotFoundDetail).id}' with the feature host ({source, reads?}), ` +
|
|
174
177
|
'then reference it from a typed fullscreen RenderFeaturePlan.',
|
|
175
178
|
},
|
|
176
179
|
'fullscreen-input-not-found': {
|
|
@@ -187,6 +190,11 @@ const POST_PROCESS_POLICY = {
|
|
|
187
190
|
);
|
|
188
191
|
},
|
|
189
192
|
},
|
|
193
|
+
'ssao-parameter-invalid': {
|
|
194
|
+
expected: 'finite non-negative SSAO intensity and low, medium, or high quality',
|
|
195
|
+
hint: () =>
|
|
196
|
+
'Set ssao.intensity to a finite non-negative value and ssao.quality to low, medium, or high.',
|
|
197
|
+
},
|
|
190
198
|
'ssao-radius-non-positive': {
|
|
191
199
|
expected: 'SSAO radius must be > 0',
|
|
192
200
|
hint: (detail) => {
|