@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
|
@@ -139,6 +139,7 @@ import {
|
|
|
139
139
|
cameraExposureFromColumns,
|
|
140
140
|
cameraProjectionFromF32,
|
|
141
141
|
cubeCameraUpdateIntentFromF32,
|
|
142
|
+
DynamicResolution,
|
|
142
143
|
Fog,
|
|
143
144
|
MotionBlur,
|
|
144
145
|
ReflectionProbe,
|
|
@@ -146,6 +147,7 @@ import {
|
|
|
146
147
|
ScreenSpaceReflection,
|
|
147
148
|
tonemapFromF32,
|
|
148
149
|
tonemapToU32,
|
|
150
|
+
validateDynamicResolutionCamera,
|
|
149
151
|
} from './components';
|
|
150
152
|
import type { DirectionalShadowQuality } from './components/directional-shadow-filter';
|
|
151
153
|
import type { LightValidationError } from './components/light-helpers';
|
|
@@ -932,6 +934,10 @@ export interface MaterialSnapshot {
|
|
|
932
934
|
*/
|
|
933
935
|
readonly materialShaderId?: string | undefined;
|
|
934
936
|
readonly materialProgramKeys?: Readonly<Record<string, string>> | undefined;
|
|
937
|
+
/** Producer-selected scene-index program keys, when a cooked publication carries them. */
|
|
938
|
+
readonly materialSceneIndexProgramKeys?:
|
|
939
|
+
| Readonly<Record<string, MaterialSceneIndexProgramKey>>
|
|
940
|
+
| undefined;
|
|
935
941
|
/**
|
|
936
942
|
* Stable source handle for the material asset. Record uses this only for
|
|
937
943
|
* same-frame assembly reuse; GPU bind-group validity still comes from the
|
|
@@ -1055,6 +1061,15 @@ export interface MaterialSnapshot {
|
|
|
1055
1061
|
readonly transparent?: boolean | undefined;
|
|
1056
1062
|
}
|
|
1057
1063
|
|
|
1064
|
+
/**
|
|
1065
|
+
* One producer-selected scene-index program, retaining the effective Pass
|
|
1066
|
+
* kind so record does not infer shadow/depth semantics from an authored name.
|
|
1067
|
+
*/
|
|
1068
|
+
export interface MaterialSceneIndexProgramKey {
|
|
1069
|
+
readonly specializationKey: string;
|
|
1070
|
+
readonly pass: 'forward' | 'shadow' | 'depth';
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1058
1073
|
export interface MaterialCacheChainIdentity {
|
|
1059
1074
|
readonly asset: MaterialAsset;
|
|
1060
1075
|
readonly parentGuid: string | undefined;
|
|
@@ -1262,8 +1277,13 @@ export interface ShadowCasterMembership {
|
|
|
1262
1277
|
readonly materialHandle: number;
|
|
1263
1278
|
readonly passIndex: number;
|
|
1264
1279
|
readonly materialShaderId?: string;
|
|
1280
|
+
/** Selected authored ShadowCaster entry points, when published. */
|
|
1281
|
+
readonly vertexEntry?: string;
|
|
1282
|
+
readonly fragmentEntry?: string;
|
|
1265
1283
|
readonly renderState?: MaterialRenderState;
|
|
1266
1284
|
readonly cpuReason?: ShadowCasterCpuReason;
|
|
1285
|
+
/** Producer-owned result of the complete ShadowCaster admission check. */
|
|
1286
|
+
readonly gpuDrivenEligible?: boolean;
|
|
1267
1287
|
}
|
|
1268
1288
|
|
|
1269
1289
|
/** Producer evidence for a concrete ShadowCaster pass that remains on CPU. */
|
|
@@ -1520,28 +1540,85 @@ export function materialProgramKeysForMaterial(
|
|
|
1520
1540
|
assets: AssetRegistry,
|
|
1521
1541
|
context: MaterialCookProgramContext | undefined,
|
|
1522
1542
|
): Readonly<Record<string, string>> | undefined {
|
|
1543
|
+
return materialProgramKeysForAddress(material, assets, context, 'direct');
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/** Resolve the producer's scene-index program key for each cooked Pass. */
|
|
1547
|
+
export function materialSceneIndexProgramKeysForMaterial(
|
|
1548
|
+
material: MaterialAsset,
|
|
1549
|
+
assets: AssetRegistry,
|
|
1550
|
+
context: MaterialCookProgramContext | undefined,
|
|
1551
|
+
): Readonly<Record<string, MaterialSceneIndexProgramKey>> | undefined {
|
|
1523
1552
|
const projection = assets.getMaterialProjectionForPayload(material);
|
|
1524
1553
|
if (projection === undefined) return undefined;
|
|
1525
1554
|
if (context === undefined)
|
|
1526
1555
|
throw new Error('Published material selection requires renderer-owned compiler context');
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1556
|
+
const entries: Record<string, MaterialSceneIndexProgramKey> = {};
|
|
1557
|
+
for (const pass of projection.passes) {
|
|
1558
|
+
const mode = String(
|
|
1559
|
+
(pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
|
|
1560
|
+
);
|
|
1561
|
+
const passKind = /shadow/i.test(mode)
|
|
1562
|
+
? ('shadow' as const)
|
|
1563
|
+
: /depth/i.test(mode)
|
|
1564
|
+
? ('depth' as const)
|
|
1565
|
+
: ('forward' as const);
|
|
1566
|
+
const selectedContext: MaterialCookProgramContext = {
|
|
1567
|
+
...context,
|
|
1568
|
+
pass: passKind,
|
|
1569
|
+
pipeline: /deferred|gbuffer/i.test(mode) ? 'deferred' : context.pipeline,
|
|
1570
|
+
};
|
|
1571
|
+
try {
|
|
1572
|
+
const selected = selectMaterialPassProgram(
|
|
1573
|
+
projection,
|
|
1538
1574
|
pass.name,
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1575
|
+
selectedContext,
|
|
1576
|
+
'scene-index',
|
|
1577
|
+
);
|
|
1578
|
+
entries[pass.name] = { specializationKey: selected.specializationKey, pass: passKind };
|
|
1579
|
+
} catch (error) {
|
|
1580
|
+
if (!isMissingMaterialProgram(error)) throw error;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return Object.keys(entries).length === 0 ? undefined : entries;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function isMissingMaterialProgram(error: unknown): boolean {
|
|
1587
|
+
return (
|
|
1588
|
+
error !== null &&
|
|
1589
|
+
typeof error === 'object' &&
|
|
1590
|
+
(error as { readonly code?: unknown }).code === 'material-specialization-not-cooked'
|
|
1542
1591
|
);
|
|
1543
1592
|
}
|
|
1544
1593
|
|
|
1594
|
+
function materialProgramKeysForAddress(
|
|
1595
|
+
material: MaterialAsset,
|
|
1596
|
+
assets: AssetRegistry,
|
|
1597
|
+
context: MaterialCookProgramContext | undefined,
|
|
1598
|
+
address: 'direct' | 'scene-index',
|
|
1599
|
+
): Readonly<Record<string, string>> | undefined {
|
|
1600
|
+
const projection = assets.getMaterialProjectionForPayload(material);
|
|
1601
|
+
if (projection === undefined) return undefined;
|
|
1602
|
+
if (context === undefined)
|
|
1603
|
+
throw new Error('Published material selection requires renderer-owned compiler context');
|
|
1604
|
+
const entries: [string, string][] = [];
|
|
1605
|
+
for (const pass of projection.passes) {
|
|
1606
|
+
const mode = String(
|
|
1607
|
+
(pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
|
|
1608
|
+
);
|
|
1609
|
+
const selectedContext: MaterialCookProgramContext = {
|
|
1610
|
+
...context,
|
|
1611
|
+
pass: /shadow/i.test(mode) ? 'shadow' : /depth/i.test(mode) ? 'depth' : 'forward',
|
|
1612
|
+
pipeline: /deferred|gbuffer/i.test(mode) ? 'deferred' : context.pipeline,
|
|
1613
|
+
};
|
|
1614
|
+
entries.push([
|
|
1615
|
+
pass.name,
|
|
1616
|
+
selectMaterialPassProgram(projection, pass.name, selectedContext, address).specializationKey,
|
|
1617
|
+
]);
|
|
1618
|
+
}
|
|
1619
|
+
return entries.length === 0 ? undefined : Object.fromEntries(entries);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1545
1622
|
export function runtimeMaterialShaderIdForMaterial(
|
|
1546
1623
|
passes: readonly MaterialPass[],
|
|
1547
1624
|
programs: Readonly<Record<string, string>> | undefined,
|
|
@@ -1620,38 +1697,18 @@ export function shadowCasterCpuReason(
|
|
|
1620
1697
|
return 'transparent';
|
|
1621
1698
|
}
|
|
1622
1699
|
if (morph !== undefined) return 'morph';
|
|
1623
|
-
const isStandardPbr =
|
|
1624
|
-
material.materialShaderId === 'forgeax::default-standard-pbr' ||
|
|
1625
|
-
material.materialShaderId === 'forgeax::pbr-skin' ||
|
|
1626
|
-
material.materialShaderId === 'forgeax::default-standard-pbr-skin';
|
|
1627
|
-
if (!isStandardPbr) return 'unsupported-shader';
|
|
1628
1700
|
const shadowEntry = shadowEntries[0];
|
|
1629
|
-
if (
|
|
1630
|
-
shadowEntry !== undefined &&
|
|
1631
|
-
shadowEntry.materialShaderId !== undefined &&
|
|
1632
|
-
shadowEntry.materialShaderId !== 'forgeax::default-shadow-caster'
|
|
1633
|
-
) {
|
|
1634
|
-
return 'unsupported-shader';
|
|
1635
|
-
}
|
|
1636
1701
|
if (shadowEntry?.renderState !== undefined) return 'unsupported-render-state';
|
|
1637
1702
|
if (draw === undefined) return 'missing-gpu-draw';
|
|
1638
1703
|
if (draw.prepared === undefined) return 'unprepared';
|
|
1639
|
-
const isSkinnedPbr =
|
|
1640
|
-
material.materialShaderId === 'forgeax::pbr-skin' ||
|
|
1641
|
-
material.materialShaderId === 'forgeax::default-standard-pbr-skin';
|
|
1642
1704
|
const preparedMaterial = draw.prepared.identity.material;
|
|
1643
1705
|
const preparedDeformation = draw.prepared.identity.deformation;
|
|
1644
|
-
const materialContractMatches =
|
|
1645
|
-
(material.materialShaderId === 'forgeax::default-standard-pbr' &&
|
|
1646
|
-
preparedMaterial === 'forgeax::default-standard-pbr') ||
|
|
1647
|
-
(isSkinnedPbr &&
|
|
1648
|
-
(preparedMaterial === 'forgeax::pbr-skin' ||
|
|
1649
|
-
preparedMaterial === 'forgeax::default-standard-pbr-skin'));
|
|
1706
|
+
const materialContractMatches = preparedMaterial === material.materialShaderId;
|
|
1650
1707
|
const deformationContractMatches =
|
|
1651
1708
|
(skin === undefined && preparedDeformation === 'rigid') ||
|
|
1652
1709
|
(skin !== undefined && preparedDeformation === 'skin');
|
|
1653
1710
|
if (!materialContractMatches || !deformationContractMatches) return 'prepared-contract';
|
|
1654
|
-
if (
|
|
1711
|
+
if (preparedDeformation === 'skin' && !hasFiniteOrderedSkinBounds(skin?.bounds)) {
|
|
1655
1712
|
return 'missing-skin-bounds';
|
|
1656
1713
|
}
|
|
1657
1714
|
return undefined;
|
|
@@ -2247,6 +2304,11 @@ export function resolveMaterialSnapshot(
|
|
|
2247
2304
|
const resolved = resolvedResult.value;
|
|
2248
2305
|
const allPasses = resolved.passes;
|
|
2249
2306
|
const materialProgramKeys = materialProgramKeysForMaterial(asset, assetsRef, materialContext);
|
|
2307
|
+
const materialSceneIndexProgramKeys = materialSceneIndexProgramKeysForMaterial(
|
|
2308
|
+
asset,
|
|
2309
|
+
assetsRef,
|
|
2310
|
+
materialContext,
|
|
2311
|
+
);
|
|
2250
2312
|
const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, undefined);
|
|
2251
2313
|
const firstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, materialProgramKeys);
|
|
2252
2314
|
const pv = materialValuesToLinearRuntime(
|
|
@@ -2351,6 +2413,7 @@ export function resolveMaterialSnapshot(
|
|
|
2351
2413
|
normalScale: normalScalePv,
|
|
2352
2414
|
materialShaderId: firstPassShader,
|
|
2353
2415
|
materialProgramKeys,
|
|
2416
|
+
materialSceneIndexProgramKeys,
|
|
2354
2417
|
materialHandle: handleRaw,
|
|
2355
2418
|
renderState: pipelineRenderState(allPasses[0]?.renderState),
|
|
2356
2419
|
paramSnapshot: paramSnap,
|
|
@@ -2726,7 +2789,11 @@ export function computeDirectionalCsm(
|
|
|
2726
2789
|
resultLightViewProjs.push(new Float32Array(16));
|
|
2727
2790
|
continue;
|
|
2728
2791
|
}
|
|
2729
|
-
|
|
2792
|
+
// The receiver blends into this cascade before the preceding split.
|
|
2793
|
+
// Fit that same overlap instead of sampling outside the next projection.
|
|
2794
|
+
const previousSplit = splits[cIdx - 1] ?? sNear;
|
|
2795
|
+
const cascadeNear =
|
|
2796
|
+
cIdx === 0 ? sNear : Math.max(sNear, previousSplit * (1 - config.cascadeBlend));
|
|
2730
2797
|
const cascadeFar = splits[cIdx] ?? sFar;
|
|
2731
2798
|
const corners = computeFrustumCorners(
|
|
2732
2799
|
cameraVP,
|
|
@@ -2768,7 +2835,7 @@ export function computeDirectionalCsm(
|
|
|
2768
2835
|
minY,
|
|
2769
2836
|
maxY,
|
|
2770
2837
|
minZ,
|
|
2771
|
-
maxZ,
|
|
2838
|
+
maxZ: nearZ,
|
|
2772
2839
|
});
|
|
2773
2840
|
resultLightViewProjs.push(new Float32Array(mat4.multiply(mat4.create(), orthoProj, lightView)));
|
|
2774
2841
|
}
|
|
@@ -2831,7 +2898,12 @@ export interface PreparedExtractContext {
|
|
|
2831
2898
|
readonly getMaterialShaderArtifact:
|
|
2832
2899
|
| ((
|
|
2833
2900
|
materialShaderId: string,
|
|
2834
|
-
|
|
2901
|
+
request?: {
|
|
2902
|
+
readonly vertexColorAvailable?: boolean;
|
|
2903
|
+
readonly deformation?: 'rigid' | 'skin';
|
|
2904
|
+
readonly pass?: 'forward' | 'shadow' | 'depth';
|
|
2905
|
+
readonly address?: 'direct' | 'scene-index';
|
|
2906
|
+
},
|
|
2835
2907
|
) => MaterialShaderArtifact | undefined)
|
|
2836
2908
|
| undefined;
|
|
2837
2909
|
/** Renderer-owned canonical source for explicit large instance collections. */
|
|
@@ -2852,13 +2924,14 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
|
|
|
2852
2924
|
const cameraQuery = world
|
|
2853
2925
|
.query({
|
|
2854
2926
|
read: [Camera],
|
|
2855
|
-
optional: [MotionBlur, ScreenSpaceReflection],
|
|
2927
|
+
optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection],
|
|
2856
2928
|
with: [Transform, GlobalTransform],
|
|
2857
2929
|
})
|
|
2858
2930
|
.unwrap();
|
|
2859
2931
|
for (const row of cameraQuery) {
|
|
2860
2932
|
const cam = row.get(Camera);
|
|
2861
2933
|
const motionBlur = row.get(MotionBlur);
|
|
2934
|
+
const dynamicResolution = row.get(DynamicResolution);
|
|
2862
2935
|
const screenSpaceReflection = row.get(ScreenSpaceReflection);
|
|
2863
2936
|
const entity = row.entity;
|
|
2864
2937
|
const view = worldInternal._getArrayView(entity, GlobalTransform, 'world');
|
|
@@ -2881,6 +2954,9 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
|
|
|
2881
2954
|
colorLutStrength: cam.colorLutStrength,
|
|
2882
2955
|
}
|
|
2883
2956
|
: undefined;
|
|
2957
|
+
const antialias = antialiasFromF32(cam.antialias);
|
|
2958
|
+
const dynamicResolutionResult = validateDynamicResolutionCamera(dynamicResolution, antialias);
|
|
2959
|
+
if (!dynamicResolutionResult.ok) throw dynamicResolutionResult.error;
|
|
2884
2960
|
cameras.push({
|
|
2885
2961
|
entityKey: entity as number,
|
|
2886
2962
|
...(target === undefined ? {} : { target }),
|
|
@@ -2900,7 +2976,10 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
|
|
|
2900
2976
|
exposure: cam.exposure,
|
|
2901
2977
|
whitePoint: cam.whitePoint,
|
|
2902
2978
|
...(output === undefined ? {} : { output }),
|
|
2903
|
-
antialias
|
|
2979
|
+
antialias,
|
|
2980
|
+
...(dynamicResolutionResult.value === undefined
|
|
2981
|
+
? {}
|
|
2982
|
+
: { dynamicResolution: dynamicResolutionResult.value }),
|
|
2904
2983
|
bloom: bloomEnabledFromF32(cam.bloom),
|
|
2905
2984
|
bloomThreshold: cam.bloomThreshold,
|
|
2906
2985
|
bloomIntensity: cam.bloomIntensity,
|
|
@@ -2982,6 +3061,7 @@ export function collectReflectionProbeFacts(world: World): ReflectionProbeFact[]
|
|
|
2982
3061
|
priority: probe.priority,
|
|
2983
3062
|
intensity: probe.intensity,
|
|
2984
3063
|
resolution: probe.resolution,
|
|
3064
|
+
boxProjection: probe.boxProjection,
|
|
2985
3065
|
revision: probe.invalidationVersion,
|
|
2986
3066
|
updateIntent: reflectionProbeUpdateIntentFromF32(probe.updateIntent),
|
|
2987
3067
|
invalidationVersion: probe.invalidationVersion,
|
|
@@ -3068,7 +3148,12 @@ export function prepareExtractContext(
|
|
|
3068
3148
|
readonly worldId?: number;
|
|
3069
3149
|
readonly getMaterialShaderArtifact?: (
|
|
3070
3150
|
materialShaderId: string,
|
|
3071
|
-
|
|
3151
|
+
request?: {
|
|
3152
|
+
readonly vertexColorAvailable?: boolean;
|
|
3153
|
+
readonly deformation?: 'rigid' | 'skin';
|
|
3154
|
+
readonly pass?: 'forward' | 'shadow' | 'depth';
|
|
3155
|
+
readonly address?: 'direct' | 'scene-index';
|
|
3156
|
+
},
|
|
3072
3157
|
) => MaterialShaderArtifact | undefined;
|
|
3073
3158
|
readonly instanceCollections?: InstanceCollectionStore;
|
|
3074
3159
|
} = {},
|
package/src/render-system.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { projectCaptureScene } from './capture/scene-projection';
|
|
1
2
|
import type { RenderSceneBounds } from './scene/render-scene-types';
|
|
2
3
|
// @forgeax/engine-runtime - RenderSystem main entry (D-S2 three-stage Extract ->
|
|
3
4
|
// Prepare -> Record + 4-tier error fan-out).
|
|
@@ -1246,7 +1247,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1246
1247
|
// explicit texture/sampler handles resolved to resident GPU resources.
|
|
1247
1248
|
materialBgAssemblyCache: new Map(),
|
|
1248
1249
|
// singleton material cache (flat Map<variant, BindGroup>; D-6).
|
|
1249
|
-
|
|
1250
|
+
shadowMaterialBindGroups: new WeakMap(),
|
|
1250
1251
|
// post-process bind group cache (bloom / fxaa / ssao): identity-keyed
|
|
1251
1252
|
// WeakMap chain so resize-retired transient targets rebuild automatically.
|
|
1252
1253
|
postProcessBgCache: new WeakMap(),
|
|
@@ -2294,8 +2295,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2294
2295
|
if (producer === undefined || target === undefined) {
|
|
2295
2296
|
return undefined;
|
|
2296
2297
|
}
|
|
2297
|
-
const
|
|
2298
|
-
const
|
|
2298
|
+
const descriptor = target.descriptor.kind === 'texture' ? target.descriptor : undefined;
|
|
2299
|
+
const width = descriptor?.width ?? Math.max(1, internals.canvas.width);
|
|
2300
|
+
const height = descriptor?.height ?? Math.max(1, internals.canvas.height);
|
|
2299
2301
|
return Object.freeze({
|
|
2300
2302
|
identity: 'standard-scene-temporal',
|
|
2301
2303
|
producerId: 'forgeax::standard::scene-data',
|
|
@@ -2420,6 +2422,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2420
2422
|
}
|
|
2421
2423
|
}
|
|
2422
2424
|
try {
|
|
2425
|
+
internals.recoveryColdWorkGuard?.beginFrame();
|
|
2423
2426
|
pointsLinesOwner.beginFrame();
|
|
2424
2427
|
// cameraOwner drives the surfaced cameras + frustum
|
|
2425
2428
|
// cull; resourceOwner drives skylight/skybox/postProcess + per-world
|
|
@@ -2540,6 +2543,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2540
2543
|
cameras[0],
|
|
2541
2544
|
frameState.frameNumber,
|
|
2542
2545
|
skylight,
|
|
2546
|
+
frame.reflectionProbes?.some((probe) => probe.updateIntent === 'on-change')
|
|
2547
|
+
? JSON.stringify([
|
|
2548
|
+
persistentRenderScene.reflectionCaptureRevision(),
|
|
2549
|
+
lights.directional,
|
|
2550
|
+
lights.point,
|
|
2551
|
+
lights.spot,
|
|
2552
|
+
lights.rect,
|
|
2553
|
+
skylight,
|
|
2554
|
+
frame.skybox,
|
|
2555
|
+
environment?.environmentSignature,
|
|
2556
|
+
])
|
|
2557
|
+
: '',
|
|
2558
|
+
frame.skybox,
|
|
2543
2559
|
);
|
|
2544
2560
|
latestCamera = cameras[0];
|
|
2545
2561
|
frameState.ssrRequested = latestCamera?.screenSpaceReflection !== undefined;
|
|
@@ -3144,14 +3160,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3144
3160
|
Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
|
|
3145
3161
|
);
|
|
3146
3162
|
}
|
|
3163
|
+
const probeCaptureScene =
|
|
3164
|
+
shadowCasterProjection !== undefined &&
|
|
3165
|
+
reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined)
|
|
3166
|
+
? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
|
|
3167
|
+
: undefined;
|
|
3147
3168
|
submitted = runProfiledRenderPhase(profileSession, 'record', () =>
|
|
3148
3169
|
recordFrame(
|
|
3149
3170
|
internals,
|
|
3150
3171
|
resourceWorld,
|
|
3151
3172
|
cameras,
|
|
3152
3173
|
lights,
|
|
3153
|
-
submissionRenderables,
|
|
3154
|
-
orderedDispatch,
|
|
3174
|
+
probeCaptureScene?.renderables ?? submissionRenderables,
|
|
3175
|
+
probeCaptureScene?.displayDispatch ?? orderedDispatch,
|
|
3155
3176
|
frameState,
|
|
3156
3177
|
dispatchCounts,
|
|
3157
3178
|
bindGroupCounts,
|
|
@@ -3181,6 +3202,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3181
3202
|
scheduler: cubeCaptureScheduler,
|
|
3182
3203
|
state: cubeCaptureState,
|
|
3183
3204
|
reflectionProbes: reflectionProbeRecord,
|
|
3205
|
+
...(probeCaptureScene === undefined
|
|
3206
|
+
? {}
|
|
3207
|
+
: { captureDispatch: probeCaptureScene.captureDispatch }),
|
|
3184
3208
|
} satisfies CubeCaptureFrameInput,
|
|
3185
3209
|
environment?.environmentSignature ?? '',
|
|
3186
3210
|
environment?.fogSignature ?? '',
|
|
@@ -3322,6 +3346,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3322
3346
|
}),
|
|
3323
3347
|
);
|
|
3324
3348
|
} finally {
|
|
3349
|
+
internals.recoveryColdWorkGuard?.endFrame();
|
|
3325
3350
|
if (ownsProfileFrame) {
|
|
3326
3351
|
try {
|
|
3327
3352
|
profileSession?.endFrame();
|
|
@@ -3439,7 +3464,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3439
3464
|
? config
|
|
3440
3465
|
: {
|
|
3441
3466
|
clusterGrid: DEFAULT_CLUSTER_GRID,
|
|
3442
|
-
|
|
3467
|
+
ssao: {
|
|
3468
|
+
enabled: profileConfig.ssao !== false,
|
|
3469
|
+
...(typeof profileConfig.ssao === 'object' ? profileConfig.ssao : {}),
|
|
3470
|
+
},
|
|
3443
3471
|
...config,
|
|
3444
3472
|
};
|
|
3445
3473
|
if (resolvedConfig?.clusterGrid !== undefined) {
|
|
@@ -3792,7 +3820,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3792
3820
|
frameState.instancesBgPerEntity.clear();
|
|
3793
3821
|
frameState.materialBgShared.clear();
|
|
3794
3822
|
frameState.materialBgAssemblyCache.clear();
|
|
3795
|
-
frameState.
|
|
3823
|
+
frameState.shadowMaterialBindGroups = new WeakMap();
|
|
3796
3824
|
frameState.postProcessBgCache = new WeakMap();
|
|
3797
3825
|
// Fullscreen PSOs are cached outside frameState because the normal
|
|
3798
3826
|
// path reuses them across frames. They still carry opaque handles from
|
|
@@ -758,6 +758,10 @@ export class RenderScene {
|
|
|
758
758
|
return records;
|
|
759
759
|
}
|
|
760
760
|
|
|
761
|
+
get contentRevision(): number {
|
|
762
|
+
return this.revision;
|
|
763
|
+
}
|
|
764
|
+
|
|
761
765
|
inspect(): RenderSceneInspection {
|
|
762
766
|
return {
|
|
763
767
|
records: this.slotsSnapshot().map(({ slot, generation, worldId, entityKey }) => ({
|
|
@@ -2449,6 +2453,10 @@ export class PersistentRenderScene {
|
|
|
2449
2453
|
return { min: [...bounds.min], max: [...bounds.max] };
|
|
2450
2454
|
}
|
|
2451
2455
|
|
|
2456
|
+
reflectionCaptureRevision(): string {
|
|
2457
|
+
return `${this.fullRebuilds}:${this.composition?.projection.contentRevision ?? 0}`;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2452
2460
|
inspect(): PersistentRenderSceneInspection {
|
|
2453
2461
|
const entry = this.composition;
|
|
2454
2462
|
const pointsLines = this.pointsLinesInspections;
|
package/src/ssao-config.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
// @forgeax/engine-render - SSAO parameter authority.
|
|
2
2
|
|
|
3
|
-
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
3
|
+
import { err, ok, type RenderPipelineAsset, type Result } from '@forgeax/engine-types';
|
|
4
4
|
import { PostProcessError } from './post-process-errors';
|
|
5
5
|
|
|
6
6
|
export const SSAO_DEFAULT_RADIUS = 0.5;
|
|
7
7
|
export const SSAO_DEFAULT_BIAS = 0.025;
|
|
8
8
|
export const SSAO_DEFAULT_INTENSITY = 1.0;
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
export type SsaoParameterConfig = Omit<
|
|
11
|
+
NonNullable<NonNullable<RenderPipelineAsset['config']>['ssao']>,
|
|
12
|
+
'enabled'
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
export const SSAO_SAMPLE_COUNTS = { low: 16, medium: 32, high: 64 } as const;
|
|
15
16
|
|
|
16
17
|
export interface ResolvedSsaoParameters {
|
|
17
18
|
readonly radius: number;
|
|
18
19
|
readonly bias: number;
|
|
19
20
|
readonly intensity: number;
|
|
21
|
+
readonly quality: 'low' | 'medium' | 'high';
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -29,6 +31,7 @@ export function getSsaoParameters(config: SsaoParameterConfig | undefined): Reso
|
|
|
29
31
|
radius: config?.radius ?? SSAO_DEFAULT_RADIUS,
|
|
30
32
|
bias: config?.bias ?? SSAO_DEFAULT_BIAS,
|
|
31
33
|
intensity: config?.intensity ?? SSAO_DEFAULT_INTENSITY,
|
|
34
|
+
quality: config?.quality ?? 'high',
|
|
32
35
|
};
|
|
33
36
|
}
|
|
34
37
|
|
|
@@ -41,7 +44,7 @@ export function resolveSsaoParameters(
|
|
|
41
44
|
config: SsaoParameterConfig | undefined,
|
|
42
45
|
): Result<ResolvedSsaoParameters, PostProcessError> {
|
|
43
46
|
const resolved = getSsaoParameters(config);
|
|
44
|
-
if (resolved.radius <= 0) {
|
|
47
|
+
if (!Number.isFinite(resolved.radius) || resolved.radius <= 0) {
|
|
45
48
|
return err(
|
|
46
49
|
new PostProcessError({
|
|
47
50
|
code: 'ssao-radius-non-positive',
|
|
@@ -49,7 +52,7 @@ export function resolveSsaoParameters(
|
|
|
49
52
|
}),
|
|
50
53
|
);
|
|
51
54
|
}
|
|
52
|
-
if (resolved.bias < 0) {
|
|
55
|
+
if (!Number.isFinite(resolved.bias) || resolved.bias < 0) {
|
|
53
56
|
return err(
|
|
54
57
|
new PostProcessError({
|
|
55
58
|
code: 'ssao-bias-negative',
|
|
@@ -57,5 +60,19 @@ export function resolveSsaoParameters(
|
|
|
57
60
|
}),
|
|
58
61
|
);
|
|
59
62
|
}
|
|
63
|
+
if (
|
|
64
|
+
!Number.isFinite(resolved.intensity) ||
|
|
65
|
+
resolved.intensity < 0 ||
|
|
66
|
+
!Object.hasOwn(SSAO_SAMPLE_COUNTS, resolved.quality)
|
|
67
|
+
) {
|
|
68
|
+
const paramName =
|
|
69
|
+
!Number.isFinite(resolved.intensity) || resolved.intensity < 0 ? 'intensity' : 'quality';
|
|
70
|
+
return err(
|
|
71
|
+
new PostProcessError({
|
|
72
|
+
code: 'ssao-parameter-invalid',
|
|
73
|
+
detail: { paramName, value: resolved[paramName] },
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
60
77
|
return ok(resolved);
|
|
61
78
|
}
|