@forgeax/engine-render 0.1.23 → 0.1.25
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 +231 -10
- package/dist/assembly/bundler-contract.d.ts +9 -0
- package/dist/assembly/bundler-contract.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +8 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
- package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +7 -243
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +3 -2
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
- package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
- package/dist/assembly/material/surface-projection.d.ts +24 -0
- package/dist/assembly/material/surface-projection.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts +188 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -0
- package/dist/assembly/material-shader-prewarm.d.ts +21 -0
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
- package/dist/assembly/recovery/generation.d.ts +46 -0
- package/dist/assembly/recovery/generation.d.ts.map +1 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts +10 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +19 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -0
- package/dist/assembly/renderer-lifecycle.d.ts +34 -0
- package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +55 -0
- package/dist/assembly/webgpu-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +152 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts +89 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-FF7K3FSO.mjs → chunk-ADHHVYLW.mjs} +89 -89
- package/dist/chunk-ADHHVYLW.mjs.map +1 -0
- package/dist/{chunk-YALPS44A.mjs → chunk-E34VL5VI.mjs} +47 -47
- package/dist/chunk-E34VL5VI.mjs.map +1 -0
- package/dist/{chunk-4L3P6DT5.mjs → chunk-GE3SDD72.mjs} +37 -5
- package/dist/chunk-GE3SDD72.mjs.map +1 -0
- package/dist/{chunk-HZUPSYW7.mjs → chunk-HKXTW355.mjs} +105 -15
- package/dist/chunk-HKXTW355.mjs.map +1 -0
- package/dist/chunk-JSEDTZYS.mjs +413 -0
- package/dist/chunk-JSEDTZYS.mjs.map +1 -0
- package/dist/{chunk-FBC4R44J.mjs → chunk-KM2NOX2I.mjs} +57 -57
- package/dist/chunk-KM2NOX2I.mjs.map +1 -0
- package/dist/{chunk-DIYW3M5D.mjs → chunk-N3RT2EUR.mjs} +2288 -2238
- package/dist/chunk-N3RT2EUR.mjs.map +1 -0
- package/dist/{chunk-ZUWKAZ2I.mjs → chunk-TCLDX7SZ.mjs} +1167 -368
- package/dist/chunk-TCLDX7SZ.mjs.map +1 -0
- package/dist/{chunk-QODA5UKU.mjs → chunk-ZZ4YQ474.mjs} +2 -2
- package/dist/chunk-ZZ4YQ474.mjs.map +1 -0
- package/dist/components/instances.d.ts +13 -31
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +20688 -16314
- 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 +24 -4
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/frame.d.ts +5 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/inspection.d.ts +7 -0
- package/dist/environment/inspection.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +20 -2
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +58 -2
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +13 -0
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +899 -0
- package/dist/extract/contracts.d.ts.map +1 -0
- package/dist/features/host.d.ts +2 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +3 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +34 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +7 -6
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +7 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +27 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instance-buffer-cache.d.ts +7 -1
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +101 -0
- package/dist/instances.d.ts.map +1 -0
- package/dist/internal.mjs +6 -6
- package/dist/light-buffer-layout.d.ts +3 -0
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts +96 -11
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +56 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/occlusion-proxy.d.ts +4 -0
- package/dist/occlusion-proxy.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +32 -9
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/prepare.d.ts +3 -0
- package/dist/points-lines/prepare.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +33 -0
- package/dist/points-lines/standard-owner.d.ts.map +1 -0
- package/dist/record/frame-snapshot.d.ts +18 -2
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +36 -4
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -17
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +11 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +30 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +28 -5
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +11 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +1 -1
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +65 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -0
- package/dist/render-contract.d.ts +68 -7
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +16 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +180 -22
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +131 -4
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +2 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +31 -1
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +6 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/taa-history-store.d.ts +15 -1
- package/dist/temporal/taa-history-store.d.ts.map +1 -1
- package/dist/temporal/transaction.d.ts +5 -0
- package/dist/temporal/transaction.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/device-feature-admission.unit.test.ts +6 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
- package/src/__tests__/environment-generation.integration.test.ts +23 -0
- package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
- package/src/__tests__/factory-contract.integration.test.ts +122 -7
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
- package/src/__tests__/gpu-scene.unit.test.ts +38 -2
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
- package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
- package/src/__tests__/instances-store.unit.test.ts +46 -0
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +29 -22
- package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
- package/src/__tests__/material-pass-policy.unit.test.ts +69 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +69 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
- package/src/__tests__/material-surface-authoring.test-d.ts +62 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
- package/src/__tests__/materials-transmission-validation.unit.test.ts +24 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -5
- package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +1 -1
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +127 -18
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
- package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
- package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
- package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
- package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
- package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
- package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
- package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
- package/src/__tests__/shader-manifest-fixture.ts +13 -16
- package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
- package/src/__tests__/skin-motion-regression.unit.test.ts +33 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +30 -2
- package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +60 -0
- package/src/__tests__/surface-standard-pipeline.browser.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.dawn.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.fixture.ts +132 -0
- package/src/__tests__/surface-variant-provenance.integration.test.ts +33 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +95 -85
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
- package/src/assembly/bundler-contract.ts +9 -0
- package/src/assembly/device-feature-admission.ts +15 -5
- package/src/assembly/extended-lighting-fallback.ts +216 -0
- package/src/assembly/factory.ts +83 -10088
- package/src/assembly/material/__tests__/standard-layer-plan-projection.integration.test.ts +18 -0
- package/src/assembly/material/__tests__/surface-pass-projection.integration.test.ts +62 -0
- package/src/assembly/material/assembly.ts +18 -2
- package/src/assembly/material/standard-layer-projection.ts +16 -0
- package/src/assembly/material/surface-projection.ts +90 -0
- package/src/assembly/material-shader-policy.ts +932 -0
- package/src/assembly/material-shader-prewarm.ts +88 -0
- package/src/assembly/mesh-ssbo-grow.ts +270 -0
- package/src/assembly/recovery/device-loss-fanout.ts +89 -0
- package/src/assembly/recovery/generation.ts +141 -0
- package/src/assembly/recovery/recovery-attempt.ts +800 -0
- package/src/assembly/recovery/renderer-recover.ts +906 -0
- package/src/assembly/renderer-facade.ts +342 -0
- package/src/assembly/renderer-frame-transaction.ts +45 -0
- package/src/assembly/renderer-helpers.ts +99 -0
- package/src/assembly/renderer-lifecycle.ts +159 -0
- package/src/assembly/shader-prewarm-policy.ts +157 -0
- package/src/assembly/webgpu-ready-contract.ts +14 -0
- package/src/assembly/webgpu-ready.ts +4066 -0
- package/src/assembly/webgpu-renderer.ts +4027 -0
- package/src/assembly/webgpu-vertex-layouts.ts +132 -0
- package/src/assets/asset-decoders.ts +27 -4
- package/src/components/camera.ts +1 -1
- package/src/components/instances.ts +14 -197
- package/src/debug-draw-glue.ts +1 -1
- package/src/device/device-scope.ts +35 -6
- package/src/device/gpu-residency.ts +194 -26
- package/src/environment/frame.ts +6 -0
- package/src/environment/inspection.ts +10 -0
- package/src/environment/lifecycle.ts +114 -8
- package/src/errors/recover.ts +76 -5
- package/src/errors/render.ts +17 -0
- package/src/extract/contracts.ts +974 -0
- package/src/features/host.ts +16 -0
- package/src/features/prepared-gpu-work.ts +20 -2
- package/src/features/prepared-graphics-store.ts +17 -0
- package/src/gpu-driven/production-raster.ts +131 -3
- package/src/gpu-scene.ts +87 -31
- package/src/ibl/IblPipelineCache.ts +134 -50
- package/src/ibl/skylight-bind-group.ts +26 -0
- package/src/index.ts +10 -1
- package/src/instance-buffer-cache.ts +14 -1
- package/src/instances.ts +288 -0
- package/src/light-buffer-layout.ts +3 -0
- package/src/materials.ts +365 -53
- package/src/mesh-material-bindings.ts +59 -0
- package/src/occlusion-proxy.ts +64 -0
- package/src/pbr-pipeline.ts +139 -15
- package/src/pipeline-builder.ts +14 -10
- package/src/pipeline-spec.ts +6 -14
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
- package/src/points-lines/prepare.ts +9 -0
- package/src/points-lines/standard-owner.ts +403 -0
- package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
- package/src/record/__tests__/temporal-payload.unit.test.ts +22 -43
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -1
- package/src/record/frame-snapshot.ts +34 -2
- package/src/record/frame-targets.ts +11 -1
- package/src/record/frame.ts +37 -4
- package/src/record/helpers.ts +1 -1
- package/src/record/main-pass-geometry.ts +727 -63
- package/src/record/main-pass-material.ts +316 -209
- package/src/record/main-pass-sprite-draws.ts +7 -8
- package/src/record/main-pass.ts +94 -6
- package/src/record/mesh-ssbo.ts +32 -10
- package/src/record/recovery-pipeline.ts +695 -0
- package/src/record/render-context.ts +39 -4
- package/src/record/shadow-pass.ts +46 -99
- package/src/record/typed-frame-graph.ts +45 -1
- package/src/record/view-ubo.ts +3 -3
- package/src/recovery/render-system-candidate.ts +876 -0
- package/src/render-contract.ts +69 -7
- package/src/render-system-extract-tail.ts +3039 -0
- package/src/render-system-extract.ts +177 -3003
- package/src/render-system.ts +906 -662
- package/src/scene/render-scene-types.ts +2 -0
- package/src/scene/render-scene.ts +703 -37
- package/src/systems/skin-palette-allocator.ts +129 -7
- package/src/temporal/frame-coordinator.ts +4 -1
- package/src/temporal/taa-history-store.ts +46 -2
- package/src/temporal/temporal-view.ts +1 -1
- package/src/temporal/transaction.ts +9 -0
- package/src/tilemap-chunk-extract-system.ts +1 -1
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
- package/src/transmission/__tests__/surface-compatibility.integration.test.ts +32 -0
- package/dist/chunk-4L3P6DT5.mjs.map +0 -1
- package/dist/chunk-4NPUASZR.mjs +0 -203
- package/dist/chunk-4NPUASZR.mjs.map +0 -1
- package/dist/chunk-DIYW3M5D.mjs.map +0 -1
- package/dist/chunk-FBC4R44J.mjs.map +0 -1
- package/dist/chunk-FF7K3FSO.mjs.map +0 -1
- package/dist/chunk-HZUPSYW7.mjs.map +0 -1
- package/dist/chunk-QODA5UKU.mjs.map +0 -1
- package/dist/chunk-YALPS44A.mjs.map +0 -1
- package/dist/chunk-ZUWKAZ2I.mjs.map +0 -1
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { GlyphText, selectActiveCameraIndex, getActiveCamera } from './chunk-FJ6P52EE.mjs';
|
|
2
|
-
import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams,
|
|
2
|
+
import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, Camera, bloomEnabledFromF32, antialiasFromF32, tonemapFromF32, cameraProjectionFromF32 } from './chunk-ADHHVYLW.mjs';
|
|
3
3
|
import { SpriteRegionOverride, SpriteInstances } from './chunk-JDWARUOI.mjs';
|
|
4
|
-
import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY,
|
|
5
|
-
import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, AtmosphereInvalidParameterError } from './chunk-
|
|
4
|
+
import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, selectPasses, resolveRenderTargetMaterialSource, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE } from './chunk-HKXTW355.mjs';
|
|
5
|
+
import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, AtmosphereInvalidParameterError } from './chunk-ZZ4YQ474.mjs';
|
|
6
6
|
import { err, ok, RhiError } from '@forgeax/engine-rhi';
|
|
7
7
|
import { resolveAssetHandle, walkMaterialPassesOverSharedRefs } from '@forgeax/engine-assets-runtime';
|
|
8
8
|
import { SpawnLightInvalidBoundsError, routeWorldError, SpriteInstancesMutuallyExclusiveWithInstancesError, SpriteInstancesRequiresSpriteShaderError, SpriteInstancesCountMismatchError, InstanceTransformsStrideMismatchError, readRenderArrayView } from '@forgeax/engine-ecs/projection';
|
|
9
|
-
import { PROCEDURAL_FLOATS_PER_VERTEX, deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
10
9
|
import { vec3, mat4, frustum, box3 } from '@forgeax/engine-math';
|
|
11
10
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
12
11
|
import { Transform, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
|
|
13
|
-
import {
|
|
12
|
+
import { STANDARD_PIPELINE_PARAM_SCHEMA } from '@forgeax/engine-shader';
|
|
14
13
|
import { R_MIN, err as err$1, ok as ok$1, TextError, toShared, handleSlot, AssetError, ASSET_ERROR_HINTS, materialValuesToLinearRuntime, derive, unpackSlot, materialGuidText } from '@forgeax/engine-types';
|
|
14
|
+
import { PROCEDURAL_FLOATS_PER_VERTEX, deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
15
|
+
import { Skin, SkinInstancesCoexistForbiddenError, SkeletonResolveFailedError, JointCountMismatchError, JointEntityDanglingError } from '@forgeax/engine-skinning';
|
|
15
16
|
import { resetFontConcurrency, trackFontConcurrency, layoutGlyphText, conservativeCubeAabb, bakeGlyphMesh } from '@forgeax/engine-graphics-extras';
|
|
16
17
|
|
|
17
18
|
// src/inspection-types.ts
|
|
@@ -869,6 +870,10 @@ function validateAtmosphereParameters(parameters) {
|
|
|
869
870
|
}
|
|
870
871
|
|
|
871
872
|
// src/environment/frame.ts
|
|
873
|
+
var SKYLIGHT_RECOVERY_FALLBACK = Object.freeze({
|
|
874
|
+
kind: "skylight",
|
|
875
|
+
active: false
|
|
876
|
+
});
|
|
872
877
|
var EnvironmentSelectionParameterError = class extends Error {
|
|
873
878
|
code = "environment-selection-invalid";
|
|
874
879
|
expected;
|
|
@@ -1598,2243 +1603,1207 @@ function createCookieProjectionMatrixData(count) {
|
|
|
1598
1603
|
return data;
|
|
1599
1604
|
}
|
|
1600
1605
|
|
|
1601
|
-
// src/render-system-extract.ts
|
|
1602
|
-
function
|
|
1603
|
-
const
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
);
|
|
1612
|
-
const
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
tags: passState.tags ?? {},
|
|
1655
|
-
renderState: pipelineRenderState(passState),
|
|
1656
|
-
// Material module identity is already closed in the cooked program.
|
|
1657
|
-
// It must never become a draw-time define map.
|
|
1658
|
-
defines: void 0,
|
|
1659
|
-
vertexEntry: pass.program.vertexEntry,
|
|
1660
|
-
fragmentEntry: pass.program.fragmentEntry,
|
|
1661
|
-
materialShaderId: runtimeMaterialShaderId(pass.program.module, pass.name),
|
|
1662
|
-
paramSnapshot,
|
|
1663
|
-
...passState.stencilReference !== void 0 && {
|
|
1664
|
-
stencilReference: passState.stencilReference
|
|
1606
|
+
// src/render-system-extract-tail.ts
|
|
1607
|
+
function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCachesByWorld, options = {}) {
|
|
1608
|
+
const cameraOwner = typeof owner === "number" ? owner : owner.cameraOwner;
|
|
1609
|
+
const resourceOwner = typeof owner === "number" ? owner : owner.resourceOwner;
|
|
1610
|
+
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
1611
|
+
if (skinPaletteAllocator !== null) {
|
|
1612
|
+
skinPaletteAllocator.resetForFrame();
|
|
1613
|
+
}
|
|
1614
|
+
const failedWorlds = /* @__PURE__ */ new Set();
|
|
1615
|
+
const resourceOwnerWorld = worlds[resourceOwner];
|
|
1616
|
+
const resourceOwnerFog = resourceOwnerWorld === void 0 ? null : selectFogFrame(resourceOwnerWorld) ?? null;
|
|
1617
|
+
const succeededFrames = [];
|
|
1618
|
+
const succeededIndices = [];
|
|
1619
|
+
const extractionOrder = Array.from({ length: worlds.length }, (_, wi) => wi).sort((a, b) => {
|
|
1620
|
+
if (a === cameraOwner) return -1;
|
|
1621
|
+
if (b === cameraOwner) return 1;
|
|
1622
|
+
return a - b;
|
|
1623
|
+
});
|
|
1624
|
+
const framesByWorld = /* @__PURE__ */ new Map();
|
|
1625
|
+
for (const wi of extractionOrder) {
|
|
1626
|
+
const world = worlds[wi];
|
|
1627
|
+
if (world === void 0 || failedWorlds.has(world)) continue;
|
|
1628
|
+
try {
|
|
1629
|
+
const isCameraOwner = wi === cameraOwner;
|
|
1630
|
+
const cameraOwnerFrame2 = framesByWorld.get(cameraOwner);
|
|
1631
|
+
const prepared = prepareExtractContext(world, {
|
|
1632
|
+
...assets !== void 0 ? { assets } : {},
|
|
1633
|
+
...pipelineState !== void 0 ? { pipelineState } : {},
|
|
1634
|
+
resourceOwnerFog: wi === resourceOwner ? resourceOwnerFog : null,
|
|
1635
|
+
...materialSnapshotCachesByWorld === void 0 ? {} : {
|
|
1636
|
+
materialSnapshotCache: materialSnapshotCachesByWorld.get(world) ?? (() => {
|
|
1637
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1638
|
+
materialSnapshotCachesByWorld.set(world, cache);
|
|
1639
|
+
return cache;
|
|
1640
|
+
})()
|
|
1641
|
+
},
|
|
1642
|
+
cull: options.cull === "none" ? "none" : isCameraOwner ? "self" : "external",
|
|
1643
|
+
renderables: options.renderables ?? "full",
|
|
1644
|
+
...options.renderableEntitiesByWorld?.[wi] === void 0 ? {} : { renderableEntities: options.renderableEntitiesByWorld[wi] },
|
|
1645
|
+
retainHidden: options.retainHidden ?? false,
|
|
1646
|
+
...options.getMaterialShaderArtifact === void 0 ? {} : { getMaterialShaderArtifact: options.getMaterialShaderArtifact },
|
|
1647
|
+
...options.instanceCollections === void 0 ? {} : { instanceCollections: options.instanceCollections },
|
|
1648
|
+
...cameraOwnerFrame2 === void 0 ? {} : { cullCameras: cameraOwnerFrame2.cameras }
|
|
1649
|
+
});
|
|
1650
|
+
const frame = extractFrame(world, prepared);
|
|
1651
|
+
framesByWorld.set(wi, frame);
|
|
1652
|
+
} catch (err6) {
|
|
1653
|
+
try {
|
|
1654
|
+
createWorldInternalView(world)._routeError(err6, {
|
|
1655
|
+
severity: Severity.Error,
|
|
1656
|
+
systemName: `RenderSystem.extractFrames(world[${wi}])`
|
|
1657
|
+
});
|
|
1658
|
+
} catch {
|
|
1665
1659
|
}
|
|
1666
|
-
}
|
|
1660
|
+
}
|
|
1667
1661
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
(
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
const
|
|
1675
|
-
const
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1662
|
+
for (let wi = 0; wi < worlds.length; wi++) {
|
|
1663
|
+
const frame = framesByWorld.get(wi);
|
|
1664
|
+
if (frame === void 0) continue;
|
|
1665
|
+
succeededFrames.push(frame);
|
|
1666
|
+
succeededIndices.push(wi);
|
|
1667
|
+
}
|
|
1668
|
+
const renderables = [];
|
|
1669
|
+
const dispatchEntries = [];
|
|
1670
|
+
const visibilitySnapshots = [];
|
|
1671
|
+
const featureVisibilitySnapshots = [];
|
|
1672
|
+
const hiddenEntityReports = [];
|
|
1673
|
+
for (let fi = 0; fi < succeededFrames.length; fi++) {
|
|
1674
|
+
const f = succeededFrames[fi];
|
|
1675
|
+
const wId = succeededIndices[fi];
|
|
1676
|
+
if (f === void 0 || wId === void 0) continue;
|
|
1677
|
+
const base = renderables.length;
|
|
1678
|
+
const visibilitySnapshot = f.visibilitySnapshots[0];
|
|
1679
|
+
const world = worlds[wId];
|
|
1680
|
+
if (visibilitySnapshot !== void 0) {
|
|
1681
|
+
visibilitySnapshots.push(visibilitySnapshot);
|
|
1682
|
+
if (world !== void 0)
|
|
1683
|
+
featureVisibilitySnapshots.push({ world, snapshot: visibilitySnapshot });
|
|
1683
1684
|
}
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1685
|
+
hiddenEntityReports.push(...f.hiddenEntityReports);
|
|
1686
|
+
for (const r of f.renderables) {
|
|
1687
|
+
renderables.push({
|
|
1688
|
+
...r,
|
|
1689
|
+
worldId: wId,
|
|
1690
|
+
...r.pointsLines === void 0 ? {} : { pointsLines: { ...r.pointsLines, worldId: wId } }
|
|
1691
|
+
});
|
|
1687
1692
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
continue;
|
|
1693
|
+
for (const d of f.dispatch) {
|
|
1694
|
+
dispatchEntries.push({ ...d, renderableIndex: (d.renderableIndex ?? 0) + base });
|
|
1691
1695
|
}
|
|
1692
|
-
auxiliary.push(candidate);
|
|
1693
1696
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1697
|
+
dispatchEntries.sort((a, b) => (a.queue ?? 0) - (b.queue ?? 0));
|
|
1698
|
+
const point = [];
|
|
1699
|
+
const spot = [];
|
|
1700
|
+
const rect = [];
|
|
1701
|
+
let directional;
|
|
1702
|
+
let directionalCount = 0;
|
|
1703
|
+
let lightViewProj;
|
|
1704
|
+
let splitPlanes;
|
|
1705
|
+
let cascadeCount;
|
|
1706
|
+
let cascadeBlend;
|
|
1707
|
+
let shadowMapSize;
|
|
1708
|
+
let depthBias;
|
|
1709
|
+
let normalBias;
|
|
1710
|
+
let directionalShadowQuality;
|
|
1711
|
+
let directionalShadowError;
|
|
1712
|
+
const pointShadow = [];
|
|
1713
|
+
let directionalCsmConfig;
|
|
1714
|
+
let directionalCsmDirection;
|
|
1715
|
+
for (const f of succeededFrames) {
|
|
1716
|
+
for (const p of f.lights.point) point.push(p);
|
|
1717
|
+
for (const s of f.lights.spot) spot.push(s);
|
|
1718
|
+
for (const r of f.lights.rect) rect.push(r);
|
|
1719
|
+
for (const ps of f.lights.pointShadow) pointShadow.push(ps);
|
|
1720
|
+
if (directional === void 0 && f.lights.directional !== void 0) {
|
|
1721
|
+
directional = f.lights.directional;
|
|
1722
|
+
lightViewProj = f.lights.lightViewProj;
|
|
1723
|
+
splitPlanes = f.lights.splitPlanes;
|
|
1724
|
+
cascadeCount = f.lights.cascadeCount;
|
|
1725
|
+
cascadeBlend = f.lights.cascadeBlend;
|
|
1726
|
+
shadowMapSize = f.lights.shadowMapSize;
|
|
1727
|
+
depthBias = f.lights.depthBias;
|
|
1728
|
+
normalBias = f.lights.normalBias;
|
|
1729
|
+
directionalShadowQuality = f.lights.directionalShadowQuality;
|
|
1730
|
+
directionalShadowError = f.lights.directionalShadowError;
|
|
1731
|
+
directionalCsmConfig = f.lights.directionalCsmConfig;
|
|
1732
|
+
directionalCsmDirection = f.lights.directionalCsmDirection;
|
|
1708
1733
|
}
|
|
1709
|
-
|
|
1710
|
-
}
|
|
1711
|
-
function resolveCameraTarget(world, raw) {
|
|
1712
|
-
if (raw === void 0 || raw <= 0) return void 0;
|
|
1713
|
-
const resolved = world.sharedRefs.resolve(
|
|
1714
|
-
toShared(Math.round(raw))
|
|
1715
|
-
);
|
|
1716
|
-
return resolved.ok ? resolved.value : void 0;
|
|
1717
|
-
}
|
|
1718
|
-
var BUILTIN_USER_REGION_TEXTURE_FIELDS = [
|
|
1719
|
-
"baseColorTexture",
|
|
1720
|
-
"metallicRoughnessTexture",
|
|
1721
|
-
"normalTexture",
|
|
1722
|
-
"specularTintTexture",
|
|
1723
|
-
"emissiveTexture",
|
|
1724
|
-
"occlusionTexture",
|
|
1725
|
-
"transmissionTexture",
|
|
1726
|
-
"thicknessTexture"
|
|
1727
|
-
];
|
|
1728
|
-
var BUILTIN_USER_REGION_TEXTURE_FIELD_SET = new Set(BUILTIN_USER_REGION_TEXTURE_FIELDS);
|
|
1729
|
-
var BUILTIN_BASE_COLOR_TEXTURE_FIELD_SET = /* @__PURE__ */ new Set(["baseColorTexture"]);
|
|
1730
|
-
function materialTextureFields(shaderId, fields) {
|
|
1731
|
-
if (fields !== void 0 && fields.size > 0) return fields;
|
|
1732
|
-
if (shaderId === "forgeax::default-standard-pbr" || shaderId === "forgeax::default-standard-pbr-skin" || shaderId === "forgeax::pbr-skin") {
|
|
1733
|
-
return BUILTIN_USER_REGION_TEXTURE_FIELD_SET;
|
|
1734
|
+
directionalCount += f.lights.directionalCount;
|
|
1734
1735
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1736
|
+
let cameraOwnerFrame;
|
|
1737
|
+
let resourceOwnerFrame;
|
|
1738
|
+
for (let fi = 0; fi < succeededFrames.length; fi++) {
|
|
1739
|
+
if (succeededIndices[fi] === cameraOwner) cameraOwnerFrame = succeededFrames[fi];
|
|
1740
|
+
if (succeededIndices[fi] === resourceOwner) resourceOwnerFrame = succeededFrames[fi];
|
|
1737
1741
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1742
|
+
const cameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.cameras] : [];
|
|
1743
|
+
const auxiliaryCameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.auxiliaryCameras] : [];
|
|
1744
|
+
const cubeCameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.cubeCameras] : [];
|
|
1745
|
+
const mergeCam = cameras[0];
|
|
1746
|
+
if (directionalCsmConfig !== void 0 && directionalCsmDirection !== void 0) {
|
|
1747
|
+
const mergeCameraData = mergeCam !== void 0 ? {
|
|
1748
|
+
world: mergeCam.world,
|
|
1749
|
+
fov: mergeCam.fov,
|
|
1750
|
+
aspect: mergeCam.aspect,
|
|
1751
|
+
near: mergeCam.near,
|
|
1752
|
+
far: mergeCam.far,
|
|
1753
|
+
projection: mergeCam.projection,
|
|
1754
|
+
orthoLeft: mergeCam.orthoLeft,
|
|
1755
|
+
orthoRight: mergeCam.orthoRight,
|
|
1756
|
+
orthoBottom: mergeCam.orthoBottom,
|
|
1757
|
+
orthoTop: mergeCam.orthoTop
|
|
1758
|
+
} : void 0;
|
|
1759
|
+
const csm = computeDirectionalCsm(
|
|
1760
|
+
directionalCsmDirection,
|
|
1761
|
+
directionalCsmConfig,
|
|
1762
|
+
mergeCameraData
|
|
1763
|
+
);
|
|
1764
|
+
if (csm !== null) {
|
|
1765
|
+
lightViewProj = csm.lightViewProj;
|
|
1766
|
+
splitPlanes = csm.splitPlanes;
|
|
1767
|
+
cascadeCount = csm.cascadeCount;
|
|
1768
|
+
cascadeBlend = csm.cascadeBlend;
|
|
1769
|
+
shadowMapSize = csm.shadowMapSize;
|
|
1770
|
+
directionalShadowQuality = csm.directionalShadowQuality;
|
|
1771
|
+
}
|
|
1743
1772
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1773
|
+
const lights = {
|
|
1774
|
+
directional,
|
|
1775
|
+
directionalCount,
|
|
1776
|
+
point,
|
|
1777
|
+
spot,
|
|
1778
|
+
rect,
|
|
1779
|
+
lightViewProj,
|
|
1780
|
+
splitPlanes,
|
|
1781
|
+
cascadeCount,
|
|
1782
|
+
cascadeBlend,
|
|
1783
|
+
shadowMapSize,
|
|
1784
|
+
depthBias,
|
|
1785
|
+
normalBias,
|
|
1786
|
+
directionalShadowQuality,
|
|
1787
|
+
directionalShadowError,
|
|
1788
|
+
pointShadow,
|
|
1789
|
+
directionalCsmConfig,
|
|
1790
|
+
directionalCsmDirection
|
|
1791
|
+
};
|
|
1792
|
+
const volumetricFog = resourceOwnerFrame?.volumetricFog;
|
|
1793
|
+
const skylight = resourceOwnerFrame?.skylight;
|
|
1794
|
+
const skylightCount = resourceOwnerFrame?.skylightCount ?? 0;
|
|
1795
|
+
const skybox = resourceOwnerFrame?.skybox;
|
|
1796
|
+
const skyboxCount = resourceOwnerFrame?.skyboxCount ?? 0;
|
|
1797
|
+
const fog = resourceOwnerFrame?.fog;
|
|
1798
|
+
const fogFailure = resourceOwnerFrame?.fogFailure;
|
|
1799
|
+
const environment = resourceOwnerFrame?.environment;
|
|
1800
|
+
const lightProbes = succeededFrames.flatMap((frame) => frame.lightProbes ?? []);
|
|
1801
|
+
const postProcessParams = new Map(resourceOwnerFrame?.postProcessParams);
|
|
1802
|
+
const OUTPUT_TRANSFORM_PARAM_KEY = STANDARD_OUTPUT_TRANSFORM_FEATURE_ID;
|
|
1803
|
+
const cameraTonemapParam = cameraOwnerFrame?.postProcessParams.get(OUTPUT_TRANSFORM_PARAM_KEY);
|
|
1804
|
+
if (cameraTonemapParam !== void 0) {
|
|
1805
|
+
postProcessParams.set(OUTPUT_TRANSFORM_PARAM_KEY, cameraTonemapParam);
|
|
1806
|
+
} else {
|
|
1807
|
+
postProcessParams.delete(OUTPUT_TRANSFORM_PARAM_KEY);
|
|
1755
1808
|
}
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1809
|
+
const frustumStats = {
|
|
1810
|
+
culled: succeededFrames.reduce((s, f) => s + f.frustumStats.culled, 0),
|
|
1811
|
+
total: succeededFrames.reduce((s, f) => s + f.frustumStats.total, 0)
|
|
1812
|
+
};
|
|
1813
|
+
const visibilityStats = {
|
|
1814
|
+
explicitlyHidden: succeededFrames.reduce((s, f) => s + f.visibilityStats.explicitlyHidden, 0)
|
|
1815
|
+
};
|
|
1816
|
+
const reflectionProbes = succeededFrames.flatMap((f, index) => {
|
|
1817
|
+
const worldId = succeededIndices[index] ?? 0;
|
|
1818
|
+
return (f.reflectionProbes ?? []).map((probe) => ({ ...probe, worldId }));
|
|
1819
|
+
});
|
|
1820
|
+
if (options.renderables !== "none" && options.renderableEntitiesByWorld === void 0) {
|
|
1821
|
+
options.instanceCollections?.retain(
|
|
1822
|
+
new Set(
|
|
1823
|
+
renderables.flatMap(
|
|
1824
|
+
(row) => row.instances?.collectionId === void 0 ? [] : [row.instances.collectionId]
|
|
1825
|
+
)
|
|
1826
|
+
)
|
|
1827
|
+
);
|
|
1828
|
+
if (skinPaletteAllocator !== null && typeof skinPaletteAllocator.retainSliceKeys === "function") {
|
|
1829
|
+
skinPaletteAllocator.retainSliceKeys(
|
|
1830
|
+
new Set(
|
|
1831
|
+
renderables.flatMap(
|
|
1832
|
+
(row) => row.skin === void 0 ? [] : [`${worlds[row.worldId]?.identity ?? row.worldId}:${row.entityKey}`]
|
|
1833
|
+
)
|
|
1834
|
+
)
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1772
1837
|
}
|
|
1773
1838
|
return {
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
...
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1839
|
+
cameras,
|
|
1840
|
+
auxiliaryCameras,
|
|
1841
|
+
cubeCameras,
|
|
1842
|
+
reflectionProbes,
|
|
1843
|
+
lights,
|
|
1844
|
+
...volumetricFog === void 0 ? {} : { volumetricFog: { ...volumetricFog, worldId: resourceOwner } },
|
|
1845
|
+
renderables,
|
|
1846
|
+
dispatch: dispatchEntries,
|
|
1847
|
+
skylight,
|
|
1848
|
+
skylightCount,
|
|
1849
|
+
lightProbes,
|
|
1850
|
+
skybox,
|
|
1851
|
+
skyboxCount,
|
|
1852
|
+
fog,
|
|
1853
|
+
...fogFailure === void 0 ? {} : { fogFailure },
|
|
1854
|
+
environment,
|
|
1855
|
+
environmentReady: resourceOwnerFrame !== void 0 && environment !== void 0,
|
|
1856
|
+
frustumStats,
|
|
1857
|
+
visibilityStats,
|
|
1858
|
+
postProcessParams,
|
|
1859
|
+
visibilitySnapshots,
|
|
1860
|
+
featureVisibilitySnapshots,
|
|
1861
|
+
hiddenEntityReports
|
|
1783
1862
|
};
|
|
1784
1863
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
const
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
if (cached !== void 0 && cached.payload === payload) {
|
|
1796
|
-
const cachedHandle = toShared(cached.handle);
|
|
1797
|
-
if (world.sharedRefs.resolve(cachedHandle).ok) return cachedHandle;
|
|
1798
|
-
}
|
|
1799
|
-
if (cached !== void 0) {
|
|
1800
|
-
world.sharedRefs.release(toShared(cached.handle));
|
|
1801
|
-
perWorld.delete(key);
|
|
1802
|
-
}
|
|
1803
|
-
if (payload === void 0) return void 0;
|
|
1804
|
-
const handle = world.internSharedRef(brand, payload);
|
|
1805
|
-
perWorld.set(key, { handle, payload });
|
|
1806
|
-
return handle;
|
|
1807
|
-
}
|
|
1808
|
-
function resolveVideoFieldHandle(value, world, assetsRef) {
|
|
1809
|
-
const texture = materialTextureValue(value);
|
|
1810
|
-
const textureGuid = assetReferenceText(texture?.texture ?? value);
|
|
1811
|
-
if (textureGuid === void 0) return void 0;
|
|
1812
|
-
const payload = assetsRef.lookup(textureGuid);
|
|
1813
|
-
if (payload === void 0 || payload.kind !== "video") return void 0;
|
|
1814
|
-
return internSharedRefFromGuid(world, assetsRef, textureGuid, "VideoAsset");
|
|
1815
|
-
}
|
|
1816
|
-
function materialTextureValue(value) {
|
|
1817
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
1818
|
-
const textureValue = value;
|
|
1819
|
-
return typeof textureValue.texture === "number" || typeof textureValue.texture === "string" || textureValue.texture instanceof Uint8Array ? textureValue : void 0;
|
|
1820
|
-
}
|
|
1821
|
-
function assetReferenceText(value) {
|
|
1822
|
-
if (typeof value === "string") return value;
|
|
1823
|
-
if (value instanceof Uint8Array && isAssetGuidBytes(value)) return AssetGuid.format(value);
|
|
1824
|
-
return void 0;
|
|
1825
|
-
}
|
|
1826
|
-
function isAssetGuidBytes(value) {
|
|
1827
|
-
return value.byteLength === 16;
|
|
1828
|
-
}
|
|
1829
|
-
function materialNormalScale(values) {
|
|
1830
|
-
for (const [field, value] of Object.entries(values)) {
|
|
1831
|
-
if (field !== "normalTexture") continue;
|
|
1832
|
-
const scale = materialTextureValue(value)?.normalScale;
|
|
1833
|
-
return typeof scale === "number" && Number.isFinite(scale) ? scale : 1;
|
|
1864
|
+
function hasFiniteOrderedLocalAabb(aabb) {
|
|
1865
|
+
if (aabb === void 0 || aabb.length !== 6) return false;
|
|
1866
|
+
const minX = aabb[0];
|
|
1867
|
+
const minY = aabb[1];
|
|
1868
|
+
const minZ = aabb[2];
|
|
1869
|
+
const maxX = aabb[3];
|
|
1870
|
+
const maxY = aabb[4];
|
|
1871
|
+
const maxZ = aabb[5];
|
|
1872
|
+
if (minX === void 0 || minY === void 0 || minZ === void 0 || maxX === void 0 || maxY === void 0 || maxZ === void 0) {
|
|
1873
|
+
return false;
|
|
1834
1874
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
function materialTextureRef(value) {
|
|
1838
|
-
return materialTextureValue(value)?.texture ?? value;
|
|
1839
|
-
}
|
|
1840
|
-
function collectMaterialTextureCoordinates(values) {
|
|
1841
|
-
const out = /* @__PURE__ */ new Map();
|
|
1842
|
-
for (const field of [
|
|
1843
|
-
"baseColorTexture",
|
|
1844
|
-
"metallicRoughnessTexture",
|
|
1845
|
-
"normalTexture",
|
|
1846
|
-
"specularTintTexture",
|
|
1847
|
-
"emissiveTexture",
|
|
1848
|
-
"occlusionTexture"
|
|
1849
|
-
]) {
|
|
1850
|
-
const coordinates = materialTextureValue(values[field])?.coordinates;
|
|
1851
|
-
if (coordinates !== void 0) out.set(field, coordinates);
|
|
1875
|
+
if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(minZ) || !Number.isFinite(maxX) || !Number.isFinite(maxY) || !Number.isFinite(maxZ)) {
|
|
1876
|
+
return false;
|
|
1852
1877
|
}
|
|
1853
|
-
return
|
|
1878
|
+
return minX <= maxX && minY <= maxY && minZ <= maxZ;
|
|
1854
1879
|
}
|
|
1855
|
-
function
|
|
1856
|
-
const
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
out.set(field, resolved.value);
|
|
1880
|
+
function morphSnapshotFor(mesh, weights) {
|
|
1881
|
+
const targets = mesh.morphTargets;
|
|
1882
|
+
if (targets === void 0 || targets.length === 0 || weights === void 0) return void 0;
|
|
1883
|
+
if (weights.length !== targets.length) return void 0;
|
|
1884
|
+
const firstPositions = targets[0]?.position;
|
|
1885
|
+
if (firstPositions === void 0 || firstPositions.length === 0 || firstPositions.length % 3 !== 0) {
|
|
1886
|
+
return void 0;
|
|
1863
1887
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
const sampler = resolveSampler(materialTextureValue(value)?.sampler);
|
|
1870
|
-
if (sampler !== void 0) out.set(field, sampler);
|
|
1888
|
+
const vertexCount = firstPositions.length / 3;
|
|
1889
|
+
if (mesh.vertices.length % vertexCount !== 0) return void 0;
|
|
1890
|
+
for (let targetIndex = 0; targetIndex < targets.length; targetIndex += 1) {
|
|
1891
|
+
const target = targets[targetIndex];
|
|
1892
|
+
if (target?.position?.length !== firstPositions.length) return void 0;
|
|
1871
1893
|
}
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
|
|
1894
|
+
const copied = new Float32Array(weights.length);
|
|
1895
|
+
for (let index = 0; index < weights.length; index += 1) {
|
|
1896
|
+
const weight = weights[index] ?? Number.NaN;
|
|
1897
|
+
if (!Number.isFinite(weight)) return void 0;
|
|
1898
|
+
copied[index] = weight;
|
|
1875
1899
|
}
|
|
1876
|
-
return
|
|
1900
|
+
return { weights: copied, targetCount: targets.length };
|
|
1877
1901
|
}
|
|
1878
|
-
function
|
|
1879
|
-
const
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1902
|
+
function extractFrame(world, context) {
|
|
1903
|
+
const {
|
|
1904
|
+
assets,
|
|
1905
|
+
pipelineState,
|
|
1906
|
+
materialSnapshotCache: persistentMaterialSnapshotCache,
|
|
1907
|
+
cull: cullMode,
|
|
1908
|
+
resourceOwnerFog,
|
|
1909
|
+
getMaterialShaderArtifact,
|
|
1910
|
+
instanceCollections,
|
|
1911
|
+
renderableEntities,
|
|
1912
|
+
retainHidden
|
|
1913
|
+
} = context;
|
|
1914
|
+
const fog = resourceOwnerFog === void 0 ? selectFogFrame(world) : resourceOwnerFog ?? void 0;
|
|
1915
|
+
const fogFailure = fogState(world).failure;
|
|
1916
|
+
const visibility = context.visibility.hasAnyHiddenIntent ? context.visibility : void 0;
|
|
1917
|
+
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
1918
|
+
const directionalLightQuery = world.query({ read: [DirectionalLight] }).unwrap();
|
|
1919
|
+
const worldInternal = createWorldInternalView(world);
|
|
1920
|
+
let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
|
|
1921
|
+
const cameraRoles = selectCameraRoles(world);
|
|
1922
|
+
const cameras = [...cameraRoles.display];
|
|
1923
|
+
const auxiliaryCameras = cameraRoles.auxiliary;
|
|
1924
|
+
const cubeCameras = collectCubeCameraSnapshots(world);
|
|
1925
|
+
const reflectionProbes = collectReflectionProbeFacts(world);
|
|
1926
|
+
let directional;
|
|
1927
|
+
let directionalCount = 0;
|
|
1928
|
+
let firstHitCastShadow;
|
|
1929
|
+
let firstHitShadowFields;
|
|
1930
|
+
for (const row of directionalLightQuery) {
|
|
1931
|
+
const l = row.get(DirectionalLight);
|
|
1932
|
+
directionalCount += 1;
|
|
1933
|
+
const intensity = l.intensity;
|
|
1934
|
+
const snapshot = {
|
|
1935
|
+
kind: "directional",
|
|
1936
|
+
entity: row.entity,
|
|
1937
|
+
direction: vec3.create(l.direction[0] ?? 0, l.direction[1] ?? -1, l.direction[2] ?? 0),
|
|
1938
|
+
color: vec3.create(
|
|
1939
|
+
(l.color[0] ?? 1) * intensity,
|
|
1940
|
+
(l.color[1] ?? 1) * intensity,
|
|
1941
|
+
(l.color[2] ?? 1) * intensity
|
|
1942
|
+
),
|
|
1943
|
+
intensity
|
|
1944
|
+
};
|
|
1945
|
+
if (directional === void 0) {
|
|
1946
|
+
directional = snapshot;
|
|
1947
|
+
firstHitCastShadow = l.castShadow;
|
|
1948
|
+
firstHitShadowFields = {
|
|
1949
|
+
cascadeCount: l.cascadeCount,
|
|
1950
|
+
splitLambda: l.splitLambda,
|
|
1951
|
+
cascadeBlend: l.cascadeBlend,
|
|
1952
|
+
mapSize: l.mapSize,
|
|
1953
|
+
depthBias: l.depthBias,
|
|
1954
|
+
normalBias: l.normalBias,
|
|
1955
|
+
shadowDistance: l.shadowDistance,
|
|
1956
|
+
shadowFilter: l.shadowFilter,
|
|
1957
|
+
shadowAngularRadius: l.shadowAngularRadius,
|
|
1958
|
+
maxPenumbraTexels: l.maxPenumbraTexels
|
|
1959
|
+
};
|
|
1889
1960
|
}
|
|
1890
|
-
const handle = resolveTex(materialTextureRef(pv[field]), "TextureAsset");
|
|
1891
|
-
if (handle !== void 0) out.set(field, handle);
|
|
1892
1961
|
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
{
|
|
1907
|
-
name: parameter.name,
|
|
1908
|
-
type: parameter.type === "texture_cube" ? "texture_cube" : "texture2d"
|
|
1909
|
-
}
|
|
1910
|
-
];
|
|
1962
|
+
let directionalShadowError;
|
|
1963
|
+
if (directional !== void 0 && firstHitShadowFields !== void 0) {
|
|
1964
|
+
const validation = validateDirectionalLightData({
|
|
1965
|
+
direction: directional.direction,
|
|
1966
|
+
castShadow: firstHitCastShadow,
|
|
1967
|
+
...firstHitShadowFields
|
|
1968
|
+
});
|
|
1969
|
+
if (!validation.ok) {
|
|
1970
|
+
directionalShadowError = validation.error;
|
|
1971
|
+
worldInternal._routeError(directionalShadowError, {
|
|
1972
|
+
severity: Severity.Error,
|
|
1973
|
+
systemName: "RenderSystem.extract (directional-shadow)"
|
|
1974
|
+
});
|
|
1911
1975
|
}
|
|
1912
|
-
return [
|
|
1913
|
-
{
|
|
1914
|
-
name: parameter.name,
|
|
1915
|
-
type: parameter.type,
|
|
1916
|
-
...parameter.colorSpace === void 0 ? {} : { colorSpace: parameter.colorSpace }
|
|
1917
|
-
}
|
|
1918
|
-
];
|
|
1919
|
-
});
|
|
1920
|
-
}
|
|
1921
|
-
function materialColorParameterSchema(parameters, shaderId, assets) {
|
|
1922
|
-
if (shaderId === void 0) return parameters;
|
|
1923
|
-
const shader = assets.shaderRegistry.findMaterialArtifact(shaderId);
|
|
1924
|
-
if (!shader.ok) return parameters;
|
|
1925
|
-
const byName = new Map(
|
|
1926
|
-
shader.value.paramSchema.map((parameter) => [parameter.name, parameter])
|
|
1927
|
-
);
|
|
1928
|
-
for (const parameter of parameters) byName.set(parameter.name, parameter);
|
|
1929
|
-
return [...byName.values()];
|
|
1930
|
-
}
|
|
1931
|
-
var MATERIAL_PARENT_CHAIN_LIMIT = 128;
|
|
1932
|
-
function isDeepFrozen(value, seen = /* @__PURE__ */ new Set()) {
|
|
1933
|
-
if (typeof value !== "object" || value === null) return true;
|
|
1934
|
-
if (seen.has(value)) return true;
|
|
1935
|
-
if (!Object.isFrozen(value)) return false;
|
|
1936
|
-
seen.add(value);
|
|
1937
|
-
for (const child of Object.values(value)) {
|
|
1938
|
-
if (!isDeepFrozen(child, seen)) return false;
|
|
1939
|
-
}
|
|
1940
|
-
return true;
|
|
1941
|
-
}
|
|
1942
|
-
function captureMaterialCacheChain(root, assets) {
|
|
1943
|
-
const chain = [];
|
|
1944
|
-
const visitedParentGuids = /* @__PURE__ */ new Set();
|
|
1945
|
-
let current = root;
|
|
1946
|
-
for (let depth = 0; depth < MATERIAL_PARENT_CHAIN_LIMIT; depth += 1) {
|
|
1947
|
-
const parentRef = current.parent;
|
|
1948
|
-
const parentGuid = parentRef === void 0 ? void 0 : materialGuidText(parentRef);
|
|
1949
|
-
chain.push({ asset: current, parentGuid });
|
|
1950
|
-
if (parentGuid === void 0) return chain;
|
|
1951
|
-
if (parentRef === void 0) return void 0;
|
|
1952
|
-
if (visitedParentGuids.has(parentGuid)) return void 0;
|
|
1953
|
-
visitedParentGuids.add(parentGuid);
|
|
1954
|
-
const parent = assets.lookup(parentRef);
|
|
1955
|
-
if (parent?.kind !== "material") return void 0;
|
|
1956
|
-
current = parent;
|
|
1957
|
-
}
|
|
1958
|
-
return void 0;
|
|
1959
|
-
}
|
|
1960
|
-
function readPersistentMaterialSnapshot(cache, handleRaw, assets) {
|
|
1961
|
-
const entry = cache?.get(handleRaw);
|
|
1962
|
-
if (entry === void 0) return void 0;
|
|
1963
|
-
if (entry.crossFrameSafe && entry.chain !== void 0 && entry.catalogEpoch === assets.catalogEpoch)
|
|
1964
|
-
return entry;
|
|
1965
|
-
cache?.delete(handleRaw);
|
|
1966
|
-
return void 0;
|
|
1967
|
-
}
|
|
1968
|
-
function readStablePersistentMaterialSnapshot(cache, handleRaw, assets) {
|
|
1969
|
-
const entry = cache?.get(handleRaw);
|
|
1970
|
-
return entry?.crossFrameSafe === true && entry.chain !== void 0 && entry.catalogEpoch === assets.catalogEpoch ? entry : void 0;
|
|
1971
|
-
}
|
|
1972
|
-
function storeMaterialSnapshot(cache, handleRaw, snapshot, passes, root, assets) {
|
|
1973
|
-
const chain = captureMaterialCacheChain(root, assets);
|
|
1974
|
-
const entry = {
|
|
1975
|
-
snapshot,
|
|
1976
|
-
passes,
|
|
1977
|
-
crossFrameSafe: chain?.every(({ asset }) => isDeepFrozen(asset)) === true,
|
|
1978
|
-
...chain === void 0 ? {} : { chain },
|
|
1979
|
-
...chain === void 0 ? {} : { catalogEpoch: assets.catalogEpoch }
|
|
1980
|
-
};
|
|
1981
|
-
cache.set(handleRaw, entry);
|
|
1982
|
-
return entry;
|
|
1983
|
-
}
|
|
1984
|
-
function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache) {
|
|
1985
|
-
if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
|
|
1986
|
-
const cached = materialSnapshotCache?.get(handleRaw);
|
|
1987
|
-
if (cached !== void 0) return cached.snapshot;
|
|
1988
|
-
const stablePersistentCached = readStablePersistentMaterialSnapshot(
|
|
1989
|
-
persistentMaterialSnapshotCache,
|
|
1990
|
-
handleRaw,
|
|
1991
|
-
assetsRef
|
|
1992
|
-
);
|
|
1993
|
-
if (stablePersistentCached !== void 0) {
|
|
1994
|
-
materialSnapshotCache?.set(handleRaw, stablePersistentCached);
|
|
1995
|
-
return stablePersistentCached.snapshot;
|
|
1996
|
-
}
|
|
1997
|
-
const tagged = toShared(handleRaw);
|
|
1998
|
-
const res = resolveAssetHandle(world, tagged);
|
|
1999
|
-
if (!res.ok) return defaultMaterialSnapshot(handleRaw);
|
|
2000
|
-
const asset = res.value;
|
|
2001
|
-
if (asset.kind !== "material") return defaultMaterialSnapshot(handleRaw);
|
|
2002
|
-
const persistentCached = readPersistentMaterialSnapshot(
|
|
2003
|
-
persistentMaterialSnapshotCache,
|
|
2004
|
-
handleRaw,
|
|
2005
|
-
assetsRef
|
|
2006
|
-
);
|
|
2007
|
-
if (persistentCached !== void 0) {
|
|
2008
|
-
materialSnapshotCache?.set(handleRaw, persistentCached);
|
|
2009
|
-
return persistentCached.snapshot;
|
|
2010
1976
|
}
|
|
2011
|
-
const
|
|
2012
|
-
|
|
2013
|
-
const
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
const metallicPv = typeof pv.metallic === "number" ? pv.metallic : 0;
|
|
2028
|
-
const roughnessPv = typeof pv.roughness === "number" ? pv.roughness : 0.5;
|
|
2029
|
-
const clearcoatPv = typeof pv.clearcoat === "number" ? pv.clearcoat : 0;
|
|
2030
|
-
const clearcoatRoughnessPv = typeof pv.clearcoatRoughness === "number" ? pv.clearcoatRoughness : 0.5;
|
|
2031
|
-
const specularTintPv = pv.specularTint;
|
|
2032
|
-
const normalScalePv = materialNormalScale(pv);
|
|
2033
|
-
const paramSnap = {};
|
|
2034
|
-
for (const [k, v] of Object.entries(pv)) {
|
|
2035
|
-
if (typeof v === "number") paramSnap[k] = v;
|
|
2036
|
-
else if (typeof v === "string") paramSnap[k] = v;
|
|
2037
|
-
else if (Array.isArray(v) && v.every((x) => typeof x === "number")) {
|
|
2038
|
-
paramSnap[k] = v;
|
|
1977
|
+
const pointSnapshots = [];
|
|
1978
|
+
const pointSnapshotEntities = [];
|
|
1979
|
+
const pointLightQuery = world.query({
|
|
1980
|
+
read: [PointLight],
|
|
1981
|
+
optional: [Transform, GlobalTransform]
|
|
1982
|
+
}).unwrap();
|
|
1983
|
+
for (const row of pointLightQuery) {
|
|
1984
|
+
const p = row.get(PointLight);
|
|
1985
|
+
const hasTransform = row.get(GlobalTransform) !== void 0;
|
|
1986
|
+
const intensity = p.intensity;
|
|
1987
|
+
const range = p.range;
|
|
1988
|
+
const entityId = row.entity;
|
|
1989
|
+
let worldMat;
|
|
1990
|
+
if (hasTransform) {
|
|
1991
|
+
const view = worldInternal._getArrayView(entityId, GlobalTransform, "world");
|
|
1992
|
+
if (view !== void 0) worldMat = new Float32Array(view);
|
|
2039
1993
|
}
|
|
1994
|
+
const position = worldMat !== void 0 ? mat4.getTranslation(vec3.create(), worldMat) : vec3.create(0, 0, 0);
|
|
1995
|
+
pointSnapshots.push({
|
|
1996
|
+
kind: "point",
|
|
1997
|
+
entity: entityId,
|
|
1998
|
+
position,
|
|
1999
|
+
color: vec3.create(
|
|
2000
|
+
(p.color[0] ?? 1) * intensity,
|
|
2001
|
+
(p.color[1] ?? 1) * intensity,
|
|
2002
|
+
(p.color[2] ?? 1) * intensity
|
|
2003
|
+
),
|
|
2004
|
+
intensity,
|
|
2005
|
+
invRangeSquared: computeInvRangeSquared(range)
|
|
2006
|
+
});
|
|
2007
|
+
pointSnapshotEntities.push(entityId);
|
|
2040
2008
|
}
|
|
2041
|
-
const
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
const samplerHandles = collectMaterialTextureSamplers(
|
|
2063
|
-
pv,
|
|
2064
|
-
(value) => resolveTexLike(materialTextureRef(value), "SamplerAsset")
|
|
2065
|
-
);
|
|
2066
|
-
const textureSources = collectMaterialTextureSources(pv, world);
|
|
2067
|
-
const emissiveTextureHandle = resolveTexLike(
|
|
2068
|
-
materialTextureRef(pv.emissiveTexture),
|
|
2069
|
-
"TextureAsset"
|
|
2070
|
-
);
|
|
2071
|
-
const occlusionTextureHandle = resolveTexLike(
|
|
2072
|
-
materialTextureRef(pv.occlusionTexture),
|
|
2073
|
-
"TextureAsset"
|
|
2074
|
-
);
|
|
2075
|
-
const textureCoordinates = collectMaterialTextureCoordinates(pv);
|
|
2076
|
-
const baseColorTextureHandle = textureHandles.get("baseColorTexture");
|
|
2077
|
-
const metallicRoughnessTextureHandle = textureHandles.get("metallicRoughnessTexture");
|
|
2078
|
-
const normalTextureHandle = textureHandles.get("normalTexture");
|
|
2079
|
-
const emissivePv = pv.emissive;
|
|
2080
|
-
const snapshot = {
|
|
2081
|
-
baseColor,
|
|
2082
|
-
metallic: metallicPv,
|
|
2083
|
-
roughness: roughnessPv,
|
|
2084
|
-
clearcoat: clearcoatPv,
|
|
2085
|
-
clearcoatRoughness: clearcoatRoughnessPv,
|
|
2086
|
-
...specularTintPv !== void 0 && {
|
|
2087
|
-
specularTint: [
|
|
2088
|
-
specularTintPv[0] ?? 1,
|
|
2089
|
-
specularTintPv[1] ?? 1,
|
|
2090
|
-
specularTintPv[2] ?? 1
|
|
2091
|
-
]
|
|
2092
|
-
},
|
|
2093
|
-
normalScale: normalScalePv,
|
|
2094
|
-
materialShaderId: firstPassShader,
|
|
2095
|
-
materialHandle: handleRaw,
|
|
2096
|
-
renderState: pipelineRenderState(allPasses[0]?.renderState),
|
|
2097
|
-
paramSnapshot: paramSnap,
|
|
2098
|
-
...materialParamSchema.length > 0 && { materialParamSchema },
|
|
2099
|
-
...textureCoordinates.size > 0 && { textureCoordinates },
|
|
2100
|
-
...textureHandles.size > 0 && { textureHandles },
|
|
2101
|
-
...textureSources.size > 0 && { textureSources },
|
|
2102
|
-
...videoTextureFields.size > 0 && { videoTextureFields },
|
|
2103
|
-
...samplerHandles.size > 0 && { samplerHandles },
|
|
2104
|
-
...baseColorTextureHandle !== void 0 && { baseColorTexture: baseColorTextureHandle },
|
|
2105
|
-
...metallicRoughnessTextureHandle !== void 0 && {
|
|
2106
|
-
metallicRoughnessTexture: metallicRoughnessTextureHandle
|
|
2107
|
-
},
|
|
2108
|
-
...normalTextureHandle !== void 0 && { normalTexture: normalTextureHandle },
|
|
2109
|
-
...emissivePv !== void 0 && {
|
|
2110
|
-
emissive: [emissivePv[0] ?? 0, emissivePv[1] ?? 0, emissivePv[2] ?? 0]
|
|
2111
|
-
},
|
|
2112
|
-
...typeof pv.emissiveIntensity === "number" && { emissiveIntensity: pv.emissiveIntensity },
|
|
2113
|
-
...emissiveTextureHandle !== void 0 && { emissiveTexture: emissiveTextureHandle },
|
|
2114
|
-
...occlusionTextureHandle !== void 0 && { occlusionTexture: occlusionTextureHandle },
|
|
2115
|
-
...typeof pv.occlusionStrength === "number" && { occlusionStrength: pv.occlusionStrength },
|
|
2116
|
-
// feat-city-glb Bug 5 (per-submesh transparency): derive `transparent`
|
|
2117
|
-
// from the first pass's `renderState.blend` presence, identical to the
|
|
2118
|
-
// entity-level snapshot builder (extractFrame archetype loop). Without
|
|
2119
|
-
// this, per-submesh materials (materials[i>=1], e.g. a glTF BLEND decal
|
|
2120
|
-
// submesh on a multi-material mesh) never carry the transparent flag, so
|
|
2121
|
-
// the record stage's LDR split + blend routing treats them as opaque and
|
|
2122
|
-
// their alpha=0 texels composite as black.
|
|
2123
|
-
transparent: allPasses[0]?.renderState?.blend !== void 0
|
|
2124
|
-
};
|
|
2125
|
-
const stored = materialSnapshotCache !== void 0 ? storeMaterialSnapshot(
|
|
2126
|
-
materialSnapshotCache,
|
|
2127
|
-
handleRaw,
|
|
2128
|
-
snapshot,
|
|
2129
|
-
allPasses,
|
|
2130
|
-
asset,
|
|
2131
|
-
assetsRef
|
|
2132
|
-
) : void 0;
|
|
2133
|
-
const cacheEntry = stored ?? (persistentMaterialSnapshotCache !== void 0 ? storeMaterialSnapshot(
|
|
2134
|
-
persistentMaterialSnapshotCache,
|
|
2135
|
-
handleRaw,
|
|
2136
|
-
snapshot,
|
|
2137
|
-
allPasses,
|
|
2138
|
-
asset,
|
|
2139
|
-
assetsRef
|
|
2140
|
-
) : void 0);
|
|
2141
|
-
if (cacheEntry?.crossFrameSafe === true) {
|
|
2142
|
-
persistentMaterialSnapshotCache?.set(handleRaw, cacheEntry);
|
|
2143
|
-
}
|
|
2144
|
-
return snapshot;
|
|
2145
|
-
}
|
|
2146
|
-
function computeFrustumCorners(vp, camNear, camFar, nearZ, farZ, projection) {
|
|
2147
|
-
const invVP = mat4.create();
|
|
2148
|
-
mat4.invert(invVP, vp);
|
|
2149
|
-
const corners = [];
|
|
2150
|
-
const span = camFar - camNear;
|
|
2151
|
-
const ndcNear = projection === "orthographic" ? (nearZ - camNear) / span : camFar * (nearZ - camNear) / (nearZ * span);
|
|
2152
|
-
const ndcFar = projection === "orthographic" ? (farZ - camNear) / span : camFar * (farZ - camNear) / (farZ * span);
|
|
2153
|
-
const signs = [-1, 1];
|
|
2154
|
-
for (const sx of signs) {
|
|
2155
|
-
for (const sy of signs) {
|
|
2156
|
-
corners.push(unprojectNDC(invVP, sx, sy, ndcNear));
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
for (const sx of signs) {
|
|
2160
|
-
for (const sy of signs) {
|
|
2161
|
-
corners.push(unprojectNDC(invVP, sx, sy, ndcFar));
|
|
2009
|
+
const spotSnapshots = [];
|
|
2010
|
+
const spotLightQuery = world.query({
|
|
2011
|
+
read: [SpotLight],
|
|
2012
|
+
optional: [Transform, GlobalTransform]
|
|
2013
|
+
}).unwrap();
|
|
2014
|
+
let spotTileNext = 0;
|
|
2015
|
+
const iesSlices = /* @__PURE__ */ new Map();
|
|
2016
|
+
const cookieSlices = /* @__PURE__ */ new Map();
|
|
2017
|
+
const projectorSlices = /* @__PURE__ */ new Map();
|
|
2018
|
+
for (const row of spotLightQuery) {
|
|
2019
|
+
const s = row.get(SpotLight);
|
|
2020
|
+
const hasTransform = row.get(GlobalTransform) !== void 0;
|
|
2021
|
+
const intensity = s.intensity;
|
|
2022
|
+
const range = s.range;
|
|
2023
|
+
const innerConeDeg = s.innerConeDeg;
|
|
2024
|
+
const outerConeDeg = s.outerConeDeg;
|
|
2025
|
+
let worldMat;
|
|
2026
|
+
if (hasTransform) {
|
|
2027
|
+
const entity = row.entity;
|
|
2028
|
+
const view = worldInternal._getArrayView(entity, GlobalTransform, "world");
|
|
2029
|
+
if (view !== void 0) worldMat = new Float32Array(view);
|
|
2162
2030
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
const ndc = vec3.create(ndcX, ndcY, ndcZ);
|
|
2168
|
-
const ws = vec3.create();
|
|
2169
|
-
mat4.unproject(ws, ndc, invVP);
|
|
2170
|
-
return ws;
|
|
2171
|
-
}
|
|
2172
|
-
function pssmSplit(nearPlane, farPlane, cascadeCount, splitLambda) {
|
|
2173
|
-
const EPS = 1e-6;
|
|
2174
|
-
if (farPlane <= nearPlane + EPS) {
|
|
2175
|
-
throw new ShadowInvalidConfigError("shadowDistance", farPlane, nearPlane + EPS);
|
|
2176
|
-
}
|
|
2177
|
-
const result = new Float32Array(cascadeCount);
|
|
2178
|
-
const m = cascadeCount;
|
|
2179
|
-
const n = nearPlane;
|
|
2180
|
-
const f = farPlane;
|
|
2181
|
-
const ratio = f / n;
|
|
2182
|
-
for (let i = 1; i <= m; i++) {
|
|
2183
|
-
const t = i / m;
|
|
2184
|
-
const logPart = n * ratio ** t;
|
|
2185
|
-
const uniformPart = n + t * (f - n);
|
|
2186
|
-
result[i - 1] = splitLambda * logPart + (1 - splitLambda) * uniformPart;
|
|
2187
|
-
}
|
|
2188
|
-
return result;
|
|
2189
|
-
}
|
|
2190
|
-
var POINT_SHADOW_FACE_LOOK = [
|
|
2191
|
-
vec3.create(1, 0, 0),
|
|
2192
|
-
vec3.create(-1, 0, 0),
|
|
2193
|
-
vec3.create(0, 1, 0),
|
|
2194
|
-
vec3.create(0, -1, 0),
|
|
2195
|
-
vec3.create(0, 0, 1),
|
|
2196
|
-
vec3.create(0, 0, -1)
|
|
2197
|
-
];
|
|
2198
|
-
var POINT_SHADOW_FACE_UP = [
|
|
2199
|
-
vec3.create(0, -1, 0),
|
|
2200
|
-
vec3.create(0, -1, 0),
|
|
2201
|
-
vec3.create(0, 0, 1),
|
|
2202
|
-
vec3.create(0, 0, -1),
|
|
2203
|
-
vec3.create(0, -1, 0),
|
|
2204
|
-
vec3.create(0, -1, 0)
|
|
2205
|
-
];
|
|
2206
|
-
function buildPointShadowMatrices(lightPos, near, far) {
|
|
2207
|
-
const fovY = Math.PI / 2;
|
|
2208
|
-
const aspect = 1;
|
|
2209
|
-
const proj = mat4.create();
|
|
2210
|
-
mat4.perspective(proj, fovY, aspect, near, far);
|
|
2211
|
-
const out = [];
|
|
2212
|
-
for (let i = 0; i < 6; i++) {
|
|
2213
|
-
const look = POINT_SHADOW_FACE_LOOK[i];
|
|
2214
|
-
const up = POINT_SHADOW_FACE_UP[i];
|
|
2215
|
-
const target = vec3.create(
|
|
2216
|
-
(lightPos[0] ?? 0) + (look[0] ?? 0),
|
|
2217
|
-
(lightPos[1] ?? 0) + (look[1] ?? 0),
|
|
2218
|
-
(lightPos[2] ?? 0) + (look[2] ?? 0)
|
|
2219
|
-
);
|
|
2220
|
-
const view = mat4.create();
|
|
2221
|
-
mat4.lookAt(view, lightPos, target, up);
|
|
2222
|
-
const vp = mat4.create();
|
|
2223
|
-
mat4.multiply(vp, proj, view);
|
|
2224
|
-
out.push(vp);
|
|
2225
|
-
}
|
|
2226
|
-
return out;
|
|
2227
|
-
}
|
|
2228
|
-
function computeDirectionalCsm(direction, config, cameraData) {
|
|
2229
|
-
const cascadeCount = Math.round(config.cascadeCount);
|
|
2230
|
-
const sNear = cameraData?.near ?? 0.1;
|
|
2231
|
-
const sFar = config.shadowDistance;
|
|
2232
|
-
const splits = pssmSplit(sNear, sFar, cascadeCount, config.splitLambda);
|
|
2233
|
-
const lightDirN = vec3.normalize(vec3.create(), direction);
|
|
2234
|
-
const lightTarget = vec3.create(lightDirN[0] ?? 0, lightDirN[1] ?? 0, lightDirN[2] ?? 0);
|
|
2235
|
-
const lightView = mat4.create();
|
|
2236
|
-
mat4.lookAt(lightView, vec3.create(0, 0, 0), lightTarget, vec3.create(0, 1, 0));
|
|
2237
|
-
if (cameraData === void 0) return null;
|
|
2238
|
-
const camProj = mat4.create();
|
|
2239
|
-
if (cameraData.projection === "orthographic") {
|
|
2240
|
-
mat4.orthographic(
|
|
2241
|
-
camProj,
|
|
2242
|
-
cameraData.orthoLeft,
|
|
2243
|
-
cameraData.orthoRight,
|
|
2244
|
-
cameraData.orthoBottom,
|
|
2245
|
-
cameraData.orthoTop,
|
|
2246
|
-
cameraData.near,
|
|
2247
|
-
cameraData.far
|
|
2031
|
+
const position = worldMat !== void 0 ? mat4.getTranslation(vec3.create(), worldMat) : vec3.create(0, 0, 0);
|
|
2032
|
+
const dir = vec3.create(s.direction[0] ?? 0, s.direction[1] ?? -1, s.direction[2] ?? 0);
|
|
2033
|
+
const dirLen = Math.sqrt(
|
|
2034
|
+
(dir[0] ?? 0) * (dir[0] ?? 0) + (dir[1] ?? 0) * (dir[1] ?? 0) + (dir[2] ?? 0) * (dir[2] ?? 0)
|
|
2248
2035
|
);
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
sNear,
|
|
2264
|
-
sFar,
|
|
2265
|
-
cameraData.projection
|
|
2266
|
-
);
|
|
2267
|
-
for (const ws of fullCorners) {
|
|
2268
|
-
const ls = vec3.create();
|
|
2269
|
-
mat4.transformVec3(ls, lightView, ws);
|
|
2270
|
-
if ((ls[2] ?? 0) > lightSpaceMaxZFull) lightSpaceMaxZFull = ls[2] ?? 0;
|
|
2271
|
-
}
|
|
2272
|
-
for (let cIdx = 0; cIdx < 4; cIdx++) {
|
|
2273
|
-
if (cIdx >= cascadeCount) {
|
|
2274
|
-
resultLightViewProjs.push(new Float32Array(16));
|
|
2275
|
-
continue;
|
|
2036
|
+
const EPSILON = 1e-6;
|
|
2037
|
+
const hasValidDirection = dirLen > EPSILON;
|
|
2038
|
+
if (!hasValidDirection) {
|
|
2039
|
+
worldInternal._routeError(
|
|
2040
|
+
new SpawnLightInvalidBoundsError("SpotLight", "direction", [
|
|
2041
|
+
dir[0] ?? 0,
|
|
2042
|
+
dir[1] ?? 0,
|
|
2043
|
+
dir[2] ?? 0
|
|
2044
|
+
]),
|
|
2045
|
+
{
|
|
2046
|
+
severity: Severity.Error,
|
|
2047
|
+
systemName: "RenderSystem.extract (spot-direction)"
|
|
2048
|
+
}
|
|
2049
|
+
);
|
|
2276
2050
|
}
|
|
2277
|
-
const
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
);
|
|
2287
|
-
const
|
|
2288
|
-
|
|
2289
|
-
let
|
|
2290
|
-
let
|
|
2291
|
-
let
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2051
|
+
const dirN = vec3.create(
|
|
2052
|
+
hasValidDirection ? (dir[0] ?? 0) / dirLen : dir[0] ?? 0,
|
|
2053
|
+
hasValidDirection ? (dir[1] ?? 0) / dirLen : dir[1] ?? 0,
|
|
2054
|
+
hasValidDirection ? (dir[2] ?? 0) / dirLen : dir[2] ?? 0
|
|
2055
|
+
);
|
|
2056
|
+
const castShadow = s.castShadow;
|
|
2057
|
+
const sMapSize = s.mapSize;
|
|
2058
|
+
const sNearPlane = s.nearPlane;
|
|
2059
|
+
const sFarPlane = s.farPlane;
|
|
2060
|
+
const iesProfileAsset = s.iesProfile === void 0 ? void 0 : resolveAssetHandle(world, s.iesProfile);
|
|
2061
|
+
const cookieAsset = s.cookie === void 0 ? void 0 : resolveAssetHandle(world, s.cookie);
|
|
2062
|
+
const hasProjector = Number(s.projector) > 0;
|
|
2063
|
+
let projectorHandle;
|
|
2064
|
+
let projectorAsset;
|
|
2065
|
+
let projectorGuid;
|
|
2066
|
+
if (hasProjector) {
|
|
2067
|
+
const candidate = toShared(Math.round(Number(s.projector)));
|
|
2068
|
+
const resolvedProjector = resolveAssetHandle(world, candidate);
|
|
2069
|
+
if (!resolvedProjector.ok || resolvedProjector.value.kind !== "texture") {
|
|
2070
|
+
worldInternal._routeError(
|
|
2071
|
+
resolvedProjector.ok ? new RhiError({
|
|
2072
|
+
code: "asset-not-registered",
|
|
2073
|
+
expected: "SpotLight.projector resolves to a TextureAsset",
|
|
2074
|
+
hint: "load the authored projector TextureAsset before assigning SpotLight.projector",
|
|
2075
|
+
detail: { assetHandle: Number(candidate) }
|
|
2076
|
+
}) : resolvedProjector.error,
|
|
2077
|
+
{ severity: Severity.Error, systemName: "RenderSystem.extract (spot-projector)" }
|
|
2078
|
+
);
|
|
2079
|
+
} else {
|
|
2080
|
+
projectorHandle = candidate;
|
|
2081
|
+
projectorAsset = resolvedProjector.value;
|
|
2082
|
+
projectorGuid = assets?.guidOf(projectorAsset) ?? `handle:${Number(candidate)}`;
|
|
2083
|
+
}
|
|
2303
2084
|
}
|
|
2304
|
-
const
|
|
2305
|
-
const
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2085
|
+
const iesProfileData = iesProfileAsset?.ok && iesProfileAsset.value.kind === "ies-profile" ? new Uint8Array(iesProfileAsset.value.data) : void 0;
|
|
2086
|
+
const cookieProjection = cookieAsset?.ok && cookieAsset.value.kind === "texture" ? prepareCookieProjection(cookieAsset.value) : void 0;
|
|
2087
|
+
const cookieData = cookieProjection?.data;
|
|
2088
|
+
const projectorProjection = projectorAsset === void 0 ? void 0 : prepareCookieProjection(projectorAsset);
|
|
2089
|
+
const projectorData = projectorProjection?.data;
|
|
2090
|
+
const iesProfileHandle = s.iesProfile === void 0 ? void 0 : handleSlot(s.iesProfile);
|
|
2091
|
+
const cookieHandle = s.cookie === void 0 ? void 0 : handleSlot(s.cookie);
|
|
2092
|
+
let iesProfileSlice = iesProfileHandle === void 0 ? void 0 : iesSlices.get(iesProfileHandle);
|
|
2093
|
+
if (iesProfileSlice === void 0 && iesProfileHandle !== void 0 && iesProfileData !== void 0 && iesSlices.size < IES_SLICE_CAPACITY) {
|
|
2094
|
+
iesProfileSlice = iesSlices.size;
|
|
2095
|
+
iesSlices.set(iesProfileHandle, iesProfileSlice);
|
|
2096
|
+
}
|
|
2097
|
+
let cookieSlice = cookieHandle === void 0 ? void 0 : cookieSlices.get(cookieHandle);
|
|
2098
|
+
if (cookieSlice === void 0 && cookieHandle !== void 0 && cookieData !== void 0 && cookieSlices.size < COOKIE_SLICE_CAPACITY) {
|
|
2099
|
+
cookieSlice = cookieSlices.size;
|
|
2100
|
+
cookieSlices.set(cookieHandle, cookieSlice);
|
|
2101
|
+
}
|
|
2102
|
+
let projectorSlice = projectorHandle === void 0 ? void 0 : projectorSlices.get(projectorHandle) ?? cookieSlices.get(projectorHandle);
|
|
2103
|
+
if (projectorSlice === void 0 && projectorHandle !== void 0 && projectorData !== void 0 && cookieSlices.size + projectorSlices.size < COOKIE_SLICE_CAPACITY) {
|
|
2104
|
+
projectorSlice = cookieSlices.size + projectorSlices.size;
|
|
2105
|
+
projectorSlices.set(projectorHandle, projectorSlice);
|
|
2106
|
+
}
|
|
2107
|
+
const shadowIntensity = s.shadowIntensity;
|
|
2108
|
+
let lightViewProj2;
|
|
2109
|
+
let shadowAtlasTile = -1;
|
|
2110
|
+
if ((castShadow || hasProjector) && hasValidDirection) {
|
|
2111
|
+
const target = vec3.create(
|
|
2112
|
+
(position[0] ?? 0) + (dirN[0] ?? 0),
|
|
2113
|
+
(position[1] ?? 0) + (dirN[1] ?? 0),
|
|
2114
|
+
(position[2] ?? 0) + (dirN[2] ?? 0)
|
|
2115
|
+
);
|
|
2116
|
+
const fov = outerConeDeg * 2 * (Math.PI / 180);
|
|
2117
|
+
const proj = mat4.create();
|
|
2118
|
+
mat4.perspective(proj, fov, 1, sNearPlane, sFarPlane);
|
|
2119
|
+
const view = mat4.create();
|
|
2120
|
+
mat4.lookAt(view, position, target, vec3.create(0, 1, 0));
|
|
2121
|
+
lightViewProj2 = new Float32Array(16);
|
|
2122
|
+
mat4.multiply(lightViewProj2, proj, view);
|
|
2123
|
+
if (castShadow && spotTileNext < 4) {
|
|
2124
|
+
shadowAtlasTile = spotTileNext;
|
|
2125
|
+
spotTileNext += 1;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
spotSnapshots.push({
|
|
2129
|
+
kind: "spot",
|
|
2130
|
+
entity: row.entity,
|
|
2131
|
+
// D-6: position reflects world transform; direction stays sourced
|
|
2132
|
+
// from SpotLight.direction (NOT rotated by the parent).
|
|
2133
|
+
position,
|
|
2134
|
+
direction: dirN,
|
|
2135
|
+
color: vec3.create(
|
|
2136
|
+
(s.color[0] ?? 1) * intensity,
|
|
2137
|
+
(s.color[1] ?? 1) * intensity,
|
|
2138
|
+
(s.color[2] ?? 1) * intensity
|
|
2139
|
+
),
|
|
2140
|
+
intensity,
|
|
2141
|
+
invRangeSquared: computeInvRangeSquared(range),
|
|
2142
|
+
cosInner: degToCos(innerConeDeg),
|
|
2143
|
+
cosOuter: degToCos(outerConeDeg),
|
|
2144
|
+
...s.iesProfile === void 0 ? {} : {
|
|
2145
|
+
iesProfileHandle: handleSlot(s.iesProfile),
|
|
2146
|
+
...iesProfileSlice === void 0 ? {} : { iesProfileSlice }
|
|
2147
|
+
},
|
|
2148
|
+
...s.cookie === void 0 ? {} : {
|
|
2149
|
+
cookieHandle: handleSlot(s.cookie),
|
|
2150
|
+
...cookieSlice === void 0 ? {} : { cookieSlice }
|
|
2151
|
+
},
|
|
2152
|
+
...iesProfileData === void 0 ? {} : { iesProfileData },
|
|
2153
|
+
...cookieData === void 0 ? {} : { cookieData },
|
|
2154
|
+
...cookieProjection === void 0 ? {} : { cookieMatrix: cookieProjection.matrix },
|
|
2155
|
+
...projectorSlice === void 0 ? {} : { projectorSlice },
|
|
2156
|
+
...projectorData === void 0 ? {} : { projectorData },
|
|
2157
|
+
...projectorProjection === void 0 ? {} : { projectorMatrix: projectorProjection.matrix },
|
|
2158
|
+
rollDeg: s.rollDeg,
|
|
2159
|
+
// ── shadow fields ──
|
|
2160
|
+
castShadow,
|
|
2161
|
+
lightViewProj: lightViewProj2,
|
|
2162
|
+
mapSize: sMapSize,
|
|
2163
|
+
nearPlane: sNearPlane,
|
|
2164
|
+
farPlane: sFarPlane,
|
|
2165
|
+
shadowAtlasTile,
|
|
2166
|
+
shadowIntensity,
|
|
2167
|
+
depthBias: s.depthBias,
|
|
2168
|
+
normalBias: s.normalBias,
|
|
2169
|
+
pcfKernelSize: s.pcfKernelSize,
|
|
2170
|
+
...projectorHandle === void 0 || projectorAsset === void 0 || projectorGuid === void 0 ? {} : {
|
|
2171
|
+
projectorHandle,
|
|
2172
|
+
projectorAsset,
|
|
2173
|
+
projectorGuid,
|
|
2174
|
+
projectorGeneration: 1,
|
|
2175
|
+
projectorRevision: 1
|
|
2389
2176
|
}
|
|
2390
2177
|
});
|
|
2391
2178
|
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
const
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
requestVersion: camera.requestVersion,
|
|
2412
|
-
faceBudget: camera.faceBudget
|
|
2413
|
-
});
|
|
2414
|
-
}
|
|
2415
|
-
return snapshots;
|
|
2416
|
-
}
|
|
2417
|
-
function collectReflectionProbeFacts(world) {
|
|
2418
|
-
const worldInternal = createWorldInternalView(world);
|
|
2419
|
-
const facts = [];
|
|
2420
|
-
const query = world.query({ read: [ReflectionProbe], with: [Transform, GlobalTransform] }).unwrap();
|
|
2421
|
-
for (const row of query) {
|
|
2422
|
-
const probe = row.get(ReflectionProbe);
|
|
2423
|
-
const view = worldInternal._getArrayView(row.entity, GlobalTransform, "world");
|
|
2424
|
-
if (view === void 0) {
|
|
2179
|
+
const rectSnapshots = [];
|
|
2180
|
+
const rectLightQuery = world.query({
|
|
2181
|
+
read: [RectAreaLight],
|
|
2182
|
+
optional: [Transform, GlobalTransform]
|
|
2183
|
+
}).unwrap();
|
|
2184
|
+
for (const row of rectLightQuery) {
|
|
2185
|
+
const light = row.get(RectAreaLight);
|
|
2186
|
+
const validation = validateRectAreaLightData({
|
|
2187
|
+
intensity: light.intensity,
|
|
2188
|
+
color: light.color,
|
|
2189
|
+
width: light.width,
|
|
2190
|
+
height: light.height,
|
|
2191
|
+
range: light.range
|
|
2192
|
+
});
|
|
2193
|
+
if (!validation.ok) {
|
|
2194
|
+
worldInternal._routeError(validation.error, {
|
|
2195
|
+
severity: Severity.Error,
|
|
2196
|
+
systemName: "RenderSystem.extract (rect-area-light)"
|
|
2197
|
+
});
|
|
2425
2198
|
continue;
|
|
2426
2199
|
}
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
priority: probe.priority,
|
|
2437
|
-
intensity: probe.intensity,
|
|
2438
|
-
resolution: probe.resolution,
|
|
2439
|
-
revision: probe.invalidationVersion,
|
|
2440
|
-
updateIntent: reflectionProbeUpdateIntentFromF32(probe.updateIntent),
|
|
2441
|
-
invalidationVersion: probe.invalidationVersion
|
|
2200
|
+
const worldView = row.get(GlobalTransform);
|
|
2201
|
+
const worldMat = worldView === void 0 ? void 0 : new Float32Array(worldInternal._getArrayView(row.entity, GlobalTransform, "world") ?? []);
|
|
2202
|
+
const position = worldMat !== void 0 ? mat4.getTranslation(vec3.create(), worldMat) : vec3.create(0, 0, 0);
|
|
2203
|
+
const frame = buildRectAreaWorldFrame({
|
|
2204
|
+
center: position,
|
|
2205
|
+
axisX: [worldMat?.[0] ?? 1, worldMat?.[1] ?? 0, worldMat?.[2] ?? 0],
|
|
2206
|
+
axisY: [worldMat?.[4] ?? 0, worldMat?.[5] ?? 1, worldMat?.[6] ?? 0],
|
|
2207
|
+
width: light.width,
|
|
2208
|
+
height: light.height
|
|
2442
2209
|
});
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
entityKey: camera.entityKey ?? 0,
|
|
2458
|
-
...camera.target === void 0 ? {} : { target: camera.target },
|
|
2459
|
-
requestVersion: 0,
|
|
2460
|
-
update: "continuous"
|
|
2461
|
-
}));
|
|
2462
|
-
const selected = selectCameraTargetViews(candidates, {
|
|
2463
|
-
...displayEntityKey === void 0 ? {} : { displayEntityKey },
|
|
2464
|
-
budget: 1
|
|
2465
|
-
});
|
|
2466
|
-
const auxiliary = selected.auxiliary.flatMap(
|
|
2467
|
-
(candidate) => cameras.filter((camera) => camera.entityKey === candidate.entityKey)
|
|
2468
|
-
);
|
|
2469
|
-
return { display, auxiliary };
|
|
2470
|
-
}
|
|
2471
|
-
function tonemapParams(camera) {
|
|
2472
|
-
const bytes = new ArrayBuffer(16);
|
|
2473
|
-
const floats = new Float32Array(bytes);
|
|
2474
|
-
const integers = new Uint32Array(bytes);
|
|
2475
|
-
floats[0] = camera.exposure;
|
|
2476
|
-
floats[1] = camera.whitePoint;
|
|
2477
|
-
integers[2] = tonemapToU32(camera.tonemap);
|
|
2478
|
-
return new Uint8Array(bytes);
|
|
2479
|
-
}
|
|
2480
|
-
function prepareExtractContext(world, options = {}) {
|
|
2481
|
-
const renderables = options.renderables ?? "full";
|
|
2482
|
-
return {
|
|
2483
|
-
assets: options.assets,
|
|
2484
|
-
pipelineState: options.pipelineState,
|
|
2485
|
-
materialSnapshotCache: options.materialSnapshotCache,
|
|
2486
|
-
resourceOwnerFog: options.resourceOwnerFog,
|
|
2487
|
-
cull: options.cull ?? "self",
|
|
2488
|
-
cullCameras: options.cullCameras,
|
|
2489
|
-
renderables,
|
|
2490
|
-
visibility: renderables === "none" ? ALL_VISIBLE : resolveVisibility(world),
|
|
2491
|
-
getMaterialShaderArtifact: options.getMaterialShaderArtifact
|
|
2492
|
-
};
|
|
2493
|
-
}
|
|
2494
|
-
var fogQueries = /* @__PURE__ */ new WeakMap();
|
|
2495
|
-
var fogLkgStates = /* @__PURE__ */ new WeakMap();
|
|
2496
|
-
function fogState(world) {
|
|
2497
|
-
const existing = fogLkgStates.get(world);
|
|
2498
|
-
if (existing !== void 0) return existing;
|
|
2499
|
-
const created = { lkg: void 0, failure: void 0 };
|
|
2500
|
-
fogLkgStates.set(world, created);
|
|
2501
|
-
return created;
|
|
2502
|
-
}
|
|
2503
|
-
function selectFogFrame(world) {
|
|
2504
|
-
const fogCandidates = [];
|
|
2505
|
-
let fogQuery = fogQueries.get(world);
|
|
2506
|
-
if (fogQuery === void 0) {
|
|
2507
|
-
fogQuery = world.query({ read: [Fog] }).unwrap();
|
|
2508
|
-
fogQueries.set(world, fogQuery);
|
|
2509
|
-
}
|
|
2510
|
-
for (const row of fogQuery) {
|
|
2511
|
-
const value = row.get(Fog);
|
|
2512
|
-
fogCandidates.push({
|
|
2513
|
-
entityKey: row.entity,
|
|
2514
|
-
color: [value.color[0] ?? 0, value.color[1] ?? 0, value.color[2] ?? 0],
|
|
2515
|
-
density: value.density,
|
|
2516
|
-
heightFalloff: value.heightFalloff,
|
|
2517
|
-
maxOpacity: value.maxOpacity
|
|
2210
|
+
rectSnapshots.push({
|
|
2211
|
+
kind: "rect-area",
|
|
2212
|
+
position,
|
|
2213
|
+
color: vec3.create(
|
|
2214
|
+
(light.color[0] ?? 1) * light.intensity,
|
|
2215
|
+
(light.color[1] ?? 1) * light.intensity,
|
|
2216
|
+
(light.color[2] ?? 1) * light.intensity
|
|
2217
|
+
),
|
|
2218
|
+
intensity: light.intensity,
|
|
2219
|
+
invRangeSquared: computeInvRangeSquared(light.range),
|
|
2220
|
+
halfWidth: frame.halfWidth,
|
|
2221
|
+
halfHeight: frame.halfHeight,
|
|
2222
|
+
axisX: frame.axisX,
|
|
2223
|
+
axisY: frame.axisY
|
|
2518
2224
|
});
|
|
2519
2225
|
}
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
if (fogSelection.ok) {
|
|
2528
|
-
state.lkg = fogSelection.value.fog;
|
|
2529
|
-
state.failure = void 0;
|
|
2530
|
-
return fogSelection.value.fog;
|
|
2531
|
-
}
|
|
2532
|
-
state.failure = {
|
|
2533
|
-
code: fogSelection.error.code,
|
|
2534
|
-
expected: fogSelection.error.expected,
|
|
2535
|
-
hint: fogSelection.error.hint,
|
|
2536
|
-
detail: Object.freeze({ ...fogSelection.error.detail })
|
|
2537
|
-
};
|
|
2538
|
-
routeWorldError(world, fogSelection.error, {
|
|
2539
|
-
systemName: "RenderSystem.extract (fog-selection)"
|
|
2540
|
-
});
|
|
2541
|
-
if (state.lkg !== void 0) return state.lkg;
|
|
2542
|
-
throw fogSelection.error;
|
|
2543
|
-
}
|
|
2544
|
-
function textureDigest(texture) {
|
|
2545
|
-
let hash = 2166136261;
|
|
2546
|
-
for (const byte of texture.data) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
|
|
2547
|
-
return `fnv1a:${hash.toString(16).padStart(8, "0")}`;
|
|
2548
|
-
}
|
|
2549
|
-
function extractVolumeSnapshot(world, assets, worldInternal) {
|
|
2550
|
-
const query = world.query({ read: [VolumetricFog] }).unwrap();
|
|
2551
|
-
const authorings = [];
|
|
2552
|
-
let selectedLight;
|
|
2553
|
-
let first;
|
|
2554
|
-
for (const row of query) {
|
|
2555
|
-
const source = row.get(VolumetricFog);
|
|
2556
|
-
if (source.light === null) continue;
|
|
2557
|
-
const selected = resolveSelectedVolumetricLight(world, source.light);
|
|
2558
|
-
if (selected.status === "available") {
|
|
2559
|
-
const pairSpot = source.spotLight === null ? void 0 : source.spotLight;
|
|
2560
|
-
selectedLight ??= {
|
|
2561
|
-
entity: selected.entity,
|
|
2562
|
-
kind: selected.kind,
|
|
2563
|
-
...selected.kind === "point" ? { pointLightEntity: selected.entity } : {},
|
|
2564
|
-
...pairSpot === void 0 ? {} : { spotLightEntity: pairSpot }
|
|
2565
|
-
};
|
|
2566
|
-
}
|
|
2567
|
-
const densityHandle = toShared(Math.round(Number(source.density)));
|
|
2568
|
-
const resolved = resolveAssetHandle(world, densityHandle);
|
|
2569
|
-
if (!resolved.ok || resolved.value.kind !== "texture") {
|
|
2570
|
-
worldInternal._routeError(
|
|
2571
|
-
resolved.ok ? new RhiError({
|
|
2572
|
-
code: "asset-not-registered",
|
|
2573
|
-
expected: "VolumetricFog.density resolves to a TextureAsset",
|
|
2574
|
-
hint: "load a TextureAsset before assigning it to VolumetricFog.density",
|
|
2575
|
-
detail: { assetHandle: Number(densityHandle) }
|
|
2576
|
-
}) : resolved.error,
|
|
2577
|
-
{ severity: Severity.Error, systemName: "RenderSystem.extract (volumetric-density)" }
|
|
2578
|
-
);
|
|
2579
|
-
return { status: "degraded" };
|
|
2226
|
+
let volumeSpot;
|
|
2227
|
+
const extractedFog = volumetricFog;
|
|
2228
|
+
if (extractedFog !== void 0) {
|
|
2229
|
+
if (extractedFog.spotLightEntity !== void 0) {
|
|
2230
|
+
volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.spotLightEntity);
|
|
2231
|
+
} else if (extractedFog.lightKind === "spot") {
|
|
2232
|
+
volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.lightEntity);
|
|
2580
2233
|
}
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
const
|
|
2584
|
-
const
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
},
|
|
2595
|
-
format: densityAsset.format,
|
|
2596
|
-
colorSpace: densityAsset.colorSpace
|
|
2597
|
-
} : {
|
|
2598
|
-
guid,
|
|
2599
|
-
generation: 1,
|
|
2600
|
-
shape: {
|
|
2601
|
-
viewDimension: shape.viewDimension,
|
|
2602
|
-
extent: shape.viewDimension === "2d-array" ? {
|
|
2603
|
-
width: shape.extent.width,
|
|
2604
|
-
height: shape.extent.height,
|
|
2605
|
-
layers: shape.extent.layers
|
|
2606
|
-
} : { width: shape.extent.width, height: shape.extent.height }
|
|
2607
|
-
},
|
|
2608
|
-
format: densityAsset.format,
|
|
2609
|
-
colorSpace: densityAsset.colorSpace
|
|
2610
|
-
};
|
|
2611
|
-
const authoring = {
|
|
2612
|
-
light: source.light,
|
|
2613
|
-
density,
|
|
2614
|
-
bounds: {
|
|
2615
|
-
min: [source.boundsMin[0] ?? 0, source.boundsMin[1] ?? 0, source.boundsMin[2] ?? 0],
|
|
2616
|
-
max: [source.boundsMax[0] ?? 0, source.boundsMax[1] ?? 0, source.boundsMax[2] ?? 0]
|
|
2234
|
+
}
|
|
2235
|
+
if (volumetricFog !== void 0 && volumetricFog.status === "available" && volumeSpot?.projectorAsset !== void 0 && volumeSpot.projectorHandle !== void 0) {
|
|
2236
|
+
const projectorHandle = volumeSpot.projectorHandle;
|
|
2237
|
+
const projectorAsset = volumeSpot.projectorAsset;
|
|
2238
|
+
volumetricFog = {
|
|
2239
|
+
...volumetricFog,
|
|
2240
|
+
projector: {
|
|
2241
|
+
guid: volumeSpot.projectorGuid ?? `handle:${Number(volumeSpot.projectorHandle)}`,
|
|
2242
|
+
generation: volumeSpot.projectorGeneration ?? 1,
|
|
2243
|
+
view: "2d",
|
|
2244
|
+
sampler: "linear-clamp-to-edge",
|
|
2245
|
+
projection: "spot-projection",
|
|
2246
|
+
revision: volumeSpot.projectorRevision ?? 1
|
|
2617
2247
|
},
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
emission: [source.emission[0] ?? 0, source.emission[1] ?? 0, source.emission[2] ?? 0],
|
|
2621
|
-
anisotropy: source.anisotropy,
|
|
2622
|
-
maxDistance: source.maxDistance
|
|
2248
|
+
projectorHandle,
|
|
2249
|
+
projectorAsset
|
|
2623
2250
|
};
|
|
2624
|
-
authorings.push(authoring);
|
|
2625
|
-
first ??= { densityHandle, densityAsset, guid };
|
|
2626
2251
|
}
|
|
2627
|
-
if (authorings.length === 0) return void 0;
|
|
2628
|
-
const extracted = extractVolumetricFog(authorings);
|
|
2629
|
-
if (!extracted.ok) {
|
|
2630
|
-
worldInternal._routeError(extracted.error, {
|
|
2631
|
-
severity: Severity.Error,
|
|
2632
|
-
systemName: "RenderSystem.extract (volumetric-fog)"
|
|
2633
|
-
});
|
|
2634
|
-
return {
|
|
2635
|
-
status: "degraded",
|
|
2636
|
-
...first === void 0 ? {} : {
|
|
2637
|
-
densityHandle: first.densityHandle,
|
|
2638
|
-
densityAsset: first.densityAsset,
|
|
2639
|
-
guid: first.guid,
|
|
2640
|
-
generation: 1,
|
|
2641
|
-
digest: textureDigest(first.densityAsset),
|
|
2642
|
-
...selectedLight === void 0 ? {} : {
|
|
2643
|
-
lightEntity: selectedLight.entity,
|
|
2644
|
-
lightKind: selectedLight.kind,
|
|
2645
|
-
...selectedLight.pointLightEntity === void 0 ? {} : { pointLightEntity: selectedLight.pointLightEntity },
|
|
2646
|
-
...selectedLight.spotLightEntity === void 0 ? {} : { spotLightEntity: selectedLight.spotLightEntity }
|
|
2647
|
-
}
|
|
2648
|
-
}
|
|
2649
|
-
};
|
|
2650
|
-
}
|
|
2651
|
-
if (extracted.value.status === "off" || first === void 0) return { status: "off" };
|
|
2652
|
-
const selectedLightFields = selectedLight === void 0 ? {} : {
|
|
2653
|
-
lightEntity: selectedLight.entity,
|
|
2654
|
-
lightKind: selectedLight.kind,
|
|
2655
|
-
...selectedLight.pointLightEntity === void 0 ? {} : { pointLightEntity: selectedLight.pointLightEntity },
|
|
2656
|
-
...selectedLight.spotLightEntity === void 0 ? {} : { spotLightEntity: selectedLight.spotLightEntity }
|
|
2657
|
-
};
|
|
2658
|
-
return {
|
|
2659
|
-
status: "available",
|
|
2660
|
-
fog: extracted.value.fog,
|
|
2661
|
-
densityHandle: first.densityHandle,
|
|
2662
|
-
densityAsset: first.densityAsset,
|
|
2663
|
-
guid: first.guid,
|
|
2664
|
-
generation: 1,
|
|
2665
|
-
digest: textureDigest(first.densityAsset),
|
|
2666
|
-
...selectedLightFields
|
|
2667
|
-
};
|
|
2668
|
-
}
|
|
2669
|
-
function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCachesByWorld, options = {}) {
|
|
2670
|
-
const cameraOwner = typeof owner === "number" ? owner : owner.cameraOwner;
|
|
2671
|
-
const resourceOwner = typeof owner === "number" ? owner : owner.resourceOwner;
|
|
2672
|
-
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
2673
|
-
if (skinPaletteAllocator !== null) {
|
|
2674
|
-
skinPaletteAllocator.resetForFrame();
|
|
2675
|
-
}
|
|
2676
|
-
const failedWorlds = /* @__PURE__ */ new Set();
|
|
2677
|
-
const resourceOwnerWorld = worlds[resourceOwner];
|
|
2678
|
-
const resourceOwnerFog = resourceOwnerWorld === void 0 ? null : selectFogFrame(resourceOwnerWorld) ?? null;
|
|
2679
|
-
const succeededFrames = [];
|
|
2680
|
-
const succeededIndices = [];
|
|
2681
|
-
const extractionOrder = Array.from({ length: worlds.length }, (_, wi) => wi).sort((a, b) => {
|
|
2682
|
-
if (a === cameraOwner) return -1;
|
|
2683
|
-
if (b === cameraOwner) return 1;
|
|
2684
|
-
return a - b;
|
|
2685
|
-
});
|
|
2686
|
-
const framesByWorld = /* @__PURE__ */ new Map();
|
|
2687
|
-
for (const wi of extractionOrder) {
|
|
2688
|
-
const world = worlds[wi];
|
|
2689
|
-
if (world === void 0 || failedWorlds.has(world)) continue;
|
|
2690
|
-
try {
|
|
2691
|
-
const isCameraOwner = wi === cameraOwner;
|
|
2692
|
-
const cameraOwnerFrame2 = framesByWorld.get(cameraOwner);
|
|
2693
|
-
const prepared = prepareExtractContext(world, {
|
|
2694
|
-
...assets !== void 0 ? { assets } : {},
|
|
2695
|
-
...pipelineState !== void 0 ? { pipelineState } : {},
|
|
2696
|
-
resourceOwnerFog: wi === resourceOwner ? resourceOwnerFog : null,
|
|
2697
|
-
...materialSnapshotCachesByWorld === void 0 ? {} : {
|
|
2698
|
-
materialSnapshotCache: materialSnapshotCachesByWorld.get(world) ?? (() => {
|
|
2699
|
-
const cache = /* @__PURE__ */ new Map();
|
|
2700
|
-
materialSnapshotCachesByWorld.set(world, cache);
|
|
2701
|
-
return cache;
|
|
2702
|
-
})()
|
|
2703
|
-
},
|
|
2704
|
-
cull: options.cull === "none" ? "none" : isCameraOwner ? "self" : "external",
|
|
2705
|
-
...options.getMaterialShaderArtifact === void 0 ? {} : { getMaterialShaderArtifact: options.getMaterialShaderArtifact },
|
|
2706
|
-
...cameraOwnerFrame2 === void 0 ? {} : { cullCameras: cameraOwnerFrame2.cameras },
|
|
2707
|
-
renderables: options.renderables ?? "full"
|
|
2708
|
-
});
|
|
2709
|
-
const frame = extractFrame(world, prepared);
|
|
2710
|
-
framesByWorld.set(wi, frame);
|
|
2711
|
-
} catch (err6) {
|
|
2712
|
-
try {
|
|
2713
|
-
createWorldInternalView(world)._routeError(err6, {
|
|
2714
|
-
severity: Severity.Error,
|
|
2715
|
-
systemName: `RenderSystem.extractFrames(world[${wi}])`
|
|
2716
|
-
});
|
|
2717
|
-
} catch {
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
for (let wi = 0; wi < worlds.length; wi++) {
|
|
2722
|
-
const frame = framesByWorld.get(wi);
|
|
2723
|
-
if (frame === void 0) continue;
|
|
2724
|
-
succeededFrames.push(frame);
|
|
2725
|
-
succeededIndices.push(wi);
|
|
2726
|
-
}
|
|
2727
|
-
const renderables = [];
|
|
2728
|
-
const dispatchEntries = [];
|
|
2729
|
-
const visibilitySnapshots = [];
|
|
2730
|
-
const featureVisibilitySnapshots = [];
|
|
2731
|
-
const hiddenEntityReports = [];
|
|
2732
|
-
for (let fi = 0; fi < succeededFrames.length; fi++) {
|
|
2733
|
-
const f = succeededFrames[fi];
|
|
2734
|
-
const wId = succeededIndices[fi];
|
|
2735
|
-
if (f === void 0 || wId === void 0) continue;
|
|
2736
|
-
const base = renderables.length;
|
|
2737
|
-
const visibilitySnapshot = f.visibilitySnapshots[0];
|
|
2738
|
-
const world = worlds[wId];
|
|
2739
|
-
if (visibilitySnapshot !== void 0) {
|
|
2740
|
-
visibilitySnapshots.push(visibilitySnapshot);
|
|
2741
|
-
if (world !== void 0)
|
|
2742
|
-
featureVisibilitySnapshots.push({ world, snapshot: visibilitySnapshot });
|
|
2743
|
-
}
|
|
2744
|
-
hiddenEntityReports.push(...f.hiddenEntityReports);
|
|
2745
|
-
for (const r of f.renderables) {
|
|
2746
|
-
renderables.push({
|
|
2747
|
-
...r,
|
|
2748
|
-
worldId: wId,
|
|
2749
|
-
...r.pointsLines === void 0 ? {} : { pointsLines: { ...r.pointsLines, worldId: wId } }
|
|
2750
|
-
});
|
|
2751
|
-
}
|
|
2752
|
-
for (const d of f.dispatch) {
|
|
2753
|
-
dispatchEntries.push({ ...d, renderableIndex: (d.renderableIndex ?? 0) + base });
|
|
2754
|
-
}
|
|
2755
|
-
}
|
|
2756
|
-
dispatchEntries.sort((a, b) => (a.queue ?? 0) - (b.queue ?? 0));
|
|
2757
|
-
const point = [];
|
|
2758
|
-
const spot = [];
|
|
2759
|
-
const rect = [];
|
|
2760
|
-
let directional;
|
|
2761
|
-
let directionalCount = 0;
|
|
2762
2252
|
let lightViewProj;
|
|
2763
2253
|
let splitPlanes;
|
|
2764
2254
|
let cascadeCount;
|
|
2765
2255
|
let cascadeBlend;
|
|
2766
2256
|
let shadowMapSize;
|
|
2767
|
-
let depthBias;
|
|
2768
|
-
let normalBias;
|
|
2769
2257
|
let directionalShadowQuality;
|
|
2770
|
-
let directionalShadowError;
|
|
2771
|
-
const pointShadow = [];
|
|
2772
2258
|
let directionalCsmConfig;
|
|
2773
2259
|
let directionalCsmDirection;
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2260
|
+
const cam0 = cameras[0];
|
|
2261
|
+
const cameraData = cam0 !== void 0 ? {
|
|
2262
|
+
world: cam0.world,
|
|
2263
|
+
fov: cam0.fov,
|
|
2264
|
+
aspect: cam0.aspect,
|
|
2265
|
+
near: cam0.near,
|
|
2266
|
+
far: cam0.far,
|
|
2267
|
+
projection: cam0.projection,
|
|
2268
|
+
orthoLeft: cam0.orthoLeft,
|
|
2269
|
+
orthoRight: cam0.orthoRight,
|
|
2270
|
+
orthoBottom: cam0.orthoBottom,
|
|
2271
|
+
orthoTop: cam0.orthoTop
|
|
2272
|
+
} : void 0;
|
|
2273
|
+
if (directional !== void 0 && firstHitCastShadow !== false && directionalShadowError === void 0) {
|
|
2274
|
+
const dirSnapshot = directional;
|
|
2275
|
+
const sf = firstHitShadowFields;
|
|
2276
|
+
if (sf !== void 0) {
|
|
2277
|
+
directionalCsmConfig = {
|
|
2278
|
+
cascadeCount: sf.cascadeCount,
|
|
2279
|
+
splitLambda: sf.splitLambda,
|
|
2280
|
+
cascadeBlend: sf.cascadeBlend,
|
|
2281
|
+
mapSize: sf.mapSize,
|
|
2282
|
+
shadowDistance: sf.shadowDistance,
|
|
2283
|
+
shadowFilter: sf.shadowFilter,
|
|
2284
|
+
shadowAngularRadius: sf.shadowAngularRadius,
|
|
2285
|
+
maxPenumbraTexels: sf.maxPenumbraTexels
|
|
2286
|
+
};
|
|
2287
|
+
directionalCsmDirection = dirSnapshot.direction;
|
|
2288
|
+
const csm = computeDirectionalCsm(dirSnapshot.direction, directionalCsmConfig, cameraData);
|
|
2289
|
+
cascadeCount = Math.round(sf.cascadeCount);
|
|
2290
|
+
cascadeBlend = sf.cascadeBlend;
|
|
2291
|
+
shadowMapSize = sf.mapSize;
|
|
2292
|
+
if (csm !== null) {
|
|
2293
|
+
lightViewProj = csm.lightViewProj;
|
|
2294
|
+
splitPlanes = csm.splitPlanes;
|
|
2295
|
+
directionalShadowQuality = csm.directionalShadowQuality;
|
|
2296
|
+
} else {
|
|
2297
|
+
const sNear = cameraData?.near ?? 0.1;
|
|
2298
|
+
const splits = pssmSplit(sNear, sf.shadowDistance, cascadeCount, sf.splitLambda);
|
|
2299
|
+
const padded = new Float32Array(16);
|
|
2300
|
+
for (let i = 0; i < splits.length; i++) padded[i * 4] = splits[i] ?? 0;
|
|
2301
|
+
splitPlanes = padded;
|
|
2302
|
+
}
|
|
2303
|
+
directionalShadowQuality = directionalShadowQualityFromF32(
|
|
2304
|
+
sf.shadowFilter,
|
|
2305
|
+
sf.shadowAngularRadius,
|
|
2306
|
+
sf.maxPenumbraTexels
|
|
2307
|
+
);
|
|
2792
2308
|
}
|
|
2793
|
-
directionalCount += f.lights.directionalCount;
|
|
2794
|
-
}
|
|
2795
|
-
let cameraOwnerFrame;
|
|
2796
|
-
let resourceOwnerFrame;
|
|
2797
|
-
for (let fi = 0; fi < succeededFrames.length; fi++) {
|
|
2798
|
-
if (succeededIndices[fi] === cameraOwner) cameraOwnerFrame = succeededFrames[fi];
|
|
2799
|
-
if (succeededIndices[fi] === resourceOwner) resourceOwnerFrame = succeededFrames[fi];
|
|
2800
2309
|
}
|
|
2801
|
-
const
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
if (directionalCsmConfig !== void 0 && directionalCsmDirection !== void 0) {
|
|
2806
|
-
const mergeCameraData = mergeCam !== void 0 ? {
|
|
2807
|
-
world: mergeCam.world,
|
|
2808
|
-
fov: mergeCam.fov,
|
|
2809
|
-
aspect: mergeCam.aspect,
|
|
2810
|
-
near: mergeCam.near,
|
|
2811
|
-
far: mergeCam.far,
|
|
2812
|
-
projection: mergeCam.projection,
|
|
2813
|
-
orthoLeft: mergeCam.orthoLeft,
|
|
2814
|
-
orthoRight: mergeCam.orthoRight,
|
|
2815
|
-
orthoBottom: mergeCam.orthoBottom,
|
|
2816
|
-
orthoTop: mergeCam.orthoTop
|
|
2817
|
-
} : void 0;
|
|
2818
|
-
const csm = computeDirectionalCsm(
|
|
2819
|
-
directionalCsmDirection,
|
|
2820
|
-
directionalCsmConfig,
|
|
2821
|
-
mergeCameraData
|
|
2822
|
-
);
|
|
2823
|
-
if (csm !== null) {
|
|
2824
|
-
lightViewProj = csm.lightViewProj;
|
|
2825
|
-
splitPlanes = csm.splitPlanes;
|
|
2826
|
-
cascadeCount = csm.cascadeCount;
|
|
2827
|
-
cascadeBlend = csm.cascadeBlend;
|
|
2828
|
-
shadowMapSize = csm.shadowMapSize;
|
|
2829
|
-
directionalShadowQuality = csm.directionalShadowQuality;
|
|
2310
|
+
const paddedSplitPlanes = new Float32Array(16);
|
|
2311
|
+
if (splitPlanes !== void 0) {
|
|
2312
|
+
for (let i = 0; i < splitPlanes.length; i++) {
|
|
2313
|
+
paddedSplitPlanes[i] = splitPlanes[i] ?? 0;
|
|
2830
2314
|
}
|
|
2831
2315
|
}
|
|
2832
|
-
const
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2316
|
+
const pointShadowSnapshots = [];
|
|
2317
|
+
{
|
|
2318
|
+
const pointShadowQuery = world.query({ read: [Transform, GlobalTransform, PointLightShadow], with: [PointLight] }).unwrap();
|
|
2319
|
+
for (const row of pointShadowQuery) {
|
|
2320
|
+
const ps = row.get(PointLightShadow);
|
|
2321
|
+
const wRow = row.get(GlobalTransform).world;
|
|
2322
|
+
if (wRow === void 0) continue;
|
|
2323
|
+
const px = wRow[12] ?? 0;
|
|
2324
|
+
const py = wRow[13] ?? 0;
|
|
2325
|
+
const pz = wRow[14] ?? 0;
|
|
2326
|
+
const lightPos = vec3.create(px, py, pz);
|
|
2327
|
+
const mapSize = ps.mapSize;
|
|
2328
|
+
const nearPlane = ps.nearPlane;
|
|
2329
|
+
const farPlane = ps.farPlane;
|
|
2330
|
+
const layer = pointShadowSnapshots.length < SHADOW_ATLAS_DEFAULT_LAYERS ? pointShadowSnapshots.length : -1;
|
|
2331
|
+
const matrices = buildPointShadowMatrices(lightPos, nearPlane, farPlane);
|
|
2332
|
+
const packed = new Float32Array(96);
|
|
2333
|
+
for (let f = 0; f < 6; f++) {
|
|
2334
|
+
const m = matrices[f];
|
|
2335
|
+
if (m === void 0) continue;
|
|
2336
|
+
for (let k = 0; k < 16; k++) {
|
|
2337
|
+
packed[f * 16 + k] = m[k] ?? 0;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
pointShadowSnapshots.push({
|
|
2341
|
+
entity: row.entity,
|
|
2342
|
+
position: lightPos,
|
|
2343
|
+
mapSize,
|
|
2344
|
+
nearPlane,
|
|
2345
|
+
farPlane,
|
|
2346
|
+
shadowAtlasLayer: layer,
|
|
2347
|
+
shadowMatrices: packed
|
|
2348
|
+
});
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
if (pointShadowSnapshots.length > 0) {
|
|
2352
|
+
const shadowByEntity = /* @__PURE__ */ new Map();
|
|
2353
|
+
for (const ps of pointShadowSnapshots) shadowByEntity.set(ps.entity, ps);
|
|
2354
|
+
for (let i = 0; i < pointSnapshots.length; i++) {
|
|
2355
|
+
const entityId = pointSnapshotEntities[i] ?? 0;
|
|
2356
|
+
const ps = shadowByEntity.get(entityId);
|
|
2357
|
+
if (ps !== void 0) {
|
|
2358
|
+
pointSnapshots[i] = {
|
|
2359
|
+
...pointSnapshots[i],
|
|
2360
|
+
shadowAtlasLayer: ps.shadowAtlasLayer,
|
|
2361
|
+
shadowNear: ps.nearPlane,
|
|
2362
|
+
shadowFar: ps.farPlane
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
const lights = {
|
|
2368
|
+
directional,
|
|
2369
|
+
directionalCount,
|
|
2370
|
+
point: pointSnapshots,
|
|
2371
|
+
spot: spotSnapshots,
|
|
2372
|
+
rect: rectSnapshots,
|
|
2373
|
+
lightViewProj,
|
|
2374
|
+
splitPlanes: splitPlanes !== void 0 ? paddedSplitPlanes : void 0,
|
|
2375
|
+
cascadeCount,
|
|
2376
|
+
cascadeBlend,
|
|
2377
|
+
shadowMapSize,
|
|
2378
|
+
depthBias: firstHitCastShadow !== false ? firstHitShadowFields?.depthBias : void 0,
|
|
2379
|
+
normalBias: firstHitCastShadow !== false ? firstHitShadowFields?.normalBias : void 0,
|
|
2845
2380
|
directionalShadowQuality,
|
|
2846
2381
|
directionalShadowError,
|
|
2847
|
-
pointShadow,
|
|
2382
|
+
pointShadow: pointShadowSnapshots,
|
|
2383
|
+
// bug-20260710-editor-cross-world-shadow: raw CSM config + light direction
|
|
2384
|
+
// so the merge layer can recompute matrices against the surfaced camera.
|
|
2848
2385
|
directionalCsmConfig,
|
|
2849
2386
|
directionalCsmDirection
|
|
2850
2387
|
};
|
|
2851
|
-
const
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
const
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
const worldId = succeededIndices[index] ?? 0;
|
|
2877
|
-
return (f.reflectionProbes ?? []).map((probe) => ({ ...probe, worldId }));
|
|
2878
|
-
});
|
|
2879
|
-
return {
|
|
2880
|
-
cameras,
|
|
2881
|
-
auxiliaryCameras,
|
|
2882
|
-
cubeCameras,
|
|
2883
|
-
reflectionProbes,
|
|
2884
|
-
lights,
|
|
2885
|
-
...volumetricFog === void 0 ? {} : { volumetricFog: { ...volumetricFog, worldId: resourceOwner } },
|
|
2886
|
-
renderables,
|
|
2887
|
-
dispatch: dispatchEntries,
|
|
2888
|
-
skylight,
|
|
2889
|
-
skylightCount,
|
|
2890
|
-
lightProbes,
|
|
2891
|
-
skybox,
|
|
2892
|
-
skyboxCount,
|
|
2893
|
-
fog,
|
|
2894
|
-
...fogFailure === void 0 ? {} : { fogFailure },
|
|
2895
|
-
environment,
|
|
2896
|
-
environmentReady: resourceOwnerFrame !== void 0 && environment !== void 0,
|
|
2897
|
-
frustumStats,
|
|
2898
|
-
visibilityStats,
|
|
2899
|
-
postProcessParams,
|
|
2900
|
-
visibilitySnapshots,
|
|
2901
|
-
featureVisibilitySnapshots,
|
|
2902
|
-
hiddenEntityReports
|
|
2903
|
-
};
|
|
2904
|
-
}
|
|
2905
|
-
function hasFiniteOrderedLocalAabb(aabb) {
|
|
2906
|
-
if (aabb === void 0 || aabb.length !== 6) return false;
|
|
2907
|
-
const minX = aabb[0];
|
|
2908
|
-
const minY = aabb[1];
|
|
2909
|
-
const minZ = aabb[2];
|
|
2910
|
-
const maxX = aabb[3];
|
|
2911
|
-
const maxY = aabb[4];
|
|
2912
|
-
const maxZ = aabb[5];
|
|
2913
|
-
if (minX === void 0 || minY === void 0 || minZ === void 0 || maxX === void 0 || maxY === void 0 || maxZ === void 0) {
|
|
2914
|
-
return false;
|
|
2915
|
-
}
|
|
2916
|
-
if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(minZ) || !Number.isFinite(maxX) || !Number.isFinite(maxY) || !Number.isFinite(maxZ)) {
|
|
2917
|
-
return false;
|
|
2918
|
-
}
|
|
2919
|
-
return minX <= maxX && minY <= maxY && minZ <= maxZ;
|
|
2920
|
-
}
|
|
2921
|
-
function morphSnapshotFor(mesh, weights) {
|
|
2922
|
-
const targets = mesh.morphTargets;
|
|
2923
|
-
if (targets === void 0 || targets.length === 0 || weights === void 0) return void 0;
|
|
2924
|
-
if (weights.length !== targets.length) return void 0;
|
|
2925
|
-
const firstPositions = targets[0]?.position;
|
|
2926
|
-
if (firstPositions === void 0 || firstPositions.length === 0 || firstPositions.length % 3 !== 0) {
|
|
2927
|
-
return void 0;
|
|
2928
|
-
}
|
|
2929
|
-
const vertexCount = firstPositions.length / 3;
|
|
2930
|
-
if (mesh.vertices.length % vertexCount !== 0) return void 0;
|
|
2931
|
-
for (let targetIndex = 0; targetIndex < targets.length; targetIndex += 1) {
|
|
2932
|
-
const target = targets[targetIndex];
|
|
2933
|
-
if (target?.position?.length !== firstPositions.length) return void 0;
|
|
2934
|
-
}
|
|
2935
|
-
const copied = new Float32Array(weights.length);
|
|
2936
|
-
for (let index = 0; index < weights.length; index += 1) {
|
|
2937
|
-
const weight = weights[index] ?? Number.NaN;
|
|
2938
|
-
if (!Number.isFinite(weight)) return void 0;
|
|
2939
|
-
copied[index] = weight;
|
|
2940
|
-
}
|
|
2941
|
-
return { weights: copied, targetCount: targets.length };
|
|
2942
|
-
}
|
|
2943
|
-
function extractFrame(world, context) {
|
|
2944
|
-
const {
|
|
2945
|
-
assets,
|
|
2946
|
-
pipelineState,
|
|
2947
|
-
materialSnapshotCache: persistentMaterialSnapshotCache,
|
|
2948
|
-
cull: cullMode,
|
|
2949
|
-
resourceOwnerFog,
|
|
2950
|
-
getMaterialShaderArtifact
|
|
2951
|
-
} = context;
|
|
2952
|
-
const fog = resourceOwnerFog === void 0 ? selectFogFrame(world) : resourceOwnerFog ?? void 0;
|
|
2953
|
-
const fogFailure = fogState(world).failure;
|
|
2954
|
-
const visibility = context.visibility.hasAnyHiddenIntent ? context.visibility : void 0;
|
|
2955
|
-
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
2956
|
-
const directionalLightQuery = world.query({ read: [DirectionalLight] }).unwrap();
|
|
2957
|
-
const worldInternal = createWorldInternalView(world);
|
|
2958
|
-
let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
|
|
2959
|
-
const cameraRoles = selectCameraRoles(world);
|
|
2960
|
-
const cameras = [...cameraRoles.display];
|
|
2961
|
-
const auxiliaryCameras = cameraRoles.auxiliary;
|
|
2962
|
-
const cubeCameras = collectCubeCameraSnapshots(world);
|
|
2963
|
-
const reflectionProbes = collectReflectionProbeFacts(world);
|
|
2964
|
-
let directional;
|
|
2965
|
-
let directionalCount = 0;
|
|
2966
|
-
let firstHitCastShadow;
|
|
2967
|
-
let firstHitShadowFields;
|
|
2968
|
-
for (const row of directionalLightQuery) {
|
|
2969
|
-
const l = row.get(DirectionalLight);
|
|
2970
|
-
directionalCount += 1;
|
|
2971
|
-
const intensity = l.intensity;
|
|
2972
|
-
const snapshot = {
|
|
2973
|
-
kind: "directional",
|
|
2974
|
-
entity: row.entity,
|
|
2975
|
-
direction: vec3.create(l.direction[0] ?? 0, l.direction[1] ?? -1, l.direction[2] ?? 0),
|
|
2976
|
-
color: vec3.create(
|
|
2977
|
-
(l.color[0] ?? 1) * intensity,
|
|
2978
|
-
(l.color[1] ?? 1) * intensity,
|
|
2979
|
-
(l.color[2] ?? 1) * intensity
|
|
2980
|
-
),
|
|
2981
|
-
intensity
|
|
2982
|
-
};
|
|
2983
|
-
if (directional === void 0) {
|
|
2984
|
-
directional = snapshot;
|
|
2985
|
-
firstHitCastShadow = l.castShadow;
|
|
2986
|
-
firstHitShadowFields = {
|
|
2987
|
-
cascadeCount: l.cascadeCount,
|
|
2988
|
-
splitLambda: l.splitLambda,
|
|
2989
|
-
cascadeBlend: l.cascadeBlend,
|
|
2990
|
-
mapSize: l.mapSize,
|
|
2991
|
-
depthBias: l.depthBias,
|
|
2992
|
-
normalBias: l.normalBias,
|
|
2993
|
-
shadowDistance: l.shadowDistance,
|
|
2994
|
-
shadowFilter: l.shadowFilter,
|
|
2995
|
-
shadowAngularRadius: l.shadowAngularRadius,
|
|
2996
|
-
maxPenumbraTexels: l.maxPenumbraTexels
|
|
2388
|
+
const skylightQuery = world.query({ read: [Skylight] }).unwrap();
|
|
2389
|
+
let skylight;
|
|
2390
|
+
let skylightCount = 0;
|
|
2391
|
+
for (const row of skylightQuery) {
|
|
2392
|
+
const s = row.get(Skylight);
|
|
2393
|
+
const equirectRaw = s.equirect;
|
|
2394
|
+
const intensity = s.intensity;
|
|
2395
|
+
const colorR = s.color[0] ?? 1;
|
|
2396
|
+
const colorG = s.color[1] ?? 1;
|
|
2397
|
+
const colorB = s.color[2] ?? 1;
|
|
2398
|
+
const rotation = [
|
|
2399
|
+
s.rotation[0] ?? 0,
|
|
2400
|
+
s.rotation[1] ?? 0,
|
|
2401
|
+
s.rotation[2] ?? 0,
|
|
2402
|
+
s.rotation[3] ?? 1
|
|
2403
|
+
];
|
|
2404
|
+
skylightCount += 1;
|
|
2405
|
+
if (skylight === void 0) {
|
|
2406
|
+
skylight = {
|
|
2407
|
+
equirectHandle: equirectRaw !== void 0 ? Math.round(equirectRaw) : 0,
|
|
2408
|
+
color: [colorR, colorG, colorB],
|
|
2409
|
+
intensity,
|
|
2410
|
+
rotation,
|
|
2411
|
+
// w19: winning entity handle for the multi-Skylight once-warn (F-8).
|
|
2412
|
+
entityHandle: row.entity
|
|
2997
2413
|
};
|
|
2998
2414
|
}
|
|
2999
2415
|
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
2416
|
+
const lightProbeQuery = world.query({ read: [LightProbe, GlobalTransform] }).unwrap();
|
|
2417
|
+
const lightProbes = [];
|
|
2418
|
+
for (const row of lightProbeQuery) {
|
|
2419
|
+
const probe = row.get(LightProbe);
|
|
2420
|
+
const validation = validateLightProbeData({
|
|
2421
|
+
irradiance: probe.irradiance,
|
|
2422
|
+
radius: probe.radius
|
|
3006
2423
|
});
|
|
3007
2424
|
if (!validation.ok) {
|
|
3008
|
-
|
|
3009
|
-
worldInternal._routeError(directionalShadowError, {
|
|
2425
|
+
worldInternal._routeError(validation.error, {
|
|
3010
2426
|
severity: Severity.Error,
|
|
3011
|
-
systemName: "RenderSystem.extract (
|
|
2427
|
+
systemName: "RenderSystem.extract (light-probe)"
|
|
3012
2428
|
});
|
|
2429
|
+
continue;
|
|
3013
2430
|
}
|
|
2431
|
+
const transform = row.get(GlobalTransform);
|
|
2432
|
+
lightProbes.push({
|
|
2433
|
+
identity: String(row.entity),
|
|
2434
|
+
position: [transform.world[12] ?? 0, transform.world[13] ?? 0, transform.world[14] ?? 0],
|
|
2435
|
+
radius: probe.radius,
|
|
2436
|
+
irradiance: new Float32Array(probe.irradiance),
|
|
2437
|
+
admitted: true
|
|
2438
|
+
});
|
|
3014
2439
|
}
|
|
3015
|
-
const
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
const
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
2440
|
+
const skyboxQuery = world.query({ read: [SkyboxBackground] }).unwrap();
|
|
2441
|
+
let skybox;
|
|
2442
|
+
let skyboxCount = 0;
|
|
2443
|
+
for (const row of skyboxQuery) {
|
|
2444
|
+
const s = row.get(SkyboxBackground);
|
|
2445
|
+
const equirectRaw = s.equirect;
|
|
2446
|
+
const modeRaw = s.mode;
|
|
2447
|
+
const rotation = [
|
|
2448
|
+
s.rotation[0] ?? 0,
|
|
2449
|
+
s.rotation[1] ?? 0,
|
|
2450
|
+
s.rotation[2] ?? 0,
|
|
2451
|
+
s.rotation[3] ?? 1
|
|
2452
|
+
];
|
|
2453
|
+
skyboxCount += 1;
|
|
2454
|
+
if (skybox === void 0 && equirectRaw !== void 0) {
|
|
2455
|
+
skybox = {
|
|
2456
|
+
equirectHandle: Math.round(equirectRaw),
|
|
2457
|
+
mode: modeRaw,
|
|
2458
|
+
rotation,
|
|
2459
|
+
// w19: winning entity handle for the multi-SkyboxBackground warn (F-8).
|
|
2460
|
+
entityHandle: row.entity
|
|
2461
|
+
};
|
|
3031
2462
|
}
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
(p.color[2] ?? 1) * intensity
|
|
3041
|
-
),
|
|
3042
|
-
intensity,
|
|
3043
|
-
invRangeSquared: computeInvRangeSquared(range)
|
|
2463
|
+
}
|
|
2464
|
+
const environmentCandidates = [];
|
|
2465
|
+
const imageEnvironment = skylight?.equirectHandle !== void 0 && skylight.equirectHandle > 0 ? skylight : skybox?.equirectHandle !== void 0 && skybox.equirectHandle > 0 ? skybox : void 0;
|
|
2466
|
+
if (imageEnvironment !== void 0) {
|
|
2467
|
+
environmentCandidates.push({
|
|
2468
|
+
kind: "image",
|
|
2469
|
+
entityKey: imageEnvironment.entityHandle,
|
|
2470
|
+
sourceKey: `equirect:${imageEnvironment.equirectHandle}`
|
|
3044
2471
|
});
|
|
3045
|
-
pointSnapshotEntities.push(entityId);
|
|
3046
2472
|
}
|
|
3047
|
-
const
|
|
3048
|
-
const
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
severity: Severity.Error,
|
|
3085
|
-
systemName: "RenderSystem.extract (spot-direction)"
|
|
3086
|
-
}
|
|
3087
|
-
);
|
|
2473
|
+
const atmosphereQuery = world.query({ read: [Atmosphere] }).unwrap();
|
|
2474
|
+
for (const row of atmosphereQuery) {
|
|
2475
|
+
const value = row.get(Atmosphere);
|
|
2476
|
+
const atmosphere = {
|
|
2477
|
+
turbidity: value.turbidity,
|
|
2478
|
+
rayleigh: value.rayleigh,
|
|
2479
|
+
mieCoefficient: value.mieCoefficient,
|
|
2480
|
+
mieDirectionalG: value.mieDirectionalG,
|
|
2481
|
+
sunAngularRadius: value.sunAngularRadius
|
|
2482
|
+
};
|
|
2483
|
+
environmentCandidates.push({
|
|
2484
|
+
kind: "atmosphere",
|
|
2485
|
+
entityKey: row.entity,
|
|
2486
|
+
sourceKey: `atmosphere:${row.entity}`,
|
|
2487
|
+
atmosphere
|
|
2488
|
+
});
|
|
2489
|
+
}
|
|
2490
|
+
const directionalDirection = directional?.direction;
|
|
2491
|
+
const directionalLength = directionalDirection === void 0 ? 0 : Math.hypot(
|
|
2492
|
+
directionalDirection[0] ?? 0,
|
|
2493
|
+
directionalDirection[1] ?? 0,
|
|
2494
|
+
directionalDirection[2] ?? 0
|
|
2495
|
+
);
|
|
2496
|
+
const sun = directional === void 0 || directionalLength <= 1e-6 ? [] : [
|
|
2497
|
+
{
|
|
2498
|
+
entityKey: 0,
|
|
2499
|
+
direction: [
|
|
2500
|
+
-(directionalDirection?.[0] ?? 0) / directionalLength,
|
|
2501
|
+
-(directionalDirection?.[1] ?? 0) / directionalLength,
|
|
2502
|
+
-(directionalDirection?.[2] ?? 0) / directionalLength
|
|
2503
|
+
],
|
|
2504
|
+
color: [
|
|
2505
|
+
directional.color[0] ?? 0,
|
|
2506
|
+
directional.color[1] ?? 0,
|
|
2507
|
+
directional.color[2] ?? 0
|
|
2508
|
+
],
|
|
2509
|
+
intensity: directional.intensity
|
|
3088
2510
|
}
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
if (
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
2511
|
+
];
|
|
2512
|
+
const environmentSelection = selectEnvironment({
|
|
2513
|
+
environments: environmentCandidates,
|
|
2514
|
+
fogs: fog === void 0 ? [] : [fog],
|
|
2515
|
+
suns: sun,
|
|
2516
|
+
lane: "direct"
|
|
2517
|
+
});
|
|
2518
|
+
if (!environmentSelection.ok) {
|
|
2519
|
+
routeWorldError(world, environmentSelection.error, {
|
|
2520
|
+
systemName: "RenderSystem.extract (environment-selection)"
|
|
2521
|
+
});
|
|
2522
|
+
throw environmentSelection.error;
|
|
2523
|
+
}
|
|
2524
|
+
const environment = environmentSelection.value;
|
|
2525
|
+
const frustumPlanes = [];
|
|
2526
|
+
const cullingCameras = cullMode === "external" ? context.cullCameras ?? [] : cameras;
|
|
2527
|
+
if (cullMode !== "none") {
|
|
2528
|
+
for (const cam of cullingCameras) {
|
|
2529
|
+
if (cam.projection === "perspective" && (cam.fov <= 0 || cam.aspect <= 0)) {
|
|
2530
|
+
frustumPlanes.push(new Float32Array(0));
|
|
2531
|
+
continue;
|
|
2532
|
+
}
|
|
2533
|
+
if (cam.near >= cam.far) {
|
|
2534
|
+
frustumPlanes.push(new Float32Array(0));
|
|
2535
|
+
continue;
|
|
2536
|
+
}
|
|
2537
|
+
const proj = mat4.create();
|
|
2538
|
+
if (cam.projection === "orthographic") {
|
|
2539
|
+
mat4.orthographic(
|
|
2540
|
+
proj,
|
|
2541
|
+
cam.orthoLeft,
|
|
2542
|
+
cam.orthoRight,
|
|
2543
|
+
cam.orthoTop,
|
|
2544
|
+
cam.orthoBottom,
|
|
2545
|
+
cam.near,
|
|
2546
|
+
cam.far
|
|
3116
2547
|
);
|
|
3117
2548
|
} else {
|
|
3118
|
-
|
|
3119
|
-
projectorAsset = resolvedProjector.value;
|
|
3120
|
-
projectorGuid = assets?.guidOf(projectorAsset) ?? `handle:${Number(candidate)}`;
|
|
2549
|
+
mat4.perspective(proj, cam.fov, cam.aspect, cam.near, cam.far);
|
|
3121
2550
|
}
|
|
3122
|
-
}
|
|
3123
|
-
const iesProfileData = iesProfileAsset?.ok && iesProfileAsset.value.kind === "ies-profile" ? new Uint8Array(iesProfileAsset.value.data) : void 0;
|
|
3124
|
-
const cookieProjection = cookieAsset?.ok && cookieAsset.value.kind === "texture" ? prepareCookieProjection(cookieAsset.value) : void 0;
|
|
3125
|
-
const cookieData = cookieProjection?.data;
|
|
3126
|
-
const projectorProjection = projectorAsset === void 0 ? void 0 : prepareCookieProjection(projectorAsset);
|
|
3127
|
-
const projectorData = projectorProjection?.data;
|
|
3128
|
-
const iesProfileHandle = s.iesProfile === void 0 ? void 0 : handleSlot(s.iesProfile);
|
|
3129
|
-
const cookieHandle = s.cookie === void 0 ? void 0 : handleSlot(s.cookie);
|
|
3130
|
-
let iesProfileSlice = iesProfileHandle === void 0 ? void 0 : iesSlices.get(iesProfileHandle);
|
|
3131
|
-
if (iesProfileSlice === void 0 && iesProfileHandle !== void 0 && iesProfileData !== void 0 && iesSlices.size < IES_SLICE_CAPACITY) {
|
|
3132
|
-
iesProfileSlice = iesSlices.size;
|
|
3133
|
-
iesSlices.set(iesProfileHandle, iesProfileSlice);
|
|
3134
|
-
}
|
|
3135
|
-
let cookieSlice = cookieHandle === void 0 ? void 0 : cookieSlices.get(cookieHandle);
|
|
3136
|
-
if (cookieSlice === void 0 && cookieHandle !== void 0 && cookieData !== void 0 && cookieSlices.size < COOKIE_SLICE_CAPACITY) {
|
|
3137
|
-
cookieSlice = cookieSlices.size;
|
|
3138
|
-
cookieSlices.set(cookieHandle, cookieSlice);
|
|
3139
|
-
}
|
|
3140
|
-
let projectorSlice = projectorHandle === void 0 ? void 0 : projectorSlices.get(projectorHandle) ?? cookieSlices.get(projectorHandle);
|
|
3141
|
-
if (projectorSlice === void 0 && projectorHandle !== void 0 && projectorData !== void 0 && cookieSlices.size + projectorSlices.size < COOKIE_SLICE_CAPACITY) {
|
|
3142
|
-
projectorSlice = cookieSlices.size + projectorSlices.size;
|
|
3143
|
-
projectorSlices.set(projectorHandle, projectorSlice);
|
|
3144
|
-
}
|
|
3145
|
-
const shadowIntensity = s.shadowIntensity;
|
|
3146
|
-
let lightViewProj2;
|
|
3147
|
-
let shadowAtlasTile = -1;
|
|
3148
|
-
if ((castShadow || hasProjector) && hasValidDirection) {
|
|
3149
|
-
const target = vec3.create(
|
|
3150
|
-
(position[0] ?? 0) + (dirN[0] ?? 0),
|
|
3151
|
-
(position[1] ?? 0) + (dirN[1] ?? 0),
|
|
3152
|
-
(position[2] ?? 0) + (dirN[2] ?? 0)
|
|
3153
|
-
);
|
|
3154
|
-
const fov = outerConeDeg * 2 * (Math.PI / 180);
|
|
3155
|
-
const proj = mat4.create();
|
|
3156
|
-
mat4.perspective(proj, fov, 1, sNearPlane, sFarPlane);
|
|
3157
2551
|
const view = mat4.create();
|
|
3158
|
-
mat4.
|
|
3159
|
-
|
|
3160
|
-
mat4.multiply(
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
}
|
|
3166
|
-
spotSnapshots.push({
|
|
3167
|
-
kind: "spot",
|
|
3168
|
-
entity: row.entity,
|
|
3169
|
-
// D-6: position reflects world transform; direction stays sourced
|
|
3170
|
-
// from SpotLight.direction (NOT rotated by the parent).
|
|
3171
|
-
position,
|
|
3172
|
-
direction: dirN,
|
|
3173
|
-
color: vec3.create(
|
|
3174
|
-
(s.color[0] ?? 1) * intensity,
|
|
3175
|
-
(s.color[1] ?? 1) * intensity,
|
|
3176
|
-
(s.color[2] ?? 1) * intensity
|
|
3177
|
-
),
|
|
3178
|
-
intensity,
|
|
3179
|
-
invRangeSquared: computeInvRangeSquared(range),
|
|
3180
|
-
cosInner: degToCos(innerConeDeg),
|
|
3181
|
-
cosOuter: degToCos(outerConeDeg),
|
|
3182
|
-
...s.iesProfile === void 0 ? {} : {
|
|
3183
|
-
iesProfileHandle: handleSlot(s.iesProfile),
|
|
3184
|
-
...iesProfileSlice === void 0 ? {} : { iesProfileSlice }
|
|
3185
|
-
},
|
|
3186
|
-
...s.cookie === void 0 ? {} : {
|
|
3187
|
-
cookieHandle: handleSlot(s.cookie),
|
|
3188
|
-
...cookieSlice === void 0 ? {} : { cookieSlice }
|
|
3189
|
-
},
|
|
3190
|
-
...iesProfileData === void 0 ? {} : { iesProfileData },
|
|
3191
|
-
...cookieData === void 0 ? {} : { cookieData },
|
|
3192
|
-
...cookieProjection === void 0 ? {} : { cookieMatrix: cookieProjection.matrix },
|
|
3193
|
-
...projectorSlice === void 0 ? {} : { projectorSlice },
|
|
3194
|
-
...projectorData === void 0 ? {} : { projectorData },
|
|
3195
|
-
...projectorProjection === void 0 ? {} : { projectorMatrix: projectorProjection.matrix },
|
|
3196
|
-
rollDeg: s.rollDeg,
|
|
3197
|
-
// ── shadow fields ──
|
|
3198
|
-
castShadow,
|
|
3199
|
-
lightViewProj: lightViewProj2,
|
|
3200
|
-
mapSize: sMapSize,
|
|
3201
|
-
nearPlane: sNearPlane,
|
|
3202
|
-
farPlane: sFarPlane,
|
|
3203
|
-
shadowAtlasTile,
|
|
3204
|
-
shadowIntensity,
|
|
3205
|
-
depthBias: s.depthBias,
|
|
3206
|
-
normalBias: s.normalBias,
|
|
3207
|
-
pcfKernelSize: s.pcfKernelSize,
|
|
3208
|
-
...projectorHandle === void 0 || projectorAsset === void 0 || projectorGuid === void 0 ? {} : {
|
|
3209
|
-
projectorHandle,
|
|
3210
|
-
projectorAsset,
|
|
3211
|
-
projectorGuid,
|
|
3212
|
-
projectorGeneration: 1,
|
|
3213
|
-
projectorRevision: 1
|
|
3214
|
-
}
|
|
3215
|
-
});
|
|
2552
|
+
mat4.invert(view, cam.world);
|
|
2553
|
+
const vp = mat4.create();
|
|
2554
|
+
mat4.multiply(vp, proj, view);
|
|
2555
|
+
const f = frustum.create();
|
|
2556
|
+
frustum.fromViewProjection(f, vp);
|
|
2557
|
+
frustumPlanes.push(f);
|
|
2558
|
+
}
|
|
3216
2559
|
}
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
2560
|
+
const renderables = [];
|
|
2561
|
+
let frustumCulled = 0;
|
|
2562
|
+
let frustumTotal = 0;
|
|
2563
|
+
const explicitlyHidden = /* @__PURE__ */ new Set();
|
|
2564
|
+
let dispatch = [];
|
|
2565
|
+
const materialSnapshotCache = /* @__PURE__ */ new Map();
|
|
2566
|
+
const meshRendererQuery = context.renderables === "none" ? [] : world.query({
|
|
2567
|
+
read: [MeshRenderer],
|
|
2568
|
+
optional: [
|
|
2569
|
+
Transform,
|
|
2570
|
+
GlobalTransform,
|
|
2571
|
+
MeshFilter,
|
|
2572
|
+
Instances,
|
|
2573
|
+
Skin,
|
|
2574
|
+
Layer,
|
|
2575
|
+
MorphWeights,
|
|
2576
|
+
SpriteRegionOverride,
|
|
2577
|
+
SpriteInstances,
|
|
2578
|
+
Points,
|
|
2579
|
+
Lines,
|
|
2580
|
+
SortKey
|
|
2581
|
+
]
|
|
3221
2582
|
}).unwrap();
|
|
3222
|
-
|
|
3223
|
-
const
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
2583
|
+
const resolveArchVersion = (entity) => {
|
|
2584
|
+
const values = [
|
|
2585
|
+
worldInternal._getArrayView(entity, SpriteInstances, "transforms"),
|
|
2586
|
+
worldInternal._getArrayView(entity, SpriteInstances, "regions")
|
|
2587
|
+
];
|
|
2588
|
+
let hash = 2166136261;
|
|
2589
|
+
for (const value of values) {
|
|
2590
|
+
hash = Math.imul(hash ^ (value?.length ?? 0), 16777619) >>> 0;
|
|
2591
|
+
if (value === void 0) continue;
|
|
2592
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
2593
|
+
hash = Math.imul(hash ^ Math.fround(value[index] ?? 0), 16777619) >>> 0;
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
return hash;
|
|
2597
|
+
};
|
|
2598
|
+
const flushPendingDispatch = (pending) => {
|
|
2599
|
+
for (const entry of pending) dispatch.push(entry);
|
|
2600
|
+
};
|
|
2601
|
+
for (const row of meshRendererQuery) {
|
|
2602
|
+
if (context.renderables === "full" && renderableEntities !== void 0 && !renderableEntities.has(row.entity)) {
|
|
3236
2603
|
continue;
|
|
3237
2604
|
}
|
|
3238
|
-
const
|
|
3239
|
-
const
|
|
3240
|
-
const
|
|
3241
|
-
const
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
halfWidth: frame.halfWidth,
|
|
3259
|
-
halfHeight: frame.halfHeight,
|
|
3260
|
-
axisX: frame.axisX,
|
|
3261
|
-
axisY: frame.axisY
|
|
3262
|
-
});
|
|
3263
|
-
}
|
|
3264
|
-
let volumeSpot;
|
|
3265
|
-
const extractedFog = volumetricFog;
|
|
3266
|
-
if (extractedFog !== void 0) {
|
|
3267
|
-
if (extractedFog.spotLightEntity !== void 0) {
|
|
3268
|
-
volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.spotLightEntity);
|
|
3269
|
-
} else if (extractedFog.lightKind === "spot") {
|
|
3270
|
-
volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.lightEntity);
|
|
2605
|
+
const hasTransform = row.has(Transform);
|
|
2606
|
+
const meshFilter = row.get(MeshFilter);
|
|
2607
|
+
const hasInstances = row.has(Instances);
|
|
2608
|
+
const skin = row.get(Skin);
|
|
2609
|
+
const morphWeightsView = worldInternal._getArrayView(row.entity, MorphWeights, "weights");
|
|
2610
|
+
const hasMeshFilter = meshFilter !== void 0;
|
|
2611
|
+
const hasSkin = skin !== void 0;
|
|
2612
|
+
const hasSpriteInstances = row.has(SpriteInstances);
|
|
2613
|
+
const points = row.get(Points);
|
|
2614
|
+
const lines = row.get(Lines);
|
|
2615
|
+
const sortKey = row.get(SortKey)?.value;
|
|
2616
|
+
const pointsLinesComponent = points !== void 0 ? "Points" : lines !== void 0 ? "Lines" : void 0;
|
|
2617
|
+
const isRenderable = hasTransform && hasMeshFilter;
|
|
2618
|
+
const fAssetHandle = meshFilter?.assetHandle;
|
|
2619
|
+
const fLayerValue = row.get(Layer)?.value;
|
|
2620
|
+
const hasSpriteRegionOverride = row.has(SpriteRegionOverride);
|
|
2621
|
+
const skinSkeletonView = skin?.skeleton;
|
|
2622
|
+
let archVersion = 0;
|
|
2623
|
+
if (hasInstances || hasSpriteInstances) {
|
|
2624
|
+
archVersion = resolveArchVersion(row.entity);
|
|
3271
2625
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
projector: {
|
|
3279
|
-
guid: volumeSpot.projectorGuid ?? `handle:${Number(volumeSpot.projectorHandle)}`,
|
|
3280
|
-
generation: volumeSpot.projectorGeneration ?? 1,
|
|
3281
|
-
view: "2d",
|
|
3282
|
-
sampler: "linear-clamp-to-edge",
|
|
3283
|
-
projection: "spot-projection",
|
|
3284
|
-
revision: volumeSpot.projectorRevision ?? 1
|
|
3285
|
-
},
|
|
3286
|
-
projectorHandle,
|
|
3287
|
-
projectorAsset
|
|
3288
|
-
};
|
|
3289
|
-
}
|
|
3290
|
-
let lightViewProj;
|
|
3291
|
-
let splitPlanes;
|
|
3292
|
-
let cascadeCount;
|
|
3293
|
-
let cascadeBlend;
|
|
3294
|
-
let shadowMapSize;
|
|
3295
|
-
let directionalShadowQuality;
|
|
3296
|
-
let directionalCsmConfig;
|
|
3297
|
-
let directionalCsmDirection;
|
|
3298
|
-
const cam0 = cameras[0];
|
|
3299
|
-
const cameraData = cam0 !== void 0 ? {
|
|
3300
|
-
world: cam0.world,
|
|
3301
|
-
fov: cam0.fov,
|
|
3302
|
-
aspect: cam0.aspect,
|
|
3303
|
-
near: cam0.near,
|
|
3304
|
-
far: cam0.far,
|
|
3305
|
-
projection: cam0.projection,
|
|
3306
|
-
orthoLeft: cam0.orthoLeft,
|
|
3307
|
-
orthoRight: cam0.orthoRight,
|
|
3308
|
-
orthoBottom: cam0.orthoBottom,
|
|
3309
|
-
orthoTop: cam0.orthoTop
|
|
3310
|
-
} : void 0;
|
|
3311
|
-
if (directional !== void 0 && firstHitCastShadow !== false && directionalShadowError === void 0) {
|
|
3312
|
-
const dirSnapshot = directional;
|
|
3313
|
-
const sf = firstHitShadowFields;
|
|
3314
|
-
if (sf !== void 0) {
|
|
3315
|
-
directionalCsmConfig = {
|
|
3316
|
-
cascadeCount: sf.cascadeCount,
|
|
3317
|
-
splitLambda: sf.splitLambda,
|
|
3318
|
-
cascadeBlend: sf.cascadeBlend,
|
|
3319
|
-
mapSize: sf.mapSize,
|
|
3320
|
-
shadowDistance: sf.shadowDistance,
|
|
3321
|
-
shadowFilter: sf.shadowFilter,
|
|
3322
|
-
shadowAngularRadius: sf.shadowAngularRadius,
|
|
3323
|
-
maxPenumbraTexels: sf.maxPenumbraTexels
|
|
3324
|
-
};
|
|
3325
|
-
directionalCsmDirection = dirSnapshot.direction;
|
|
3326
|
-
const csm = computeDirectionalCsm(dirSnapshot.direction, directionalCsmConfig, cameraData);
|
|
3327
|
-
cascadeCount = Math.round(sf.cascadeCount);
|
|
3328
|
-
cascadeBlend = sf.cascadeBlend;
|
|
3329
|
-
shadowMapSize = sf.mapSize;
|
|
3330
|
-
if (csm !== null) {
|
|
3331
|
-
lightViewProj = csm.lightViewProj;
|
|
3332
|
-
splitPlanes = csm.splitPlanes;
|
|
3333
|
-
directionalShadowQuality = csm.directionalShadowQuality;
|
|
3334
|
-
} else {
|
|
3335
|
-
const sNear = cameraData?.near ?? 0.1;
|
|
3336
|
-
const splits = pssmSplit(sNear, sf.shadowDistance, cascadeCount, sf.splitLambda);
|
|
3337
|
-
const padded = new Float32Array(16);
|
|
3338
|
-
for (let i = 0; i < splits.length; i++) padded[i * 4] = splits[i] ?? 0;
|
|
3339
|
-
splitPlanes = padded;
|
|
2626
|
+
{
|
|
2627
|
+
const entity = row.entity;
|
|
2628
|
+
const authorVisible = !(isRenderable && visibility?.effective(entity) === "hidden");
|
|
2629
|
+
if (!authorVisible) explicitlyHidden.add(entity);
|
|
2630
|
+
if (!authorVisible && !retainHidden) {
|
|
2631
|
+
continue;
|
|
3340
2632
|
}
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
2633
|
+
const layerVal = fLayerValue ?? 0;
|
|
2634
|
+
const pendingDispatch = [];
|
|
2635
|
+
const materialsView = worldInternal._getArrayView(entity, MeshRenderer, "materials");
|
|
2636
|
+
const materialCount = materialsView?.length ?? 0;
|
|
2637
|
+
let materialHandles = Array.from(materialsView ?? []);
|
|
2638
|
+
let materialBindingSources = materialHandles.map(
|
|
2639
|
+
() => "renderer-override"
|
|
3345
2640
|
);
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
2641
|
+
let materialBindingDiagnostics = [];
|
|
2642
|
+
let gpuDrivenSubmeshes = [];
|
|
2643
|
+
let gpuDrivenIndexed = false;
|
|
2644
|
+
let gpuDrivenGeometry;
|
|
2645
|
+
const fAssetHandleVal = fAssetHandle;
|
|
2646
|
+
if (fAssetHandleVal !== void 0 && fAssetHandleVal !== 0 && assets !== void 0 && assets !== null) {
|
|
2647
|
+
const meshHandle = toShared(fAssetHandleVal);
|
|
2648
|
+
const meshRes = resolveAssetHandle(world, meshHandle);
|
|
2649
|
+
if (meshRes.ok && meshRes.value.kind === "mesh") {
|
|
2650
|
+
const meshAsset = meshRes.value;
|
|
2651
|
+
const guid = meshRes.value.guid ?? "<no-guid>";
|
|
2652
|
+
gpuDrivenSubmeshes = meshAsset.submeshes;
|
|
2653
|
+
gpuDrivenIndexed = meshAsset.indices !== void 0;
|
|
2654
|
+
const layoutProjection = deriveVertexLayoutProjection(meshAsset.attributes);
|
|
2655
|
+
gpuDrivenGeometry = {
|
|
2656
|
+
identity: `${guid}:${layoutProjection.digest}`,
|
|
2657
|
+
vertexInputs: layoutProjection.attributes.map((attribute) => ({
|
|
2658
|
+
semantic: attribute.key,
|
|
2659
|
+
location: attribute.shaderLocation,
|
|
2660
|
+
format: attribute.format
|
|
2661
|
+
})),
|
|
2662
|
+
topology: meshAsset.submeshes[0]?.topology ?? "triangle-list",
|
|
2663
|
+
indexed: gpuDrivenIndexed
|
|
2664
|
+
};
|
|
2665
|
+
if (!Array.isArray(meshAsset.materialSlots) && world.get(entity, GlyphText).ok) {
|
|
2666
|
+
ensureGlyphMeshMaterialSlots(world, meshHandle);
|
|
2667
|
+
}
|
|
2668
|
+
const resolvedBindings = resolveMeshMaterialBindings(meshAsset, materialsView ?? [], {
|
|
2669
|
+
isValidOverride(handle) {
|
|
2670
|
+
const resolved = resolveAssetHandle(world, toShared(handle));
|
|
2671
|
+
return resolved.ok && resolved.value.kind === "material";
|
|
2672
|
+
},
|
|
2673
|
+
resolveMeshDefault(defaultGuid) {
|
|
2674
|
+
const guidText = AssetGuid.format(defaultGuid);
|
|
2675
|
+
if (assets.lookup(guidText)?.kind !== "material") return void 0;
|
|
2676
|
+
return internSharedRefFromGuid(world, assets, guidText, "MaterialAsset");
|
|
2677
|
+
}
|
|
2678
|
+
});
|
|
2679
|
+
if (!resolvedBindings.ok) {
|
|
2680
|
+
if (resolvedBindings.code === "mesh-material-slots-missing") {
|
|
2681
|
+
worldInternal._routeError(
|
|
2682
|
+
new AssetError({
|
|
2683
|
+
code: "load-failed",
|
|
2684
|
+
expected: "every MeshAsset producer supplies materialSlots[]",
|
|
2685
|
+
hint: `fix the MeshAsset producer; renderer inheritance never guesses slot topology (mesh=${guid}, entity=${entity}, vertices=${meshAsset.vertices.length}, indices=${meshAsset.indices?.length ?? 0})`,
|
|
2686
|
+
detail: {
|
|
2687
|
+
referencedByGuid: guid,
|
|
2688
|
+
referencedByKind: "mesh",
|
|
2689
|
+
subAssetGuid: "<material-slots-missing>",
|
|
2690
|
+
sourceField: { fieldName: "materialSlots" }
|
|
2691
|
+
}
|
|
2692
|
+
}),
|
|
2693
|
+
{
|
|
2694
|
+
severity: Severity.Error,
|
|
2695
|
+
systemName: "RenderSystem.extract (mesh-material-slots-missing)"
|
|
2696
|
+
}
|
|
2697
|
+
);
|
|
2698
|
+
continue;
|
|
2699
|
+
}
|
|
2700
|
+
const materialGuid = AssetGuid.format(resolvedBindings.defaultMaterial);
|
|
2701
|
+
worldInternal._routeError(
|
|
2702
|
+
new AssetError({
|
|
2703
|
+
code: "load-failed",
|
|
2704
|
+
expected: `MeshAsset materialSlots[${resolvedBindings.slotIndex}] default ${materialGuid} is ready and a MaterialAsset`,
|
|
2705
|
+
hint: `loadByGuid(meshGuid) must recursively load the declared default material; mesh=${guid}, slot=${resolvedBindings.slotIndex}, material=${materialGuid}`,
|
|
2706
|
+
detail: {
|
|
2707
|
+
referencedByGuid: guid,
|
|
2708
|
+
referencedByKind: "mesh",
|
|
2709
|
+
subAssetGuid: materialGuid,
|
|
2710
|
+
sourceField: {
|
|
2711
|
+
fieldName: "materialSlots",
|
|
2712
|
+
arrayIndex: resolvedBindings.slotIndex
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
}),
|
|
2716
|
+
{
|
|
2717
|
+
severity: Severity.Error,
|
|
2718
|
+
systemName: "RenderSystem.extract (mesh-default-not-ready)"
|
|
2719
|
+
}
|
|
2720
|
+
);
|
|
2721
|
+
continue;
|
|
2722
|
+
}
|
|
2723
|
+
materialHandles = resolvedBindings.bindings.map((binding) => binding.handle);
|
|
2724
|
+
materialBindingSources = resolvedBindings.bindings.map((binding) => binding.source);
|
|
2725
|
+
materialBindingDiagnostics = resolvedBindings.diagnostics.map((diagnostic) => ({
|
|
2726
|
+
...diagnostic,
|
|
2727
|
+
detail: diagnostic.code === "mesh-renderer-material-override-overflow" ? {
|
|
2728
|
+
expectedCount: meshAsset.materialSlots.length,
|
|
2729
|
+
actualCount: materialCount,
|
|
2730
|
+
meshAssetGuid: guid
|
|
2731
|
+
} : {
|
|
2732
|
+
meshAssetGuid: guid,
|
|
2733
|
+
slotIndex: diagnostic.slotIndex,
|
|
2734
|
+
handle: diagnostic.handle ?? 0
|
|
2735
|
+
}
|
|
2736
|
+
}));
|
|
2737
|
+
for (const diagnostic of resolvedBindings.diagnostics) {
|
|
2738
|
+
worldInternal._routeError(
|
|
2739
|
+
new AssetError({
|
|
2740
|
+
code: diagnostic.code,
|
|
2741
|
+
expected: diagnostic.code === "mesh-renderer-material-override-overflow" ? `materials.length <= materialSlots.length (${meshAsset.materialSlots.length})` : `materials[${diagnostic.slotIndex}] resolves to a live MaterialAsset`,
|
|
2742
|
+
hint: ASSET_ERROR_HINTS[diagnostic.code],
|
|
2743
|
+
detail: diagnostic.code === "mesh-renderer-material-override-overflow" ? {
|
|
2744
|
+
expectedCount: meshAsset.materialSlots.length,
|
|
2745
|
+
actualCount: materialCount,
|
|
2746
|
+
meshAssetGuid: guid
|
|
2747
|
+
} : {
|
|
2748
|
+
meshAssetGuid: guid,
|
|
2749
|
+
slotIndex: diagnostic.slotIndex,
|
|
2750
|
+
handle: diagnostic.handle ?? 0
|
|
2751
|
+
}
|
|
2752
|
+
}),
|
|
2753
|
+
{
|
|
2754
|
+
severity: Severity.Warning,
|
|
2755
|
+
systemName: `RenderSystem.extract (${diagnostic.code})`
|
|
2756
|
+
}
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
3376
2759
|
}
|
|
3377
2760
|
}
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
mapSize,
|
|
3382
|
-
nearPlane,
|
|
3383
|
-
farPlane,
|
|
3384
|
-
shadowAtlasLayer: layer,
|
|
3385
|
-
shadowMatrices: packed
|
|
3386
|
-
});
|
|
3387
|
-
}
|
|
3388
|
-
}
|
|
3389
|
-
if (pointShadowSnapshots.length > 0) {
|
|
3390
|
-
const shadowByEntity = /* @__PURE__ */ new Map();
|
|
3391
|
-
for (const ps of pointShadowSnapshots) shadowByEntity.set(ps.entity, ps);
|
|
3392
|
-
for (let i = 0; i < pointSnapshots.length; i++) {
|
|
3393
|
-
const entityId = pointSnapshotEntities[i] ?? 0;
|
|
3394
|
-
const ps = shadowByEntity.get(entityId);
|
|
3395
|
-
if (ps !== void 0) {
|
|
3396
|
-
pointSnapshots[i] = {
|
|
3397
|
-
...pointSnapshots[i],
|
|
3398
|
-
shadowAtlasLayer: ps.shadowAtlasLayer,
|
|
3399
|
-
shadowNear: ps.nearPlane,
|
|
3400
|
-
shadowFar: ps.farPlane
|
|
3401
|
-
};
|
|
2761
|
+
if (materialHandles.length === 0) {
|
|
2762
|
+
materialHandles = [0];
|
|
2763
|
+
materialBindingSources = ["engine-default"];
|
|
3402
2764
|
}
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
directionalCsmConfig,
|
|
3424
|
-
directionalCsmDirection
|
|
3425
|
-
};
|
|
3426
|
-
const skylightQuery = world.query({ read: [Skylight] }).unwrap();
|
|
3427
|
-
let skylight;
|
|
3428
|
-
let skylightCount = 0;
|
|
3429
|
-
for (const row of skylightQuery) {
|
|
3430
|
-
const s = row.get(Skylight);
|
|
3431
|
-
const equirectRaw = s.equirect;
|
|
3432
|
-
const intensity = s.intensity;
|
|
3433
|
-
const colorR = s.color[0] ?? 1;
|
|
3434
|
-
const colorG = s.color[1] ?? 1;
|
|
3435
|
-
const colorB = s.color[2] ?? 1;
|
|
3436
|
-
const rotation = [
|
|
3437
|
-
s.rotation[0] ?? 0,
|
|
3438
|
-
s.rotation[1] ?? 0,
|
|
3439
|
-
s.rotation[2] ?? 0,
|
|
3440
|
-
s.rotation[3] ?? 1
|
|
3441
|
-
];
|
|
3442
|
-
skylightCount += 1;
|
|
3443
|
-
if (skylight === void 0) {
|
|
3444
|
-
skylight = {
|
|
3445
|
-
equirectHandle: equirectRaw !== void 0 ? Math.round(equirectRaw) : 0,
|
|
3446
|
-
color: [colorR, colorG, colorB],
|
|
3447
|
-
intensity,
|
|
3448
|
-
rotation,
|
|
3449
|
-
// w19: winning entity handle for the multi-Skylight once-warn (F-8).
|
|
3450
|
-
entityHandle: row.entity
|
|
3451
|
-
};
|
|
3452
|
-
}
|
|
3453
|
-
}
|
|
3454
|
-
const lightProbeQuery = world.query({ read: [LightProbe, GlobalTransform] }).unwrap();
|
|
3455
|
-
const lightProbes = [];
|
|
3456
|
-
for (const row of lightProbeQuery) {
|
|
3457
|
-
const probe = row.get(LightProbe);
|
|
3458
|
-
const validation = validateLightProbeData({
|
|
3459
|
-
irradiance: probe.irradiance,
|
|
3460
|
-
radius: probe.radius
|
|
3461
|
-
});
|
|
3462
|
-
if (!validation.ok) {
|
|
3463
|
-
worldInternal._routeError(validation.error, {
|
|
3464
|
-
severity: Severity.Error,
|
|
3465
|
-
systemName: "RenderSystem.extract (light-probe)"
|
|
3466
|
-
});
|
|
3467
|
-
continue;
|
|
3468
|
-
}
|
|
3469
|
-
const transform = row.get(GlobalTransform);
|
|
3470
|
-
lightProbes.push({
|
|
3471
|
-
identity: String(row.entity),
|
|
3472
|
-
position: [transform.world[12] ?? 0, transform.world[13] ?? 0, transform.world[14] ?? 0],
|
|
3473
|
-
radius: probe.radius,
|
|
3474
|
-
irradiance: new Float32Array(probe.irradiance),
|
|
3475
|
-
admitted: true
|
|
3476
|
-
});
|
|
3477
|
-
}
|
|
3478
|
-
const skyboxQuery = world.query({ read: [SkyboxBackground] }).unwrap();
|
|
3479
|
-
let skybox;
|
|
3480
|
-
let skyboxCount = 0;
|
|
3481
|
-
for (const row of skyboxQuery) {
|
|
3482
|
-
const s = row.get(SkyboxBackground);
|
|
3483
|
-
const equirectRaw = s.equirect;
|
|
3484
|
-
const modeRaw = s.mode;
|
|
3485
|
-
const rotation = [
|
|
3486
|
-
s.rotation[0] ?? 0,
|
|
3487
|
-
s.rotation[1] ?? 0,
|
|
3488
|
-
s.rotation[2] ?? 0,
|
|
3489
|
-
s.rotation[3] ?? 1
|
|
3490
|
-
];
|
|
3491
|
-
skyboxCount += 1;
|
|
3492
|
-
if (skybox === void 0 && equirectRaw !== void 0) {
|
|
3493
|
-
skybox = {
|
|
3494
|
-
equirectHandle: Math.round(equirectRaw),
|
|
3495
|
-
mode: modeRaw,
|
|
3496
|
-
rotation,
|
|
3497
|
-
// w19: winning entity handle for the multi-SkyboxBackground warn (F-8).
|
|
3498
|
-
entityHandle: row.entity
|
|
3499
|
-
};
|
|
3500
|
-
}
|
|
3501
|
-
}
|
|
3502
|
-
const environmentCandidates = [];
|
|
3503
|
-
const imageEnvironment = skylight?.equirectHandle !== void 0 && skylight.equirectHandle > 0 ? skylight : skybox?.equirectHandle !== void 0 && skybox.equirectHandle > 0 ? skybox : void 0;
|
|
3504
|
-
if (imageEnvironment !== void 0) {
|
|
3505
|
-
environmentCandidates.push({
|
|
3506
|
-
kind: "image",
|
|
3507
|
-
entityKey: imageEnvironment.entityHandle,
|
|
3508
|
-
sourceKey: `equirect:${imageEnvironment.equirectHandle}`
|
|
3509
|
-
});
|
|
3510
|
-
}
|
|
3511
|
-
const atmosphereQuery = world.query({ read: [Atmosphere] }).unwrap();
|
|
3512
|
-
for (const row of atmosphereQuery) {
|
|
3513
|
-
const value = row.get(Atmosphere);
|
|
3514
|
-
const atmosphere = {
|
|
3515
|
-
turbidity: value.turbidity,
|
|
3516
|
-
rayleigh: value.rayleigh,
|
|
3517
|
-
mieCoefficient: value.mieCoefficient,
|
|
3518
|
-
mieDirectionalG: value.mieDirectionalG,
|
|
3519
|
-
sunAngularRadius: value.sunAngularRadius
|
|
3520
|
-
};
|
|
3521
|
-
environmentCandidates.push({
|
|
3522
|
-
kind: "atmosphere",
|
|
3523
|
-
entityKey: row.entity,
|
|
3524
|
-
sourceKey: `atmosphere:${row.entity}`,
|
|
3525
|
-
atmosphere
|
|
3526
|
-
});
|
|
3527
|
-
}
|
|
3528
|
-
const directionalDirection = directional?.direction;
|
|
3529
|
-
const directionalLength = directionalDirection === void 0 ? 0 : Math.hypot(
|
|
3530
|
-
directionalDirection[0] ?? 0,
|
|
3531
|
-
directionalDirection[1] ?? 0,
|
|
3532
|
-
directionalDirection[2] ?? 0
|
|
3533
|
-
);
|
|
3534
|
-
const sun = directional === void 0 || directionalLength <= 1e-6 ? [] : [
|
|
3535
|
-
{
|
|
3536
|
-
entityKey: 0,
|
|
3537
|
-
direction: [
|
|
3538
|
-
-(directionalDirection?.[0] ?? 0) / directionalLength,
|
|
3539
|
-
-(directionalDirection?.[1] ?? 0) / directionalLength,
|
|
3540
|
-
-(directionalDirection?.[2] ?? 0) / directionalLength
|
|
3541
|
-
],
|
|
3542
|
-
color: [
|
|
3543
|
-
directional.color[0] ?? 0,
|
|
3544
|
-
directional.color[1] ?? 0,
|
|
3545
|
-
directional.color[2] ?? 0
|
|
3546
|
-
],
|
|
3547
|
-
intensity: directional.intensity
|
|
3548
|
-
}
|
|
3549
|
-
];
|
|
3550
|
-
const environmentSelection = selectEnvironment({
|
|
3551
|
-
environments: environmentCandidates,
|
|
3552
|
-
fogs: fog === void 0 ? [] : [fog],
|
|
3553
|
-
suns: sun,
|
|
3554
|
-
lane: "direct"
|
|
3555
|
-
});
|
|
3556
|
-
if (!environmentSelection.ok) {
|
|
3557
|
-
routeWorldError(world, environmentSelection.error, {
|
|
3558
|
-
systemName: "RenderSystem.extract (environment-selection)"
|
|
3559
|
-
});
|
|
3560
|
-
throw environmentSelection.error;
|
|
3561
|
-
}
|
|
3562
|
-
const environment = environmentSelection.value;
|
|
3563
|
-
const frustumPlanes = [];
|
|
3564
|
-
const cullingCameras = cullMode === "external" ? context.cullCameras ?? [] : cameras;
|
|
3565
|
-
if (cullMode !== "none") {
|
|
3566
|
-
for (const cam of cullingCameras) {
|
|
3567
|
-
if (cam.projection === "perspective" && (cam.fov <= 0 || cam.aspect <= 0)) {
|
|
3568
|
-
frustumPlanes.push(new Float32Array(0));
|
|
3569
|
-
continue;
|
|
3570
|
-
}
|
|
3571
|
-
if (cam.near >= cam.far) {
|
|
3572
|
-
frustumPlanes.push(new Float32Array(0));
|
|
3573
|
-
continue;
|
|
3574
|
-
}
|
|
3575
|
-
const proj = mat4.create();
|
|
3576
|
-
if (cam.projection === "orthographic") {
|
|
3577
|
-
mat4.orthographic(
|
|
3578
|
-
proj,
|
|
3579
|
-
cam.orthoLeft,
|
|
3580
|
-
cam.orthoRight,
|
|
3581
|
-
cam.orthoBottom,
|
|
3582
|
-
cam.orthoTop,
|
|
3583
|
-
cam.near,
|
|
3584
|
-
cam.far
|
|
3585
|
-
);
|
|
2765
|
+
const handleRaw = materialHandles[0] ?? 0;
|
|
2766
|
+
const cachedMaterial = handleRaw !== 0 && !hasSpriteRegionOverride && !hasSkin ? materialSnapshotCache.get(handleRaw) : void 0;
|
|
2767
|
+
let materialSnap;
|
|
2768
|
+
if (cachedMaterial !== void 0) {
|
|
2769
|
+
materialSnap = cachedMaterial.snapshot;
|
|
2770
|
+
if (isRenderable) {
|
|
2771
|
+
appendMaterialDispatchEntries(
|
|
2772
|
+
pendingDispatch,
|
|
2773
|
+
cachedMaterial.passes,
|
|
2774
|
+
entity,
|
|
2775
|
+
handleRaw,
|
|
2776
|
+
renderables.length,
|
|
2777
|
+
layerVal,
|
|
2778
|
+
materialSnap.paramSnapshot,
|
|
2779
|
+
0,
|
|
2780
|
+
materialSnap.materialShaderId
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
} else if (handleRaw === 0 || assets === void 0 || assets === null) {
|
|
2784
|
+
materialSnap = defaultMaterialSnapshot(handleRaw);
|
|
3586
2785
|
} else {
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
GlobalTransform,
|
|
3609
|
-
MeshFilter,
|
|
3610
|
-
Instances,
|
|
3611
|
-
Skin,
|
|
3612
|
-
Layer,
|
|
3613
|
-
MorphWeights,
|
|
3614
|
-
SpriteRegionOverride,
|
|
3615
|
-
SpriteInstances,
|
|
3616
|
-
Points,
|
|
3617
|
-
Lines,
|
|
3618
|
-
SortKey
|
|
3619
|
-
]
|
|
3620
|
-
}).unwrap();
|
|
3621
|
-
const resolveArchVersion = (entity) => {
|
|
3622
|
-
const values = [
|
|
3623
|
-
worldInternal._getArrayView(entity, Instances, "transforms"),
|
|
3624
|
-
worldInternal._getArrayView(entity, SpriteInstances, "transforms"),
|
|
3625
|
-
worldInternal._getArrayView(entity, SpriteInstances, "regions")
|
|
3626
|
-
];
|
|
3627
|
-
let hash = 2166136261;
|
|
3628
|
-
for (const value of values) {
|
|
3629
|
-
hash = Math.imul(hash ^ (value?.length ?? 0), 16777619) >>> 0;
|
|
3630
|
-
if (value === void 0) continue;
|
|
3631
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
3632
|
-
hash = Math.imul(hash ^ Math.fround(value[index] ?? 0), 16777619) >>> 0;
|
|
3633
|
-
}
|
|
3634
|
-
}
|
|
3635
|
-
return hash;
|
|
3636
|
-
};
|
|
3637
|
-
const flushPendingDispatch = (pending) => {
|
|
3638
|
-
for (const entry of pending) dispatch.push(entry);
|
|
3639
|
-
};
|
|
3640
|
-
for (const row of meshRendererQuery) {
|
|
3641
|
-
const hasTransform = row.has(Transform);
|
|
3642
|
-
const meshFilter = row.get(MeshFilter);
|
|
3643
|
-
const hasInstances = row.has(Instances);
|
|
3644
|
-
const skin = row.get(Skin);
|
|
3645
|
-
const morphWeightsView = worldInternal._getArrayView(row.entity, MorphWeights, "weights");
|
|
3646
|
-
const hasMeshFilter = meshFilter !== void 0;
|
|
3647
|
-
const hasSkin = skin !== void 0;
|
|
3648
|
-
const hasSpriteInstances = row.has(SpriteInstances);
|
|
3649
|
-
const points = row.get(Points);
|
|
3650
|
-
const lines = row.get(Lines);
|
|
3651
|
-
const sortKey = row.get(SortKey)?.value;
|
|
3652
|
-
const pointsLinesComponent = points !== void 0 ? "Points" : lines !== void 0 ? "Lines" : void 0;
|
|
3653
|
-
const isRenderable = hasTransform && hasMeshFilter;
|
|
3654
|
-
const fAssetHandle = meshFilter?.assetHandle;
|
|
3655
|
-
const fLayerValue = row.get(Layer)?.value;
|
|
3656
|
-
const hasSpriteRegionOverride = row.has(SpriteRegionOverride);
|
|
3657
|
-
const skinSkeletonView = skin?.skeleton;
|
|
3658
|
-
let archVersion = 0;
|
|
3659
|
-
if (hasInstances || hasSpriteInstances) {
|
|
3660
|
-
archVersion = resolveArchVersion(row.entity);
|
|
3661
|
-
}
|
|
3662
|
-
{
|
|
3663
|
-
const entity = row.entity;
|
|
3664
|
-
if (isRenderable && visibility?.effective(entity) === "hidden") {
|
|
3665
|
-
explicitlyHidden.add(entity);
|
|
3666
|
-
continue;
|
|
3667
|
-
}
|
|
3668
|
-
const layerVal = fLayerValue ?? 0;
|
|
3669
|
-
const pendingDispatch = [];
|
|
3670
|
-
const materialsView = worldInternal._getArrayView(entity, MeshRenderer, "materials");
|
|
3671
|
-
const materialCount = materialsView?.length ?? 0;
|
|
3672
|
-
let materialHandles = Array.from(materialsView ?? []);
|
|
3673
|
-
let materialBindingSources = materialHandles.map(
|
|
3674
|
-
() => "renderer-override"
|
|
3675
|
-
);
|
|
3676
|
-
let materialBindingDiagnostics = [];
|
|
3677
|
-
let gpuDrivenSubmeshes = [];
|
|
3678
|
-
let gpuDrivenIndexed = false;
|
|
3679
|
-
let gpuDrivenGeometry;
|
|
3680
|
-
const fAssetHandleVal = fAssetHandle;
|
|
3681
|
-
if (fAssetHandleVal !== void 0 && fAssetHandleVal !== 0 && assets !== void 0 && assets !== null) {
|
|
3682
|
-
const meshHandle = toShared(fAssetHandleVal);
|
|
3683
|
-
const meshRes = resolveAssetHandle(world, meshHandle);
|
|
3684
|
-
if (meshRes.ok && meshRes.value.kind === "mesh") {
|
|
3685
|
-
const meshAsset = meshRes.value;
|
|
3686
|
-
const guid = meshRes.value.guid ?? "<no-guid>";
|
|
3687
|
-
gpuDrivenSubmeshes = meshAsset.submeshes;
|
|
3688
|
-
gpuDrivenIndexed = meshAsset.indices !== void 0;
|
|
3689
|
-
const layoutProjection = deriveVertexLayoutProjection(meshAsset.attributes);
|
|
3690
|
-
gpuDrivenGeometry = {
|
|
3691
|
-
identity: `${guid}:${layoutProjection.digest}`,
|
|
3692
|
-
vertexInputs: layoutProjection.attributes.map((attribute) => ({
|
|
3693
|
-
semantic: attribute.key,
|
|
3694
|
-
location: attribute.shaderLocation,
|
|
3695
|
-
format: attribute.format
|
|
3696
|
-
})),
|
|
3697
|
-
topology: meshAsset.submeshes[0]?.topology ?? "triangle-list",
|
|
3698
|
-
indexed: gpuDrivenIndexed
|
|
3699
|
-
};
|
|
3700
|
-
if (!Array.isArray(meshAsset.materialSlots) && world.get(entity, GlyphText).ok) {
|
|
3701
|
-
ensureGlyphMeshMaterialSlots(world, meshHandle);
|
|
3702
|
-
}
|
|
3703
|
-
const resolvedBindings = resolveMeshMaterialBindings(meshAsset, materialsView ?? [], {
|
|
3704
|
-
isValidOverride(handle) {
|
|
3705
|
-
const resolved = resolveAssetHandle(world, toShared(handle));
|
|
3706
|
-
return resolved.ok && resolved.value.kind === "material";
|
|
3707
|
-
},
|
|
3708
|
-
resolveMeshDefault(defaultGuid) {
|
|
3709
|
-
const guidText = AssetGuid.format(defaultGuid);
|
|
3710
|
-
if (assets.lookup(guidText)?.kind !== "material") return void 0;
|
|
3711
|
-
return internSharedRefFromGuid(world, assets, guidText, "MaterialAsset");
|
|
3712
|
-
}
|
|
3713
|
-
});
|
|
3714
|
-
if (!resolvedBindings.ok) {
|
|
3715
|
-
if (resolvedBindings.code === "mesh-material-slots-missing") {
|
|
3716
|
-
worldInternal._routeError(
|
|
3717
|
-
new AssetError({
|
|
3718
|
-
code: "load-failed",
|
|
3719
|
-
expected: "every MeshAsset producer supplies materialSlots[]",
|
|
3720
|
-
hint: `fix the MeshAsset producer; renderer inheritance never guesses slot topology (mesh=${guid}, entity=${entity}, vertices=${meshAsset.vertices.length}, indices=${meshAsset.indices?.length ?? 0})`,
|
|
3721
|
-
detail: {
|
|
3722
|
-
referencedByGuid: guid,
|
|
3723
|
-
referencedByKind: "mesh",
|
|
3724
|
-
subAssetGuid: "<material-slots-missing>",
|
|
3725
|
-
sourceField: { fieldName: "materialSlots" }
|
|
3726
|
-
}
|
|
3727
|
-
}),
|
|
3728
|
-
{
|
|
3729
|
-
severity: Severity.Error,
|
|
3730
|
-
systemName: "RenderSystem.extract (mesh-material-slots-missing)"
|
|
3731
|
-
}
|
|
3732
|
-
);
|
|
3733
|
-
continue;
|
|
3734
|
-
}
|
|
3735
|
-
const materialGuid = AssetGuid.format(resolvedBindings.defaultMaterial);
|
|
3736
|
-
worldInternal._routeError(
|
|
3737
|
-
new AssetError({
|
|
3738
|
-
code: "load-failed",
|
|
3739
|
-
expected: `MeshAsset materialSlots[${resolvedBindings.slotIndex}] default ${materialGuid} is ready and a MaterialAsset`,
|
|
3740
|
-
hint: `loadByGuid(meshGuid) must recursively load the declared default material; mesh=${guid}, slot=${resolvedBindings.slotIndex}, material=${materialGuid}`,
|
|
3741
|
-
detail: {
|
|
3742
|
-
referencedByGuid: guid,
|
|
3743
|
-
referencedByKind: "mesh",
|
|
3744
|
-
subAssetGuid: materialGuid,
|
|
3745
|
-
sourceField: {
|
|
3746
|
-
fieldName: "materialSlots",
|
|
3747
|
-
arrayIndex: resolvedBindings.slotIndex
|
|
3748
|
-
}
|
|
3749
|
-
}
|
|
3750
|
-
}),
|
|
3751
|
-
{
|
|
3752
|
-
severity: Severity.Error,
|
|
3753
|
-
systemName: "RenderSystem.extract (mesh-default-not-ready)"
|
|
3754
|
-
}
|
|
3755
|
-
);
|
|
3756
|
-
continue;
|
|
3757
|
-
}
|
|
3758
|
-
materialHandles = resolvedBindings.bindings.map((binding) => binding.handle);
|
|
3759
|
-
materialBindingSources = resolvedBindings.bindings.map((binding) => binding.source);
|
|
3760
|
-
materialBindingDiagnostics = resolvedBindings.diagnostics.map((diagnostic) => ({
|
|
3761
|
-
...diagnostic,
|
|
3762
|
-
detail: diagnostic.code === "mesh-renderer-material-override-overflow" ? {
|
|
3763
|
-
expectedCount: meshAsset.materialSlots.length,
|
|
3764
|
-
actualCount: materialCount,
|
|
3765
|
-
meshAssetGuid: guid
|
|
3766
|
-
} : {
|
|
3767
|
-
meshAssetGuid: guid,
|
|
3768
|
-
slotIndex: diagnostic.slotIndex,
|
|
3769
|
-
handle: diagnostic.handle ?? 0
|
|
3770
|
-
}
|
|
3771
|
-
}));
|
|
3772
|
-
for (const diagnostic of resolvedBindings.diagnostics) {
|
|
3773
|
-
worldInternal._routeError(
|
|
3774
|
-
new AssetError({
|
|
3775
|
-
code: diagnostic.code,
|
|
3776
|
-
expected: diagnostic.code === "mesh-renderer-material-override-overflow" ? `materials.length <= materialSlots.length (${meshAsset.materialSlots.length})` : `materials[${diagnostic.slotIndex}] resolves to a live MaterialAsset`,
|
|
3777
|
-
hint: ASSET_ERROR_HINTS[diagnostic.code],
|
|
3778
|
-
detail: diagnostic.code === "mesh-renderer-material-override-overflow" ? {
|
|
3779
|
-
expectedCount: meshAsset.materialSlots.length,
|
|
3780
|
-
actualCount: materialCount,
|
|
3781
|
-
meshAssetGuid: guid
|
|
3782
|
-
} : {
|
|
3783
|
-
meshAssetGuid: guid,
|
|
3784
|
-
slotIndex: diagnostic.slotIndex,
|
|
3785
|
-
handle: diagnostic.handle ?? 0
|
|
3786
|
-
}
|
|
3787
|
-
}),
|
|
3788
|
-
{
|
|
3789
|
-
severity: Severity.Warning,
|
|
3790
|
-
systemName: `RenderSystem.extract (${diagnostic.code})`
|
|
3791
|
-
}
|
|
3792
|
-
);
|
|
3793
|
-
}
|
|
3794
|
-
}
|
|
3795
|
-
}
|
|
3796
|
-
if (materialHandles.length === 0) {
|
|
3797
|
-
materialHandles = [0];
|
|
3798
|
-
materialBindingSources = ["engine-default"];
|
|
3799
|
-
}
|
|
3800
|
-
const handleRaw = materialHandles[0] ?? 0;
|
|
3801
|
-
const cachedMaterial = handleRaw !== 0 && !hasSpriteRegionOverride && !hasSkin ? materialSnapshotCache.get(handleRaw) : void 0;
|
|
3802
|
-
let materialSnap;
|
|
3803
|
-
if (cachedMaterial !== void 0) {
|
|
3804
|
-
materialSnap = cachedMaterial.snapshot;
|
|
3805
|
-
if (isRenderable) {
|
|
3806
|
-
appendMaterialDispatchEntries(
|
|
3807
|
-
pendingDispatch,
|
|
3808
|
-
cachedMaterial.passes,
|
|
3809
|
-
entity,
|
|
3810
|
-
handleRaw,
|
|
3811
|
-
renderables.length,
|
|
3812
|
-
layerVal,
|
|
3813
|
-
materialSnap.paramSnapshot
|
|
3814
|
-
);
|
|
3815
|
-
}
|
|
3816
|
-
} else if (handleRaw === 0 || assets === void 0 || assets === null) {
|
|
3817
|
-
materialSnap = defaultMaterialSnapshot(handleRaw);
|
|
3818
|
-
} else {
|
|
3819
|
-
const tagged = toShared(handleRaw);
|
|
3820
|
-
const stablePersistentCached = !hasSpriteRegionOverride && !hasSkin ? readStablePersistentMaterialSnapshot(
|
|
3821
|
-
persistentMaterialSnapshotCache,
|
|
3822
|
-
handleRaw,
|
|
3823
|
-
assets
|
|
3824
|
-
) : void 0;
|
|
3825
|
-
if (stablePersistentCached !== void 0) {
|
|
3826
|
-
materialSnapshotCache.set(handleRaw, stablePersistentCached);
|
|
3827
|
-
materialSnap = stablePersistentCached.snapshot;
|
|
3828
|
-
if (isRenderable) {
|
|
3829
|
-
appendMaterialDispatchEntries(
|
|
3830
|
-
pendingDispatch,
|
|
3831
|
-
stablePersistentCached.passes,
|
|
3832
|
-
entity,
|
|
3833
|
-
handleRaw,
|
|
3834
|
-
renderables.length,
|
|
3835
|
-
layerVal,
|
|
3836
|
-
materialSnap.paramSnapshot
|
|
3837
|
-
);
|
|
2786
|
+
const tagged = toShared(handleRaw);
|
|
2787
|
+
const stablePersistentCached = !hasSpriteRegionOverride && !hasSkin ? readStablePersistentMaterialSnapshot(
|
|
2788
|
+
persistentMaterialSnapshotCache,
|
|
2789
|
+
handleRaw,
|
|
2790
|
+
assets
|
|
2791
|
+
) : void 0;
|
|
2792
|
+
if (stablePersistentCached !== void 0) {
|
|
2793
|
+
materialSnapshotCache.set(handleRaw, stablePersistentCached);
|
|
2794
|
+
materialSnap = stablePersistentCached.snapshot;
|
|
2795
|
+
if (isRenderable) {
|
|
2796
|
+
appendMaterialDispatchEntries(
|
|
2797
|
+
pendingDispatch,
|
|
2798
|
+
stablePersistentCached.passes,
|
|
2799
|
+
entity,
|
|
2800
|
+
handleRaw,
|
|
2801
|
+
renderables.length,
|
|
2802
|
+
layerVal,
|
|
2803
|
+
materialSnap.paramSnapshot,
|
|
2804
|
+
0,
|
|
2805
|
+
materialSnap.materialShaderId
|
|
2806
|
+
);
|
|
3838
2807
|
}
|
|
3839
2808
|
} else {
|
|
3840
2809
|
const res = resolveAssetHandle(world, tagged);
|
|
@@ -3887,7 +2856,7 @@ function extractFrame(world, context) {
|
|
|
3887
2856
|
}
|
|
3888
2857
|
const resolved = resolvedResult.value;
|
|
3889
2858
|
const allPasses = resolved.passes;
|
|
3890
|
-
const firstPassShader =
|
|
2859
|
+
const firstPassShader = runtimeMaterialShaderIdForMaterial(asset, allPasses, assets);
|
|
3891
2860
|
const pv = materialValuesToLinearRuntime(
|
|
3892
2861
|
resolved.values,
|
|
3893
2862
|
materialColorParameterSchema(resolved.parameters ?? [], firstPassShader, assets),
|
|
@@ -3901,9 +2870,7 @@ function extractFrame(world, context) {
|
|
|
3901
2870
|
);
|
|
3902
2871
|
const metallicPv = typeof pv.metallic === "number" ? pv.metallic : 0;
|
|
3903
2872
|
const roughnessPv = typeof pv.roughness === "number" ? pv.roughness : 0.5;
|
|
3904
|
-
const
|
|
3905
|
-
const clearcoatRoughnessPv = typeof pv.clearcoatRoughness === "number" ? pv.clearcoatRoughness : 0.5;
|
|
3906
|
-
const specularTintPv = pv.specularTint;
|
|
2873
|
+
const specularColorPv = pv.specularColor;
|
|
3907
2874
|
const normalScalePv = materialNormalScale(pv);
|
|
3908
2875
|
const paramSnap = {};
|
|
3909
2876
|
for (const [k, v] of Object.entries(pv)) {
|
|
@@ -3919,7 +2886,7 @@ function extractFrame(world, context) {
|
|
|
3919
2886
|
);
|
|
3920
2887
|
{
|
|
3921
2888
|
const hasSkinSkel = hasSkin && skinSkeletonView !== void 0 && skinSkeletonView !== void 0 && skinSkeletonView !== 0;
|
|
3922
|
-
const isPbrSkinMaterial = firstPassShader
|
|
2889
|
+
const isPbrSkinMaterial = isStandardPbrSkinMaterialShader(firstPassShader);
|
|
3923
2890
|
if (hasSkinSkel && !isPbrSkinMaterial) {
|
|
3924
2891
|
worldInternal._routeError(new SkinMaterialMismatchError(entity, firstPassShader), {
|
|
3925
2892
|
severity: Severity.Error,
|
|
@@ -4068,13 +3035,11 @@ function extractFrame(world, context) {
|
|
|
4068
3035
|
baseColor,
|
|
4069
3036
|
metallic: metallicPv,
|
|
4070
3037
|
roughness: roughnessPv,
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
specularTintPv[1] ?? 1,
|
|
4077
|
-
specularTintPv[2] ?? 1
|
|
3038
|
+
...specularColorPv !== void 0 && {
|
|
3039
|
+
specularColor: [
|
|
3040
|
+
specularColorPv[0] ?? 1,
|
|
3041
|
+
specularColorPv[1] ?? 1,
|
|
3042
|
+
specularColorPv[2] ?? 1
|
|
4078
3043
|
]
|
|
4079
3044
|
},
|
|
4080
3045
|
normalScale: normalScalePv,
|
|
@@ -4131,7 +3096,9 @@ function extractFrame(world, context) {
|
|
|
4131
3096
|
handleRaw,
|
|
4132
3097
|
renderables.length,
|
|
4133
3098
|
layerVal,
|
|
4134
|
-
paramSnap
|
|
3099
|
+
paramSnap,
|
|
3100
|
+
0,
|
|
3101
|
+
firstPassShader
|
|
4135
3102
|
);
|
|
4136
3103
|
}
|
|
4137
3104
|
}
|
|
@@ -4228,7 +3195,10 @@ function extractFrame(world, context) {
|
|
|
4228
3195
|
ibms[jIdx] = ibmFlat.subarray(jIdx * 16, jIdx * 16 + 16);
|
|
4229
3196
|
}
|
|
4230
3197
|
if (skinPaletteAllocator !== null) {
|
|
4231
|
-
const slice = skinPaletteAllocator.
|
|
3198
|
+
const slice = typeof skinPaletteAllocator.allocateSliceFor === "function" ? skinPaletteAllocator.allocateSliceFor(
|
|
3199
|
+
`${world.identity}:${entity}`,
|
|
3200
|
+
skeleton.jointCount
|
|
3201
|
+
) : skinPaletteAllocator.allocateSlice(skeleton.jointCount);
|
|
4232
3202
|
skinPaletteAllocator.writeJointPalette(slice, ibms, jointWorlds);
|
|
4233
3203
|
skinSlice = {
|
|
4234
3204
|
jointCount: slice.jointCount,
|
|
@@ -4274,7 +3244,9 @@ function extractFrame(world, context) {
|
|
|
4274
3244
|
subHandle,
|
|
4275
3245
|
renderables.length,
|
|
4276
3246
|
layerVal,
|
|
4277
|
-
materialsArr[mi]?.paramSnapshot
|
|
3247
|
+
materialsArr[mi]?.paramSnapshot,
|
|
3248
|
+
0,
|
|
3249
|
+
materialsArr[mi]?.materialShaderId
|
|
4278
3250
|
);
|
|
4279
3251
|
}
|
|
4280
3252
|
}
|
|
@@ -4372,31 +3344,28 @@ function extractFrame(world, context) {
|
|
|
4372
3344
|
};
|
|
4373
3345
|
let instancesSnap;
|
|
4374
3346
|
if (hasInstances) {
|
|
4375
|
-
const transforms = worldInternal._getArrayView(entity, Instances, "transforms");
|
|
4376
|
-
if (transforms
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
cacheKey: entity,
|
|
4381
|
-
archVersion
|
|
4382
|
-
};
|
|
4383
|
-
} else {
|
|
4384
|
-
const actualLength = transforms.length;
|
|
4385
|
-
if (actualLength % 16 !== 0) {
|
|
4386
|
-
worldInternal._routeError(new InstanceTransformsStrideMismatchError(actualLength), {
|
|
3347
|
+
const transforms = worldInternal._getArrayView(entity, Instances, "transforms") ?? new Float32Array();
|
|
3348
|
+
if (transforms.length % 16 !== 0) {
|
|
3349
|
+
worldInternal._routeError(
|
|
3350
|
+
new InstanceTransformsStrideMismatchError(transforms.length),
|
|
3351
|
+
{
|
|
4387
3352
|
severity: Severity.Error,
|
|
4388
3353
|
systemName: "RenderSystem.extract (Instances stride)"
|
|
4389
|
-
}
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
const snapshotCopy = new Float32Array(transforms);
|
|
4393
|
-
instancesSnap = {
|
|
4394
|
-
transforms: snapshotCopy,
|
|
4395
|
-
instanceCount: actualLength / 16,
|
|
4396
|
-
cacheKey: entity,
|
|
4397
|
-
archVersion
|
|
4398
|
-
};
|
|
3354
|
+
}
|
|
3355
|
+
);
|
|
3356
|
+
continue;
|
|
4399
3357
|
}
|
|
3358
|
+
const projected = instanceCollections?.project(world, entity, transforms);
|
|
3359
|
+
instancesSnap = {
|
|
3360
|
+
transforms: projected?.transforms ?? new Float32Array(transforms),
|
|
3361
|
+
instanceCount: transforms.length / 16,
|
|
3362
|
+
cacheKey: entity,
|
|
3363
|
+
archVersion: projected === void 0 ? fingerprintNumericArray(transforms) : 0,
|
|
3364
|
+
...projected === void 0 ? {} : {
|
|
3365
|
+
collectionId: projected.collectionId,
|
|
3366
|
+
revision: projected.revision
|
|
3367
|
+
}
|
|
3368
|
+
};
|
|
4400
3369
|
}
|
|
4401
3370
|
const baseRenderable = {
|
|
4402
3371
|
assetHandle: Math.round(fAssetHandle ?? 0),
|
|
@@ -4410,7 +3379,9 @@ function extractFrame(world, context) {
|
|
|
4410
3379
|
materialBindingDiagnostics,
|
|
4411
3380
|
worldId: 0,
|
|
4412
3381
|
entityKey: entity,
|
|
3382
|
+
...authorVisible ? {} : { authorVisible: false },
|
|
4413
3383
|
...skinSlice !== void 0 ? { skin: skinSlice } : {},
|
|
3384
|
+
...skin?.joints === void 0 ? {} : { skinJointEntities: Array.from(skin.joints, (joint) => Number(joint)) },
|
|
4414
3385
|
...morph !== void 0 ? { morph } : {},
|
|
4415
3386
|
...instancesSnap !== void 0 ? { instances: instancesSnap } : {},
|
|
4416
3387
|
...spriteInstancesSnap !== void 0 ? { spriteInstances: spriteInstancesSnap } : {},
|
|
@@ -4486,60 +3457,1139 @@ function extractFrame(world, context) {
|
|
|
4486
3457
|
}
|
|
4487
3458
|
}
|
|
4488
3459
|
}
|
|
4489
|
-
dispatch = sortDispatchByQueue(dispatch);
|
|
4490
|
-
const postProcessParams = /* @__PURE__ */ new Map();
|
|
4491
|
-
const postProcessParamsQuery = world.query({ with: [PostProcessParams] }).unwrap();
|
|
4492
|
-
for (const row of postProcessParamsQuery) {
|
|
3460
|
+
dispatch = sortDispatchByQueue(dispatch);
|
|
3461
|
+
const postProcessParams = /* @__PURE__ */ new Map();
|
|
3462
|
+
const postProcessParamsQuery = world.query({ with: [PostProcessParams] }).unwrap();
|
|
3463
|
+
for (const row of postProcessParamsQuery) {
|
|
3464
|
+
const entity = row.entity;
|
|
3465
|
+
const read = world.get(entity, PostProcessParams);
|
|
3466
|
+
if (!read.ok) continue;
|
|
3467
|
+
postProcessParams.set(read.value.shader, read.value.data);
|
|
3468
|
+
}
|
|
3469
|
+
const tonemapCamera = cameras[0];
|
|
3470
|
+
if (tonemapCamera !== void 0) {
|
|
3471
|
+
postProcessParams.set(STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, tonemapParams(tonemapCamera));
|
|
3472
|
+
}
|
|
3473
|
+
return {
|
|
3474
|
+
cameras,
|
|
3475
|
+
auxiliaryCameras,
|
|
3476
|
+
cubeCameras,
|
|
3477
|
+
reflectionProbes,
|
|
3478
|
+
lights,
|
|
3479
|
+
environment,
|
|
3480
|
+
environmentReady: true,
|
|
3481
|
+
...volumetricFog === void 0 ? {} : { volumetricFog },
|
|
3482
|
+
renderables,
|
|
3483
|
+
dispatch,
|
|
3484
|
+
skylight,
|
|
3485
|
+
skylightCount,
|
|
3486
|
+
lightProbes,
|
|
3487
|
+
skybox,
|
|
3488
|
+
skyboxCount,
|
|
3489
|
+
fog,
|
|
3490
|
+
...fogFailure === void 0 ? {} : { fogFailure },
|
|
3491
|
+
frustumStats: { culled: frustumCulled, total: frustumTotal },
|
|
3492
|
+
visibilityStats: { explicitlyHidden: explicitlyHidden.size },
|
|
3493
|
+
postProcessParams,
|
|
3494
|
+
visibilitySnapshots: [context.visibility],
|
|
3495
|
+
featureVisibilitySnapshots: [{ world, snapshot: context.visibility }],
|
|
3496
|
+
hiddenEntityReports: [...explicitlyHidden].map((entity) => ({ world, entity }))
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
function defaultMaterialSnapshot(materialHandle = 0) {
|
|
3500
|
+
return {
|
|
3501
|
+
baseColor: vec3.create(0.5, 0.5, 0.5),
|
|
3502
|
+
metallic: 0,
|
|
3503
|
+
roughness: 1,
|
|
3504
|
+
materialHandle
|
|
3505
|
+
};
|
|
3506
|
+
}
|
|
3507
|
+
function identityProjection() {
|
|
3508
|
+
const projection = new Float32Array(16);
|
|
3509
|
+
projection[0] = 1;
|
|
3510
|
+
projection[5] = 1;
|
|
3511
|
+
projection[10] = 1;
|
|
3512
|
+
projection[15] = 1;
|
|
3513
|
+
return projection;
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3516
|
+
// src/render-system-extract.ts
|
|
3517
|
+
function buildRectAreaWorldFrame(input) {
|
|
3518
|
+
const center = vec3.create(input.center[0] ?? 0, input.center[1] ?? 0, input.center[2] ?? 0);
|
|
3519
|
+
const axisX = vec3.normalize(
|
|
3520
|
+
vec3.create(),
|
|
3521
|
+
vec3.create(input.axisX[0] ?? 0, input.axisX[1] ?? 0, input.axisX[2] ?? 0)
|
|
3522
|
+
);
|
|
3523
|
+
const axisY = vec3.normalize(
|
|
3524
|
+
vec3.create(),
|
|
3525
|
+
vec3.create(input.axisY[0] ?? 0, input.axisY[1] ?? 0, input.axisY[2] ?? 0)
|
|
3526
|
+
);
|
|
3527
|
+
const normal = vec3.normalize(vec3.create(), vec3.cross(vec3.create(), axisX, axisY));
|
|
3528
|
+
normal[0] = normal[0] === 0 ? 0 : normal[0] ?? 0;
|
|
3529
|
+
normal[1] = normal[1] === 0 ? 0 : normal[1] ?? 0;
|
|
3530
|
+
normal[2] = normal[2] === 0 ? 0 : normal[2] ?? 0;
|
|
3531
|
+
return {
|
|
3532
|
+
center,
|
|
3533
|
+
axisX,
|
|
3534
|
+
axisY,
|
|
3535
|
+
normal,
|
|
3536
|
+
halfWidth: Math.max(0, input.width * 0.5),
|
|
3537
|
+
halfHeight: Math.max(0, input.height * 0.5)
|
|
3538
|
+
};
|
|
3539
|
+
}
|
|
3540
|
+
function rectAreaFacesPoint(frame, point) {
|
|
3541
|
+
const toPoint = vec3.create(
|
|
3542
|
+
(point[0] ?? 0) - (frame.center[0] ?? 0),
|
|
3543
|
+
(point[1] ?? 0) - (frame.center[1] ?? 0),
|
|
3544
|
+
(point[2] ?? 0) - (frame.center[2] ?? 0)
|
|
3545
|
+
);
|
|
3546
|
+
return vec3.dot(frame.normal, toPoint) > 0;
|
|
3547
|
+
}
|
|
3548
|
+
function sortDispatchByQueue(entries) {
|
|
3549
|
+
return entries.slice().sort((a, b) => a.queue - b.queue);
|
|
3550
|
+
}
|
|
3551
|
+
var DEFAULT_FORWARD_PASS = {
|
|
3552
|
+
name: "forward",
|
|
3553
|
+
program: { module: "forgeax::default-unlit", vertexEntry: "vs_main", fragmentEntry: "fs_main" },
|
|
3554
|
+
renderState: { tags: { LightMode: "Forward" }, queue: 2e3 }
|
|
3555
|
+
};
|
|
3556
|
+
function appendMaterialDispatchEntries(pendingDispatch, passes, entity, materialHandle, renderableIndex, layer, paramSnapshot, passIndexOffset = 0, materialShaderIdOverride) {
|
|
3557
|
+
const matchedPasses = selectPasses(passes, {});
|
|
3558
|
+
for (let pIdx = 0; pIdx < matchedPasses.length; pIdx++) {
|
|
3559
|
+
const pass = matchedPasses[pIdx];
|
|
3560
|
+
if (pass === void 0) continue;
|
|
3561
|
+
const passState = pass.renderState ?? {};
|
|
3562
|
+
const authoredShaderId = runtimeMaterialShaderId(pass.program.module, pass.name);
|
|
3563
|
+
const dispatchShaderId = authoredShaderId === "forgeax::default-shadow-caster" ? authoredShaderId : materialShaderIdOverride ?? authoredShaderId;
|
|
3564
|
+
pendingDispatch.push({
|
|
3565
|
+
entityIndex: entity,
|
|
3566
|
+
materialHandle,
|
|
3567
|
+
renderableIndex,
|
|
3568
|
+
passIndex: passIndexOffset + pIdx,
|
|
3569
|
+
queue: passState.queue ?? 2e3,
|
|
3570
|
+
layer,
|
|
3571
|
+
tags: passState.tags ?? {},
|
|
3572
|
+
renderState: pipelineRenderState(passState),
|
|
3573
|
+
// Material module identity is already closed in the cooked program.
|
|
3574
|
+
// It must never become a draw-time define map.
|
|
3575
|
+
defines: void 0,
|
|
3576
|
+
vertexEntry: pass.program.vertexEntry,
|
|
3577
|
+
fragmentEntry: pass.program.fragmentEntry,
|
|
3578
|
+
// A cooked Standard publication supplies one specialization key for its
|
|
3579
|
+
// forward/deferred artifact, but its ShadowCaster pass still owns the
|
|
3580
|
+
// engine depth-only shader. Keep the pass-local canonical identity so a
|
|
3581
|
+
// specialized Standard source (which only declares fs_main/fs_gbuffer)
|
|
3582
|
+
// is never asked to build an fs_shadow pipeline. Authored non-Standard
|
|
3583
|
+
// ShadowCaster modules retain the publication override and continue to
|
|
3584
|
+
// use their producer-owned source.
|
|
3585
|
+
materialShaderId: dispatchShaderId,
|
|
3586
|
+
paramSnapshot,
|
|
3587
|
+
...passState.stencilReference !== void 0 && {
|
|
3588
|
+
stencilReference: passState.stencilReference
|
|
3589
|
+
}
|
|
3590
|
+
});
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
function selectCameraTargetViews(candidates, options) {
|
|
3594
|
+
const display = candidates.find(
|
|
3595
|
+
(candidate) => candidate.entityKey === options.displayEntityKey && candidate.target === void 0
|
|
3596
|
+
);
|
|
3597
|
+
const rejected = [];
|
|
3598
|
+
const ordered = candidates.filter((candidate) => candidate.target !== void 0).sort((left, right) => left.worldId - right.worldId || left.entityKey - right.entityKey);
|
|
3599
|
+
const auxiliary = [];
|
|
3600
|
+
const seenTargets = /* @__PURE__ */ new Set();
|
|
3601
|
+
for (const candidate of ordered) {
|
|
3602
|
+
const duplicate = candidate.target !== void 0 && seenTargets.has(candidate.target);
|
|
3603
|
+
if (candidate.target !== void 0) seenTargets.add(candidate.target);
|
|
3604
|
+
if (candidate.entityKey === options.displayEntityKey) {
|
|
3605
|
+
rejected.push({ entityKey: candidate.entityKey, reason: "display-target" });
|
|
3606
|
+
continue;
|
|
3607
|
+
}
|
|
3608
|
+
if (candidate.target === void 0 || duplicate) {
|
|
3609
|
+
rejected.push({ entityKey: candidate.entityKey, reason: "duplicate-target" });
|
|
3610
|
+
continue;
|
|
3611
|
+
}
|
|
3612
|
+
if (auxiliary.length >= Math.max(0, options.budget)) {
|
|
3613
|
+
rejected.push({ entityKey: candidate.entityKey, reason: "budget" });
|
|
3614
|
+
continue;
|
|
3615
|
+
}
|
|
3616
|
+
auxiliary.push(candidate);
|
|
3617
|
+
}
|
|
3618
|
+
return {
|
|
3619
|
+
display,
|
|
3620
|
+
auxiliary: Object.freeze(auxiliary),
|
|
3621
|
+
rejected: Object.freeze(rejected)
|
|
3622
|
+
};
|
|
3623
|
+
}
|
|
3624
|
+
var Severity = Object.freeze({ Error: "error", Warning: "warning" });
|
|
3625
|
+
function createWorldInternalView(world) {
|
|
3626
|
+
return {
|
|
3627
|
+
_routeError(error, ctx) {
|
|
3628
|
+
routeWorldError(world, error, { systemName: ctx.systemName });
|
|
3629
|
+
},
|
|
3630
|
+
_getArrayView(entity, component, fieldName) {
|
|
3631
|
+
return readRenderArrayView(world, entity, component, fieldName);
|
|
3632
|
+
}
|
|
3633
|
+
};
|
|
3634
|
+
}
|
|
3635
|
+
function resolveCameraTarget(world, raw) {
|
|
3636
|
+
if (raw === void 0 || raw <= 0) return void 0;
|
|
3637
|
+
const resolved = world.sharedRefs.resolve(
|
|
3638
|
+
toShared(Math.round(raw))
|
|
3639
|
+
);
|
|
3640
|
+
return resolved.ok ? resolved.value : void 0;
|
|
3641
|
+
}
|
|
3642
|
+
var BUILTIN_USER_REGION_TEXTURE_FIELDS = [
|
|
3643
|
+
"baseColorTexture",
|
|
3644
|
+
"metallicRoughnessTexture",
|
|
3645
|
+
"normalTexture",
|
|
3646
|
+
"specularColorTexture",
|
|
3647
|
+
"emissiveTexture",
|
|
3648
|
+
"occlusionTexture",
|
|
3649
|
+
"transmissionTexture",
|
|
3650
|
+
"thicknessTexture"
|
|
3651
|
+
];
|
|
3652
|
+
var BUILTIN_USER_REGION_TEXTURE_FIELD_SET = new Set(BUILTIN_USER_REGION_TEXTURE_FIELDS);
|
|
3653
|
+
var BUILTIN_BASE_COLOR_TEXTURE_FIELD_SET = /* @__PURE__ */ new Set(["baseColorTexture"]);
|
|
3654
|
+
function materialTextureFields(shaderId, fields) {
|
|
3655
|
+
if (fields !== void 0 && fields.size > 0) return fields;
|
|
3656
|
+
if (shaderId === "forgeax::default-standard-pbr" || shaderId === "forgeax::default-standard-pbr-skin" || shaderId === "forgeax::pbr-skin") {
|
|
3657
|
+
return BUILTIN_USER_REGION_TEXTURE_FIELD_SET;
|
|
3658
|
+
}
|
|
3659
|
+
if (shaderId === "forgeax::default-unlit" || shaderId === "forgeax::sprite" || shaderId === "forgeax::sprite-lit") {
|
|
3660
|
+
return BUILTIN_BASE_COLOR_TEXTURE_FIELD_SET;
|
|
3661
|
+
}
|
|
3662
|
+
return fields;
|
|
3663
|
+
}
|
|
3664
|
+
function runtimeMaterialShaderId(module, passName) {
|
|
3665
|
+
if (passName === "shadow-caster" && (module === "forgeax_material::standard" || module === "forgeax_material::unlit" || module === "forgeax::default-standard-pbr" || module === "forgeax::default-unlit")) {
|
|
3666
|
+
return "forgeax::default-shadow-caster";
|
|
3667
|
+
}
|
|
3668
|
+
switch (module) {
|
|
3669
|
+
case "forgeax_material::standard":
|
|
3670
|
+
return "forgeax::default-standard-pbr";
|
|
3671
|
+
case "forgeax_material::unlit":
|
|
3672
|
+
return "forgeax::default-unlit";
|
|
3673
|
+
case "forgeax_material::sprite":
|
|
3674
|
+
return "forgeax::sprite";
|
|
3675
|
+
case "forgeax_material::sprite-lit":
|
|
3676
|
+
return "forgeax::sprite-lit";
|
|
3677
|
+
default:
|
|
3678
|
+
return module;
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
function runtimeMaterialShaderIdForMaterial(material, passes, assets) {
|
|
3682
|
+
const authored = runtimeMaterialShaderId(passes[0]?.program.module, passes[0]?.name);
|
|
3683
|
+
return assets.getMaterialProjectionForPayload(material)?.specializationKey ?? authored;
|
|
3684
|
+
}
|
|
3685
|
+
function pipelineRenderState(renderState) {
|
|
3686
|
+
if (renderState === void 0) return void 0;
|
|
3687
|
+
const {
|
|
3688
|
+
cullMode,
|
|
3689
|
+
depthCompare,
|
|
3690
|
+
depthWriteEnabled,
|
|
3691
|
+
blend,
|
|
3692
|
+
alphaToCoverageEnabled,
|
|
3693
|
+
stencil,
|
|
3694
|
+
stencilReadMask,
|
|
3695
|
+
stencilWriteMask,
|
|
3696
|
+
frontFace
|
|
3697
|
+
} = renderState;
|
|
3698
|
+
if (cullMode === void 0 && depthCompare === void 0 && depthWriteEnabled === void 0 && blend === void 0 && alphaToCoverageEnabled === void 0 && stencil === void 0 && stencilReadMask === void 0 && stencilWriteMask === void 0 && frontFace === void 0) {
|
|
3699
|
+
return void 0;
|
|
3700
|
+
}
|
|
3701
|
+
return {
|
|
3702
|
+
...cullMode !== void 0 && { cullMode },
|
|
3703
|
+
...depthCompare !== void 0 && { depthCompare },
|
|
3704
|
+
...depthWriteEnabled !== void 0 && { depthWriteEnabled },
|
|
3705
|
+
...blend !== void 0 && { blend },
|
|
3706
|
+
...alphaToCoverageEnabled !== void 0 && { alphaToCoverageEnabled },
|
|
3707
|
+
...stencil !== void 0 && { stencil },
|
|
3708
|
+
...stencilReadMask !== void 0 && { stencilReadMask },
|
|
3709
|
+
...stencilWriteMask !== void 0 && { stencilWriteMask },
|
|
3710
|
+
...frontFace !== void 0 && { frontFace }
|
|
3711
|
+
};
|
|
3712
|
+
}
|
|
3713
|
+
var guidHandleInternByWorld = /* @__PURE__ */ new WeakMap();
|
|
3714
|
+
function internSharedRefFromGuid(world, assetsRef, guid, brand) {
|
|
3715
|
+
let perWorld = guidHandleInternByWorld.get(world);
|
|
3716
|
+
if (perWorld === void 0) {
|
|
3717
|
+
perWorld = /* @__PURE__ */ new Map();
|
|
3718
|
+
guidHandleInternByWorld.set(world, perWorld);
|
|
3719
|
+
}
|
|
3720
|
+
const key = `${guid.toLowerCase()}\0${brand}`;
|
|
3721
|
+
const cached = perWorld.get(key);
|
|
3722
|
+
const payload = assetsRef.lookup(guid);
|
|
3723
|
+
if (cached !== void 0 && cached.payload === payload) {
|
|
3724
|
+
const cachedHandle = toShared(cached.handle);
|
|
3725
|
+
if (world.sharedRefs.resolve(cachedHandle).ok) return cachedHandle;
|
|
3726
|
+
}
|
|
3727
|
+
if (cached !== void 0) {
|
|
3728
|
+
world.sharedRefs.release(toShared(cached.handle));
|
|
3729
|
+
perWorld.delete(key);
|
|
3730
|
+
}
|
|
3731
|
+
if (payload === void 0) return void 0;
|
|
3732
|
+
const handle = world.internSharedRef(brand, payload);
|
|
3733
|
+
perWorld.set(key, { handle, payload });
|
|
3734
|
+
return handle;
|
|
3735
|
+
}
|
|
3736
|
+
function resolveVideoFieldHandle(value, world, assetsRef) {
|
|
3737
|
+
const texture = materialTextureValue(value);
|
|
3738
|
+
const textureGuid = assetReferenceText(texture?.texture ?? value);
|
|
3739
|
+
if (textureGuid === void 0) return void 0;
|
|
3740
|
+
const payload = assetsRef.lookup(textureGuid);
|
|
3741
|
+
if (payload === void 0 || payload.kind !== "video") return void 0;
|
|
3742
|
+
return internSharedRefFromGuid(world, assetsRef, textureGuid, "VideoAsset");
|
|
3743
|
+
}
|
|
3744
|
+
function materialTextureValue(value) {
|
|
3745
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
3746
|
+
const textureValue = value;
|
|
3747
|
+
return typeof textureValue.texture === "number" || typeof textureValue.texture === "string" || textureValue.texture instanceof Uint8Array ? textureValue : void 0;
|
|
3748
|
+
}
|
|
3749
|
+
function assetReferenceText(value) {
|
|
3750
|
+
if (typeof value === "string") return value;
|
|
3751
|
+
if (value instanceof Uint8Array && isAssetGuidBytes(value)) return AssetGuid.format(value);
|
|
3752
|
+
return void 0;
|
|
3753
|
+
}
|
|
3754
|
+
function isAssetGuidBytes(value) {
|
|
3755
|
+
return value.byteLength === 16;
|
|
3756
|
+
}
|
|
3757
|
+
function materialNormalScale(values) {
|
|
3758
|
+
for (const [field, value] of Object.entries(values)) {
|
|
3759
|
+
if (field !== "normalTexture") continue;
|
|
3760
|
+
const scale = materialTextureValue(value)?.normalScale;
|
|
3761
|
+
return typeof scale === "number" && Number.isFinite(scale) ? scale : 1;
|
|
3762
|
+
}
|
|
3763
|
+
return 1;
|
|
3764
|
+
}
|
|
3765
|
+
function materialTextureRef(value) {
|
|
3766
|
+
return materialTextureValue(value)?.texture ?? value;
|
|
3767
|
+
}
|
|
3768
|
+
function collectMaterialTextureCoordinates(values) {
|
|
3769
|
+
const out = /* @__PURE__ */ new Map();
|
|
3770
|
+
for (const [field, value] of Object.entries(values)) {
|
|
3771
|
+
if (!field.endsWith("Texture")) continue;
|
|
3772
|
+
const coordinates = materialTextureValue(value)?.coordinates;
|
|
3773
|
+
if (coordinates !== void 0) out.set(field, coordinates);
|
|
3774
|
+
}
|
|
3775
|
+
return out;
|
|
3776
|
+
}
|
|
3777
|
+
function collectMaterialTextureSources(values, world) {
|
|
3778
|
+
const out = /* @__PURE__ */ new Map();
|
|
3779
|
+
for (const [field, value] of Object.entries(values)) {
|
|
3780
|
+
const reference = materialTextureRef(value);
|
|
3781
|
+
if (typeof reference !== "number") continue;
|
|
3782
|
+
const resolved = world.sharedRefs.resolve(toShared(reference));
|
|
3783
|
+
if (!resolved.ok || resolveRenderTargetMaterialSource(resolved.value) === void 0) continue;
|
|
3784
|
+
out.set(field, resolved.value);
|
|
3785
|
+
}
|
|
3786
|
+
return out;
|
|
3787
|
+
}
|
|
3788
|
+
function collectMaterialTextureSamplers(values, resolveSampler) {
|
|
3789
|
+
const out = /* @__PURE__ */ new Map();
|
|
3790
|
+
for (const [field, value] of Object.entries(values)) {
|
|
3791
|
+
const sampler = resolveSampler(materialTextureValue(value)?.sampler);
|
|
3792
|
+
if (sampler !== void 0) out.set(field, sampler);
|
|
3793
|
+
}
|
|
3794
|
+
const legacySampler = resolveSampler(values.sampler);
|
|
3795
|
+
if (legacySampler !== void 0 && !out.has("baseColorTexture")) {
|
|
3796
|
+
out.set("baseColorTexture", legacySampler);
|
|
3797
|
+
}
|
|
3798
|
+
return out;
|
|
3799
|
+
}
|
|
3800
|
+
function collectUserRegionTextureHandles(pv, shaderId, paramSchema, assetsRef, world, resolveTex, videoOut) {
|
|
3801
|
+
const fields = materialTextureFields(
|
|
3802
|
+
shaderId,
|
|
3803
|
+
paramSchema !== void 0 ? derive(paramSchema).textureFieldNames : shaderId !== void 0 ? assetsRef.materialShaderTextureFieldNames(shaderId) : void 0
|
|
3804
|
+
) ?? BUILTIN_USER_REGION_TEXTURE_FIELDS;
|
|
3805
|
+
const out = /* @__PURE__ */ new Map();
|
|
3806
|
+
for (const field of fields) {
|
|
3807
|
+
const videoHandle = resolveVideoFieldHandle(pv[field], world, assetsRef);
|
|
3808
|
+
if (videoHandle !== void 0) {
|
|
3809
|
+
videoOut.set(field, videoHandle);
|
|
3810
|
+
continue;
|
|
3811
|
+
}
|
|
3812
|
+
const handle = resolveTex(materialTextureRef(pv[field]), "TextureAsset");
|
|
3813
|
+
if (handle !== void 0) out.set(field, handle);
|
|
3814
|
+
}
|
|
3815
|
+
return out;
|
|
3816
|
+
}
|
|
3817
|
+
var ENGINE_INJECTED_TEXTURE_FIELDS = /* @__PURE__ */ new Set(["emissiveTexture", "occlusionTexture"]);
|
|
3818
|
+
function isEngineInjectedTextureField(shaderId, fieldName) {
|
|
3819
|
+
return isStandardPbrMaterialShader(shaderId) && ENGINE_INJECTED_TEXTURE_FIELDS.has(fieldName);
|
|
3820
|
+
}
|
|
3821
|
+
function materialParametersToParamSchema(parameters, shaderId) {
|
|
3822
|
+
if (isCanonicalStandardPbrMaterialShader(shaderId)) {
|
|
3823
|
+
return STANDARD_PIPELINE_PARAM_SCHEMA;
|
|
3824
|
+
}
|
|
3825
|
+
const engineInjectedTextureFields = isStandardPbrMaterialShader(shaderId) ? ENGINE_INJECTED_TEXTURE_FIELDS : void 0;
|
|
3826
|
+
return parameters.flatMap((parameter) => {
|
|
3827
|
+
if (parameter.type === "bool") return [];
|
|
3828
|
+
if (parameter.type === "texture" || parameter.type === "texture_cube") {
|
|
3829
|
+
if (engineInjectedTextureFields?.has(parameter.name) === true) return [];
|
|
3830
|
+
return [
|
|
3831
|
+
{
|
|
3832
|
+
name: parameter.name,
|
|
3833
|
+
type: parameter.type === "texture_cube" ? "texture_cube" : "texture2d",
|
|
3834
|
+
default: parameter.default
|
|
3835
|
+
}
|
|
3836
|
+
];
|
|
3837
|
+
}
|
|
3838
|
+
const numericDefault = typeof parameter.default === "number" ? parameter.default : Array.isArray(parameter.default) && parameter.default.every((entry) => typeof entry === "number") ? parameter.default : void 0;
|
|
3839
|
+
const numericEntry = {
|
|
3840
|
+
name: parameter.name,
|
|
3841
|
+
type: parameter.type,
|
|
3842
|
+
...parameter.colorSpace === void 0 ? {} : { colorSpace: parameter.colorSpace }
|
|
3843
|
+
};
|
|
3844
|
+
return numericDefault === void 0 ? [numericEntry] : [{ ...numericEntry, default: numericDefault }];
|
|
3845
|
+
});
|
|
3846
|
+
}
|
|
3847
|
+
function materialColorParameterSchema(parameters, shaderId, assets) {
|
|
3848
|
+
if (shaderId === void 0) return parameters;
|
|
3849
|
+
const shader = assets.shaderRegistry.findMaterialArtifact(shaderId);
|
|
3850
|
+
if (!shader.ok) return parameters;
|
|
3851
|
+
const byName = new Map(
|
|
3852
|
+
shader.value.paramSchema.map((parameter) => [parameter.name, parameter])
|
|
3853
|
+
);
|
|
3854
|
+
for (const parameter of parameters) byName.set(parameter.name, parameter);
|
|
3855
|
+
return [...byName.values()];
|
|
3856
|
+
}
|
|
3857
|
+
var MATERIAL_PARENT_CHAIN_LIMIT = 128;
|
|
3858
|
+
function isDeepFrozen(value, seen = /* @__PURE__ */ new Set()) {
|
|
3859
|
+
if (typeof value !== "object" || value === null) return true;
|
|
3860
|
+
if (seen.has(value)) return true;
|
|
3861
|
+
if (!Object.isFrozen(value)) return false;
|
|
3862
|
+
seen.add(value);
|
|
3863
|
+
for (const child of Object.values(value)) {
|
|
3864
|
+
if (!isDeepFrozen(child, seen)) return false;
|
|
3865
|
+
}
|
|
3866
|
+
return true;
|
|
3867
|
+
}
|
|
3868
|
+
function captureMaterialCacheChain(root, assets) {
|
|
3869
|
+
const chain = [];
|
|
3870
|
+
const visitedParentGuids = /* @__PURE__ */ new Set();
|
|
3871
|
+
let current = root;
|
|
3872
|
+
for (let depth = 0; depth < MATERIAL_PARENT_CHAIN_LIMIT; depth += 1) {
|
|
3873
|
+
const parentRef = current.parent;
|
|
3874
|
+
const parentGuid = parentRef === void 0 ? void 0 : materialGuidText(parentRef);
|
|
3875
|
+
chain.push({ asset: current, parentGuid });
|
|
3876
|
+
if (parentGuid === void 0) return chain;
|
|
3877
|
+
if (parentRef === void 0) return void 0;
|
|
3878
|
+
if (visitedParentGuids.has(parentGuid)) return void 0;
|
|
3879
|
+
visitedParentGuids.add(parentGuid);
|
|
3880
|
+
const parent = assets.lookup(parentRef);
|
|
3881
|
+
if (parent?.kind !== "material") return void 0;
|
|
3882
|
+
current = parent;
|
|
3883
|
+
}
|
|
3884
|
+
return void 0;
|
|
3885
|
+
}
|
|
3886
|
+
function readPersistentMaterialSnapshot(cache, handleRaw, assets) {
|
|
3887
|
+
const entry = cache?.get(handleRaw);
|
|
3888
|
+
if (entry === void 0) return void 0;
|
|
3889
|
+
if (entry.crossFrameSafe && entry.chain !== void 0 && entry.catalogEpoch === assets.catalogEpoch)
|
|
3890
|
+
return entry;
|
|
3891
|
+
cache?.delete(handleRaw);
|
|
3892
|
+
return void 0;
|
|
3893
|
+
}
|
|
3894
|
+
function readStablePersistentMaterialSnapshot(cache, handleRaw, assets) {
|
|
3895
|
+
const entry = cache?.get(handleRaw);
|
|
3896
|
+
return entry?.crossFrameSafe === true && entry.chain !== void 0 && entry.catalogEpoch === assets.catalogEpoch ? entry : void 0;
|
|
3897
|
+
}
|
|
3898
|
+
function storeMaterialSnapshot(cache, handleRaw, snapshot, passes, root, assets) {
|
|
3899
|
+
const chain = captureMaterialCacheChain(root, assets);
|
|
3900
|
+
const entry = {
|
|
3901
|
+
snapshot,
|
|
3902
|
+
passes,
|
|
3903
|
+
crossFrameSafe: chain?.every(({ asset }) => isDeepFrozen(asset)) === true,
|
|
3904
|
+
...chain === void 0 ? {} : { chain },
|
|
3905
|
+
...chain === void 0 ? {} : { catalogEpoch: assets.catalogEpoch }
|
|
3906
|
+
};
|
|
3907
|
+
cache.set(handleRaw, entry);
|
|
3908
|
+
return entry;
|
|
3909
|
+
}
|
|
3910
|
+
function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache) {
|
|
3911
|
+
if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
|
|
3912
|
+
const cached = materialSnapshotCache?.get(handleRaw);
|
|
3913
|
+
if (cached !== void 0) return cached.snapshot;
|
|
3914
|
+
const stablePersistentCached = readStablePersistentMaterialSnapshot(
|
|
3915
|
+
persistentMaterialSnapshotCache,
|
|
3916
|
+
handleRaw,
|
|
3917
|
+
assetsRef
|
|
3918
|
+
);
|
|
3919
|
+
if (stablePersistentCached !== void 0) {
|
|
3920
|
+
materialSnapshotCache?.set(handleRaw, stablePersistentCached);
|
|
3921
|
+
return stablePersistentCached.snapshot;
|
|
3922
|
+
}
|
|
3923
|
+
const tagged = toShared(handleRaw);
|
|
3924
|
+
const res = resolveAssetHandle(world, tagged);
|
|
3925
|
+
if (!res.ok) return defaultMaterialSnapshot(handleRaw);
|
|
3926
|
+
const asset = res.value;
|
|
3927
|
+
if (asset.kind !== "material") return defaultMaterialSnapshot(handleRaw);
|
|
3928
|
+
const persistentCached = readPersistentMaterialSnapshot(
|
|
3929
|
+
persistentMaterialSnapshotCache,
|
|
3930
|
+
handleRaw,
|
|
3931
|
+
assetsRef
|
|
3932
|
+
);
|
|
3933
|
+
if (persistentCached !== void 0) {
|
|
3934
|
+
materialSnapshotCache?.set(handleRaw, persistentCached);
|
|
3935
|
+
return persistentCached.snapshot;
|
|
3936
|
+
}
|
|
3937
|
+
const resolvedResult = walkMaterialPassesOverSharedRefs(world, tagged, assetsRef);
|
|
3938
|
+
if (!resolvedResult.ok) return defaultMaterialSnapshot(handleRaw);
|
|
3939
|
+
const resolved = resolvedResult.value;
|
|
3940
|
+
const allPasses = resolved.passes;
|
|
3941
|
+
const firstPassShader = runtimeMaterialShaderIdForMaterial(asset, allPasses, assetsRef);
|
|
3942
|
+
const pv = materialValuesToLinearRuntime(
|
|
3943
|
+
resolved.values,
|
|
3944
|
+
materialColorParameterSchema(resolved.parameters ?? [], firstPassShader, assetsRef),
|
|
3945
|
+
resolved.colorSpace
|
|
3946
|
+
);
|
|
3947
|
+
const baseColorPv = pv.baseColor;
|
|
3948
|
+
const baseColor = vec3.create(
|
|
3949
|
+
baseColorPv?.[0] ?? 1,
|
|
3950
|
+
baseColorPv?.[1] ?? 1,
|
|
3951
|
+
baseColorPv?.[2] ?? 1
|
|
3952
|
+
);
|
|
3953
|
+
const metallicPv = typeof pv.metallic === "number" ? pv.metallic : 0;
|
|
3954
|
+
const roughnessPv = typeof pv.roughness === "number" ? pv.roughness : 0.5;
|
|
3955
|
+
const specularColorPv = pv.specularColor;
|
|
3956
|
+
const normalScalePv = materialNormalScale(pv);
|
|
3957
|
+
const paramSnap = {};
|
|
3958
|
+
for (const [k, v] of Object.entries(pv)) {
|
|
3959
|
+
if (typeof v === "number") paramSnap[k] = v;
|
|
3960
|
+
else if (typeof v === "string") paramSnap[k] = v;
|
|
3961
|
+
else if (Array.isArray(v) && v.every((x) => typeof x === "number")) {
|
|
3962
|
+
paramSnap[k] = v;
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
const materialParamSchema = materialParametersToParamSchema(
|
|
3966
|
+
resolved.parameters ?? [],
|
|
3967
|
+
firstPassShader
|
|
3968
|
+
);
|
|
3969
|
+
const resolveTexLike = (value, brand) => {
|
|
3970
|
+
if (typeof value === "number") return toShared(value);
|
|
3971
|
+
if (typeof value === "string") {
|
|
3972
|
+
return internSharedRefFromGuid(world, assetsRef, value, brand);
|
|
3973
|
+
}
|
|
3974
|
+
return void 0;
|
|
3975
|
+
};
|
|
3976
|
+
const videoTextureFields = /* @__PURE__ */ new Map();
|
|
3977
|
+
const textureHandles = collectUserRegionTextureHandles(
|
|
3978
|
+
pv,
|
|
3979
|
+
firstPassShader,
|
|
3980
|
+
materialParamSchema.length > 0 ? materialParamSchema : void 0,
|
|
3981
|
+
assetsRef,
|
|
3982
|
+
world,
|
|
3983
|
+
resolveTexLike,
|
|
3984
|
+
videoTextureFields
|
|
3985
|
+
);
|
|
3986
|
+
const samplerHandles = collectMaterialTextureSamplers(
|
|
3987
|
+
pv,
|
|
3988
|
+
(value) => resolveTexLike(materialTextureRef(value), "SamplerAsset")
|
|
3989
|
+
);
|
|
3990
|
+
const textureSources = collectMaterialTextureSources(pv, world);
|
|
3991
|
+
const emissiveTextureHandle = resolveTexLike(
|
|
3992
|
+
materialTextureRef(pv.emissiveTexture),
|
|
3993
|
+
"TextureAsset"
|
|
3994
|
+
);
|
|
3995
|
+
const occlusionTextureHandle = resolveTexLike(
|
|
3996
|
+
materialTextureRef(pv.occlusionTexture),
|
|
3997
|
+
"TextureAsset"
|
|
3998
|
+
);
|
|
3999
|
+
const textureCoordinates = collectMaterialTextureCoordinates(pv);
|
|
4000
|
+
const baseColorTextureHandle = textureHandles.get("baseColorTexture");
|
|
4001
|
+
const metallicRoughnessTextureHandle = textureHandles.get("metallicRoughnessTexture");
|
|
4002
|
+
const normalTextureHandle = textureHandles.get("normalTexture");
|
|
4003
|
+
const emissivePv = pv.emissive;
|
|
4004
|
+
const snapshot = {
|
|
4005
|
+
baseColor,
|
|
4006
|
+
metallic: metallicPv,
|
|
4007
|
+
roughness: roughnessPv,
|
|
4008
|
+
...specularColorPv !== void 0 && {
|
|
4009
|
+
specularColor: [
|
|
4010
|
+
specularColorPv[0] ?? 1,
|
|
4011
|
+
specularColorPv[1] ?? 1,
|
|
4012
|
+
specularColorPv[2] ?? 1
|
|
4013
|
+
]
|
|
4014
|
+
},
|
|
4015
|
+
normalScale: normalScalePv,
|
|
4016
|
+
materialShaderId: firstPassShader,
|
|
4017
|
+
materialHandle: handleRaw,
|
|
4018
|
+
renderState: pipelineRenderState(allPasses[0]?.renderState),
|
|
4019
|
+
paramSnapshot: paramSnap,
|
|
4020
|
+
...materialParamSchema.length > 0 && { materialParamSchema },
|
|
4021
|
+
...textureCoordinates.size > 0 && { textureCoordinates },
|
|
4022
|
+
...textureHandles.size > 0 && { textureHandles },
|
|
4023
|
+
...textureSources.size > 0 && { textureSources },
|
|
4024
|
+
...videoTextureFields.size > 0 && { videoTextureFields },
|
|
4025
|
+
...samplerHandles.size > 0 && { samplerHandles },
|
|
4026
|
+
...baseColorTextureHandle !== void 0 && { baseColorTexture: baseColorTextureHandle },
|
|
4027
|
+
...metallicRoughnessTextureHandle !== void 0 && {
|
|
4028
|
+
metallicRoughnessTexture: metallicRoughnessTextureHandle
|
|
4029
|
+
},
|
|
4030
|
+
...normalTextureHandle !== void 0 && { normalTexture: normalTextureHandle },
|
|
4031
|
+
...emissivePv !== void 0 && {
|
|
4032
|
+
emissive: [emissivePv[0] ?? 0, emissivePv[1] ?? 0, emissivePv[2] ?? 0]
|
|
4033
|
+
},
|
|
4034
|
+
...typeof pv.emissiveIntensity === "number" && { emissiveIntensity: pv.emissiveIntensity },
|
|
4035
|
+
...emissiveTextureHandle !== void 0 && { emissiveTexture: emissiveTextureHandle },
|
|
4036
|
+
...occlusionTextureHandle !== void 0 && { occlusionTexture: occlusionTextureHandle },
|
|
4037
|
+
...typeof pv.occlusionStrength === "number" && { occlusionStrength: pv.occlusionStrength },
|
|
4038
|
+
// feat-city-glb Bug 5 (per-submesh transparency): derive `transparent`
|
|
4039
|
+
// from the first pass's `renderState.blend` presence, identical to the
|
|
4040
|
+
// entity-level snapshot builder (extractFrame archetype loop). Without
|
|
4041
|
+
// this, per-submesh materials (materials[i>=1], e.g. a glTF BLEND decal
|
|
4042
|
+
// submesh on a multi-material mesh) never carry the transparent flag, so
|
|
4043
|
+
// the record stage's LDR split + blend routing treats them as opaque and
|
|
4044
|
+
// their alpha=0 texels composite as black.
|
|
4045
|
+
transparent: allPasses[0]?.renderState?.blend !== void 0
|
|
4046
|
+
};
|
|
4047
|
+
const stored = materialSnapshotCache !== void 0 ? storeMaterialSnapshot(
|
|
4048
|
+
materialSnapshotCache,
|
|
4049
|
+
handleRaw,
|
|
4050
|
+
snapshot,
|
|
4051
|
+
allPasses,
|
|
4052
|
+
asset,
|
|
4053
|
+
assetsRef
|
|
4054
|
+
) : void 0;
|
|
4055
|
+
const cacheEntry = stored ?? (persistentMaterialSnapshotCache !== void 0 ? storeMaterialSnapshot(
|
|
4056
|
+
persistentMaterialSnapshotCache,
|
|
4057
|
+
handleRaw,
|
|
4058
|
+
snapshot,
|
|
4059
|
+
allPasses,
|
|
4060
|
+
asset,
|
|
4061
|
+
assetsRef
|
|
4062
|
+
) : void 0);
|
|
4063
|
+
if (cacheEntry?.crossFrameSafe === true) {
|
|
4064
|
+
persistentMaterialSnapshotCache?.set(handleRaw, cacheEntry);
|
|
4065
|
+
}
|
|
4066
|
+
return snapshot;
|
|
4067
|
+
}
|
|
4068
|
+
function computeFrustumCorners(vp, camNear, camFar, nearZ, farZ, projection) {
|
|
4069
|
+
const invVP = mat4.create();
|
|
4070
|
+
mat4.invert(invVP, vp);
|
|
4071
|
+
const corners = [];
|
|
4072
|
+
const span = camFar - camNear;
|
|
4073
|
+
const ndcNear = projection === "orthographic" ? (nearZ - camNear) / span : camFar * (nearZ - camNear) / (nearZ * span);
|
|
4074
|
+
const ndcFar = projection === "orthographic" ? (farZ - camNear) / span : camFar * (farZ - camNear) / (farZ * span);
|
|
4075
|
+
const signs = [-1, 1];
|
|
4076
|
+
for (const sx of signs) {
|
|
4077
|
+
for (const sy of signs) {
|
|
4078
|
+
corners.push(unprojectNDC(invVP, sx, sy, ndcNear));
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
for (const sx of signs) {
|
|
4082
|
+
for (const sy of signs) {
|
|
4083
|
+
corners.push(unprojectNDC(invVP, sx, sy, ndcFar));
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
return corners;
|
|
4087
|
+
}
|
|
4088
|
+
function unprojectNDC(invVP, ndcX, ndcY, ndcZ) {
|
|
4089
|
+
const ndc = vec3.create(ndcX, ndcY, ndcZ);
|
|
4090
|
+
const ws = vec3.create();
|
|
4091
|
+
mat4.unproject(ws, ndc, invVP);
|
|
4092
|
+
return ws;
|
|
4093
|
+
}
|
|
4094
|
+
function pssmSplit(nearPlane, farPlane, cascadeCount, splitLambda) {
|
|
4095
|
+
const EPS = 1e-6;
|
|
4096
|
+
if (farPlane <= nearPlane + EPS) {
|
|
4097
|
+
throw new ShadowInvalidConfigError("shadowDistance", farPlane, nearPlane + EPS);
|
|
4098
|
+
}
|
|
4099
|
+
const result = new Float32Array(cascadeCount);
|
|
4100
|
+
const m = cascadeCount;
|
|
4101
|
+
const n = nearPlane;
|
|
4102
|
+
const f = farPlane;
|
|
4103
|
+
const ratio = f / n;
|
|
4104
|
+
for (let i = 1; i <= m; i++) {
|
|
4105
|
+
const t = i / m;
|
|
4106
|
+
const logPart = n * ratio ** t;
|
|
4107
|
+
const uniformPart = n + t * (f - n);
|
|
4108
|
+
result[i - 1] = splitLambda * logPart + (1 - splitLambda) * uniformPart;
|
|
4109
|
+
}
|
|
4110
|
+
return result;
|
|
4111
|
+
}
|
|
4112
|
+
var POINT_SHADOW_FACE_LOOK = [
|
|
4113
|
+
vec3.create(1, 0, 0),
|
|
4114
|
+
vec3.create(-1, 0, 0),
|
|
4115
|
+
vec3.create(0, 1, 0),
|
|
4116
|
+
vec3.create(0, -1, 0),
|
|
4117
|
+
vec3.create(0, 0, 1),
|
|
4118
|
+
vec3.create(0, 0, -1)
|
|
4119
|
+
];
|
|
4120
|
+
var POINT_SHADOW_FACE_UP = [
|
|
4121
|
+
vec3.create(0, -1, 0),
|
|
4122
|
+
vec3.create(0, -1, 0),
|
|
4123
|
+
vec3.create(0, 0, 1),
|
|
4124
|
+
vec3.create(0, 0, -1),
|
|
4125
|
+
vec3.create(0, -1, 0),
|
|
4126
|
+
vec3.create(0, -1, 0)
|
|
4127
|
+
];
|
|
4128
|
+
function buildPointShadowMatrices(lightPos, near, far) {
|
|
4129
|
+
const fovY = Math.PI / 2;
|
|
4130
|
+
const aspect = 1;
|
|
4131
|
+
const proj = mat4.create();
|
|
4132
|
+
mat4.perspective(proj, fovY, aspect, near, far);
|
|
4133
|
+
const out = [];
|
|
4134
|
+
for (let i = 0; i < 6; i++) {
|
|
4135
|
+
const look = POINT_SHADOW_FACE_LOOK[i];
|
|
4136
|
+
const up = POINT_SHADOW_FACE_UP[i];
|
|
4137
|
+
const target = vec3.create(
|
|
4138
|
+
(lightPos[0] ?? 0) + (look[0] ?? 0),
|
|
4139
|
+
(lightPos[1] ?? 0) + (look[1] ?? 0),
|
|
4140
|
+
(lightPos[2] ?? 0) + (look[2] ?? 0)
|
|
4141
|
+
);
|
|
4142
|
+
const view = mat4.create();
|
|
4143
|
+
mat4.lookAt(view, lightPos, target, up);
|
|
4144
|
+
const vp = mat4.create();
|
|
4145
|
+
mat4.multiply(vp, proj, view);
|
|
4146
|
+
out.push(vp);
|
|
4147
|
+
}
|
|
4148
|
+
return out;
|
|
4149
|
+
}
|
|
4150
|
+
function computeDirectionalCsm(direction, config, cameraData) {
|
|
4151
|
+
const cascadeCount = Math.round(config.cascadeCount);
|
|
4152
|
+
const sNear = cameraData?.near ?? 0.1;
|
|
4153
|
+
const sFar = config.shadowDistance;
|
|
4154
|
+
const splits = pssmSplit(sNear, sFar, cascadeCount, config.splitLambda);
|
|
4155
|
+
const lightDirN = vec3.normalize(vec3.create(), direction);
|
|
4156
|
+
const lightTarget = vec3.create(lightDirN[0] ?? 0, lightDirN[1] ?? 0, lightDirN[2] ?? 0);
|
|
4157
|
+
const lightView = mat4.create();
|
|
4158
|
+
mat4.lookAt(lightView, vec3.create(0, 0, 0), lightTarget, vec3.create(0, 1, 0));
|
|
4159
|
+
if (cameraData === void 0) return null;
|
|
4160
|
+
const camProj = mat4.create();
|
|
4161
|
+
if (cameraData.projection === "orthographic") {
|
|
4162
|
+
mat4.orthographic(
|
|
4163
|
+
camProj,
|
|
4164
|
+
cameraData.orthoLeft,
|
|
4165
|
+
cameraData.orthoRight,
|
|
4166
|
+
cameraData.orthoTop,
|
|
4167
|
+
cameraData.orthoBottom,
|
|
4168
|
+
cameraData.near,
|
|
4169
|
+
cameraData.far
|
|
4170
|
+
);
|
|
4171
|
+
} else {
|
|
4172
|
+
mat4.perspective(camProj, cameraData.fov, cameraData.aspect, cameraData.near, cameraData.far);
|
|
4173
|
+
}
|
|
4174
|
+
const camView = mat4.create();
|
|
4175
|
+
mat4.invert(camView, cameraData.world);
|
|
4176
|
+
const cameraVP = mat4.create();
|
|
4177
|
+
mat4.multiply(cameraVP, camProj, camView);
|
|
4178
|
+
const resultLightViewProjs = [];
|
|
4179
|
+
const cascadeFits = [];
|
|
4180
|
+
let lightSpaceMaxZFull = -Infinity;
|
|
4181
|
+
const fullCorners = computeFrustumCorners(
|
|
4182
|
+
cameraVP,
|
|
4183
|
+
cameraData.near,
|
|
4184
|
+
cameraData.far,
|
|
4185
|
+
sNear,
|
|
4186
|
+
sFar,
|
|
4187
|
+
cameraData.projection
|
|
4188
|
+
);
|
|
4189
|
+
for (const ws of fullCorners) {
|
|
4190
|
+
const ls = vec3.create();
|
|
4191
|
+
mat4.transformVec3(ls, lightView, ws);
|
|
4192
|
+
if ((ls[2] ?? 0) > lightSpaceMaxZFull) lightSpaceMaxZFull = ls[2] ?? 0;
|
|
4193
|
+
}
|
|
4194
|
+
for (let cIdx = 0; cIdx < 4; cIdx++) {
|
|
4195
|
+
if (cIdx >= cascadeCount) {
|
|
4196
|
+
resultLightViewProjs.push(new Float32Array(16));
|
|
4197
|
+
continue;
|
|
4198
|
+
}
|
|
4199
|
+
const cascadeNear = cIdx === 0 ? sNear : splits[cIdx - 1] ?? sFar;
|
|
4200
|
+
const cascadeFar = splits[cIdx] ?? sFar;
|
|
4201
|
+
const corners = computeFrustumCorners(
|
|
4202
|
+
cameraVP,
|
|
4203
|
+
cameraData.near,
|
|
4204
|
+
cameraData.far,
|
|
4205
|
+
cascadeNear,
|
|
4206
|
+
cascadeFar,
|
|
4207
|
+
cameraData.projection
|
|
4208
|
+
);
|
|
4209
|
+
const lightMVP = mat4.clone(lightView);
|
|
4210
|
+
let minX = Infinity;
|
|
4211
|
+
let maxX = -Infinity;
|
|
4212
|
+
let minY = Infinity;
|
|
4213
|
+
let maxY = -Infinity;
|
|
4214
|
+
let minZ = Infinity;
|
|
4215
|
+
let maxZ = -Infinity;
|
|
4216
|
+
for (const ws of corners) {
|
|
4217
|
+
const ls = vec3.create();
|
|
4218
|
+
mat4.transformVec3(ls, lightMVP, ws);
|
|
4219
|
+
if ((ls[0] ?? 0) < minX) minX = ls[0] ?? 0;
|
|
4220
|
+
if ((ls[0] ?? 0) > maxX) maxX = ls[0] ?? 0;
|
|
4221
|
+
if ((ls[1] ?? 0) < minY) minY = ls[1] ?? 0;
|
|
4222
|
+
if ((ls[1] ?? 0) > maxY) maxY = ls[1] ?? 0;
|
|
4223
|
+
if ((ls[2] ?? 0) < minZ) minZ = ls[2] ?? 0;
|
|
4224
|
+
if ((ls[2] ?? 0) > maxZ) maxZ = ls[2] ?? 0;
|
|
4225
|
+
}
|
|
4226
|
+
const nearZ = Math.max(maxZ, lightSpaceMaxZFull);
|
|
4227
|
+
const orthoProj = mat4.create();
|
|
4228
|
+
mat4.orthographic(orthoProj, minX, maxX, maxY, minY, -nearZ, -minZ);
|
|
4229
|
+
cascadeFits.push({
|
|
4230
|
+
split: splits[cIdx] ?? sFar,
|
|
4231
|
+
minX,
|
|
4232
|
+
maxX,
|
|
4233
|
+
minY,
|
|
4234
|
+
maxY,
|
|
4235
|
+
minZ,
|
|
4236
|
+
maxZ
|
|
4237
|
+
});
|
|
4238
|
+
resultLightViewProjs.push(new Float32Array(mat4.multiply(mat4.create(), orthoProj, lightView)));
|
|
4239
|
+
}
|
|
4240
|
+
const projection = projectDirectionalShadow(
|
|
4241
|
+
cascadeFits,
|
|
4242
|
+
config.mapSize,
|
|
4243
|
+
config.shadowFilter ?? 2,
|
|
4244
|
+
config.shadowAngularRadius ?? 465e-5,
|
|
4245
|
+
config.maxPenumbraTexels ?? 32
|
|
4246
|
+
);
|
|
4247
|
+
if (projection === void 0) return null;
|
|
4248
|
+
return {
|
|
4249
|
+
lightViewProj: resultLightViewProjs,
|
|
4250
|
+
splitPlanes: projection.splitPlanes,
|
|
4251
|
+
cascadeCount,
|
|
4252
|
+
cascadeBlend: config.cascadeBlend,
|
|
4253
|
+
shadowMapSize: config.mapSize,
|
|
4254
|
+
directionalShadowQuality: projection.directionalShadowQuality
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4257
|
+
var ALL_VISIBLE = {
|
|
4258
|
+
diagnostics: [],
|
|
4259
|
+
hasAnyIntent: false,
|
|
4260
|
+
hasAnyHiddenIntent: false,
|
|
4261
|
+
get: () => void 0,
|
|
4262
|
+
effective: () => "visible"
|
|
4263
|
+
};
|
|
4264
|
+
function collectCameraSnapshots(world) {
|
|
4265
|
+
const worldInternal = createWorldInternalView(world);
|
|
4266
|
+
const cameras = [];
|
|
4267
|
+
const cameraQuery = world.query({ read: [Camera], optional: [MotionBlur], with: [Transform, GlobalTransform] }).unwrap();
|
|
4268
|
+
for (const row of cameraQuery) {
|
|
4269
|
+
const cam = row.get(Camera);
|
|
4270
|
+
const motionBlur = row.get(MotionBlur);
|
|
4493
4271
|
const entity = row.entity;
|
|
4494
|
-
const
|
|
4495
|
-
if (
|
|
4496
|
-
|
|
4272
|
+
const view = worldInternal._getArrayView(entity, GlobalTransform, "world");
|
|
4273
|
+
if (view === void 0) continue;
|
|
4274
|
+
const worldMat = new Float32Array(view);
|
|
4275
|
+
const target = resolveCameraTarget(world, cam.target);
|
|
4276
|
+
cameras.push({
|
|
4277
|
+
entityKey: entity,
|
|
4278
|
+
...target === void 0 ? {} : { target },
|
|
4279
|
+
historyVersion: cam.historyVersion,
|
|
4280
|
+
position: mat4.getTranslation(vec3.create(), worldMat),
|
|
4281
|
+
world: worldMat,
|
|
4282
|
+
fov: cam.fov,
|
|
4283
|
+
aspect: cam.aspect,
|
|
4284
|
+
near: cam.near,
|
|
4285
|
+
far: cam.far,
|
|
4286
|
+
projection: cameraProjectionFromF32(cam.projection),
|
|
4287
|
+
orthoLeft: cam.left,
|
|
4288
|
+
orthoRight: cam.right,
|
|
4289
|
+
orthoBottom: cam.bottom,
|
|
4290
|
+
orthoTop: cam.top,
|
|
4291
|
+
tonemap: tonemapFromF32(cam.tonemap),
|
|
4292
|
+
exposure: cam.exposure,
|
|
4293
|
+
whitePoint: cam.whitePoint,
|
|
4294
|
+
antialias: antialiasFromF32(cam.antialias),
|
|
4295
|
+
bloom: bloomEnabledFromF32(cam.bloom),
|
|
4296
|
+
bloomThreshold: cam.bloomThreshold,
|
|
4297
|
+
bloomIntensity: cam.bloomIntensity,
|
|
4298
|
+
bloomBlurRadius: cam.bloomBlurRadius,
|
|
4299
|
+
clearColor: [
|
|
4300
|
+
cam.clearColor[0] ?? 0,
|
|
4301
|
+
cam.clearColor[1] ?? 0,
|
|
4302
|
+
cam.clearColor[2] ?? 0,
|
|
4303
|
+
cam.clearColor[3] ?? 1
|
|
4304
|
+
],
|
|
4305
|
+
...motionBlur === void 0 ? {} : {
|
|
4306
|
+
motionBlur: {
|
|
4307
|
+
shutterAngle: motionBlur.shutterAngle,
|
|
4308
|
+
maxRadiusPixels: motionBlur.maxRadiusPixels,
|
|
4309
|
+
sampleCount: motionBlur.sampleCount
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
});
|
|
4497
4313
|
}
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4314
|
+
return cameras;
|
|
4315
|
+
}
|
|
4316
|
+
function collectCubeCameraSnapshots(world) {
|
|
4317
|
+
const worldInternal = createWorldInternalView(world);
|
|
4318
|
+
const snapshots = [];
|
|
4319
|
+
const query = world.query({ read: [CubeCamera], with: [Transform, GlobalTransform] }).unwrap();
|
|
4320
|
+
for (const row of query) {
|
|
4321
|
+
const camera = row.get(CubeCamera);
|
|
4322
|
+
const target = resolveCameraTarget(world, camera.target);
|
|
4323
|
+
if (target === void 0) continue;
|
|
4324
|
+
const view = worldInternal._getArrayView(row.entity, GlobalTransform, "world");
|
|
4325
|
+
if (view === void 0) continue;
|
|
4326
|
+
snapshots.push({
|
|
4327
|
+
entityKey: row.entity,
|
|
4328
|
+
target,
|
|
4329
|
+
position: [view[12] ?? 0, view[13] ?? 0, view[14] ?? 0],
|
|
4330
|
+
near: camera.near,
|
|
4331
|
+
far: camera.far,
|
|
4332
|
+
updateIntent: cubeCameraUpdateIntentFromF32(camera.updateIntent),
|
|
4333
|
+
requestVersion: camera.requestVersion,
|
|
4334
|
+
faceBudget: camera.faceBudget
|
|
4335
|
+
});
|
|
4336
|
+
}
|
|
4337
|
+
return snapshots;
|
|
4338
|
+
}
|
|
4339
|
+
function collectReflectionProbeFacts(world) {
|
|
4340
|
+
const worldInternal = createWorldInternalView(world);
|
|
4341
|
+
const facts = [];
|
|
4342
|
+
const query = world.query({ read: [ReflectionProbe], with: [Transform, GlobalTransform] }).unwrap();
|
|
4343
|
+
for (const row of query) {
|
|
4344
|
+
const probe = row.get(ReflectionProbe);
|
|
4345
|
+
const view = worldInternal._getArrayView(row.entity, GlobalTransform, "world");
|
|
4346
|
+
if (view === void 0) {
|
|
4347
|
+
continue;
|
|
4348
|
+
}
|
|
4349
|
+
facts.push({
|
|
4350
|
+
worldId: 0,
|
|
4351
|
+
entityKey: row.entity,
|
|
4352
|
+
center: [view[12] ?? 0, view[13] ?? 0, view[14] ?? 0],
|
|
4353
|
+
halfExtents: [
|
|
4354
|
+
probe.halfExtents[0] ?? 0,
|
|
4355
|
+
probe.halfExtents[1] ?? 0,
|
|
4356
|
+
probe.halfExtents[2] ?? 0
|
|
4357
|
+
],
|
|
4358
|
+
priority: probe.priority,
|
|
4359
|
+
intensity: probe.intensity,
|
|
4360
|
+
resolution: probe.resolution,
|
|
4361
|
+
revision: probe.invalidationVersion,
|
|
4362
|
+
updateIntent: reflectionProbeUpdateIntentFromF32(probe.updateIntent),
|
|
4363
|
+
invalidationVersion: probe.invalidationVersion
|
|
4364
|
+
});
|
|
4501
4365
|
}
|
|
4366
|
+
return facts;
|
|
4367
|
+
}
|
|
4368
|
+
function selectCameraRoles(world) {
|
|
4369
|
+
const cameras = collectCameraSnapshots(world);
|
|
4370
|
+
const displayEntities = cameras.filter((camera) => camera.target === void 0).map((camera) => camera.entityKey ?? 0);
|
|
4371
|
+
const activeCameraIndex = selectActiveCameraIndex(
|
|
4372
|
+
displayEntities,
|
|
4373
|
+
getActiveCamera(world)?.entity
|
|
4374
|
+
);
|
|
4375
|
+
const displayEntityKey = displayEntities[activeCameraIndex] ?? displayEntities[0];
|
|
4376
|
+
const display = displayEntityKey === void 0 ? [] : cameras.filter((camera) => camera.entityKey === displayEntityKey);
|
|
4377
|
+
const candidates = cameras.map((camera) => ({
|
|
4378
|
+
worldId: 0,
|
|
4379
|
+
entityKey: camera.entityKey ?? 0,
|
|
4380
|
+
...camera.target === void 0 ? {} : { target: camera.target },
|
|
4381
|
+
requestVersion: 0,
|
|
4382
|
+
update: "continuous"
|
|
4383
|
+
}));
|
|
4384
|
+
const selected = selectCameraTargetViews(candidates, {
|
|
4385
|
+
...displayEntityKey === void 0 ? {} : { displayEntityKey },
|
|
4386
|
+
budget: 1
|
|
4387
|
+
});
|
|
4388
|
+
const auxiliary = selected.auxiliary.flatMap(
|
|
4389
|
+
(candidate) => cameras.filter((camera) => camera.entityKey === candidate.entityKey)
|
|
4390
|
+
);
|
|
4391
|
+
return { display, auxiliary };
|
|
4392
|
+
}
|
|
4393
|
+
function tonemapParams(camera) {
|
|
4394
|
+
const bytes = new ArrayBuffer(16);
|
|
4395
|
+
const floats = new Float32Array(bytes);
|
|
4396
|
+
const integers = new Uint32Array(bytes);
|
|
4397
|
+
floats[0] = camera.exposure;
|
|
4398
|
+
floats[1] = camera.whitePoint;
|
|
4399
|
+
integers[2] = tonemapToU32(camera.tonemap);
|
|
4400
|
+
return new Uint8Array(bytes);
|
|
4401
|
+
}
|
|
4402
|
+
function prepareExtractContext(world, options = {}) {
|
|
4403
|
+
const renderables = options.renderables ?? "full";
|
|
4502
4404
|
return {
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
environmentReady: true,
|
|
4510
|
-
...volumetricFog === void 0 ? {} : { volumetricFog },
|
|
4405
|
+
assets: options.assets,
|
|
4406
|
+
pipelineState: options.pipelineState,
|
|
4407
|
+
materialSnapshotCache: options.materialSnapshotCache,
|
|
4408
|
+
resourceOwnerFog: options.resourceOwnerFog,
|
|
4409
|
+
cull: options.cull ?? "self",
|
|
4410
|
+
cullCameras: options.cullCameras,
|
|
4511
4411
|
renderables,
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
skyboxCount,
|
|
4518
|
-
fog,
|
|
4519
|
-
...fogFailure === void 0 ? {} : { fogFailure },
|
|
4520
|
-
frustumStats: { culled: frustumCulled, total: frustumTotal },
|
|
4521
|
-
visibilityStats: { explicitlyHidden: explicitlyHidden.size },
|
|
4522
|
-
postProcessParams,
|
|
4523
|
-
visibilitySnapshots: [context.visibility],
|
|
4524
|
-
featureVisibilitySnapshots: [{ world, snapshot: context.visibility }],
|
|
4525
|
-
hiddenEntityReports: [...explicitlyHidden].map((entity) => ({ world, entity }))
|
|
4412
|
+
renderableEntities: options.renderableEntities,
|
|
4413
|
+
retainHidden: options.retainHidden ?? false,
|
|
4414
|
+
visibility: renderables === "none" ? ALL_VISIBLE : resolveVisibility(world),
|
|
4415
|
+
getMaterialShaderArtifact: options.getMaterialShaderArtifact,
|
|
4416
|
+
instanceCollections: options.instanceCollections
|
|
4526
4417
|
};
|
|
4527
4418
|
}
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4419
|
+
var fogQueries = /* @__PURE__ */ new WeakMap();
|
|
4420
|
+
var fogLkgStates = /* @__PURE__ */ new WeakMap();
|
|
4421
|
+
function fogState(world) {
|
|
4422
|
+
const existing = fogLkgStates.get(world);
|
|
4423
|
+
if (existing !== void 0) return existing;
|
|
4424
|
+
const created = { lkg: void 0, failure: void 0 };
|
|
4425
|
+
fogLkgStates.set(world, created);
|
|
4426
|
+
return created;
|
|
4427
|
+
}
|
|
4428
|
+
function selectFogFrame(world) {
|
|
4429
|
+
const fogCandidates = [];
|
|
4430
|
+
let fogQuery = fogQueries.get(world);
|
|
4431
|
+
if (fogQuery === void 0) {
|
|
4432
|
+
fogQuery = world.query({ read: [Fog] }).unwrap();
|
|
4433
|
+
fogQueries.set(world, fogQuery);
|
|
4434
|
+
}
|
|
4435
|
+
for (const row of fogQuery) {
|
|
4436
|
+
const value = row.get(Fog);
|
|
4437
|
+
fogCandidates.push({
|
|
4438
|
+
entityKey: row.entity,
|
|
4439
|
+
color: [value.color[0] ?? 0, value.color[1] ?? 0, value.color[2] ?? 0],
|
|
4440
|
+
density: value.density,
|
|
4441
|
+
heightFalloff: value.heightFalloff,
|
|
4442
|
+
maxOpacity: value.maxOpacity
|
|
4443
|
+
});
|
|
4444
|
+
}
|
|
4445
|
+
const fogSelection = selectEnvironment({
|
|
4446
|
+
environments: [],
|
|
4447
|
+
fogs: fogCandidates,
|
|
4448
|
+
suns: [],
|
|
4449
|
+
lane: "direct"
|
|
4450
|
+
});
|
|
4451
|
+
const state = fogState(world);
|
|
4452
|
+
if (fogSelection.ok) {
|
|
4453
|
+
state.lkg = fogSelection.value.fog;
|
|
4454
|
+
state.failure = void 0;
|
|
4455
|
+
return fogSelection.value.fog;
|
|
4456
|
+
}
|
|
4457
|
+
state.failure = {
|
|
4458
|
+
code: fogSelection.error.code,
|
|
4459
|
+
expected: fogSelection.error.expected,
|
|
4460
|
+
hint: fogSelection.error.hint,
|
|
4461
|
+
detail: Object.freeze({ ...fogSelection.error.detail })
|
|
4534
4462
|
};
|
|
4463
|
+
routeWorldError(world, fogSelection.error, {
|
|
4464
|
+
systemName: "RenderSystem.extract (fog-selection)"
|
|
4465
|
+
});
|
|
4466
|
+
if (state.lkg !== void 0) return state.lkg;
|
|
4467
|
+
throw fogSelection.error;
|
|
4535
4468
|
}
|
|
4536
|
-
function
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4469
|
+
function textureDigest(texture) {
|
|
4470
|
+
let hash = 2166136261;
|
|
4471
|
+
for (const byte of texture.data) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
|
|
4472
|
+
return `fnv1a:${hash.toString(16).padStart(8, "0")}`;
|
|
4473
|
+
}
|
|
4474
|
+
function extractVolumeSnapshot(world, assets, worldInternal) {
|
|
4475
|
+
const query = world.query({ read: [VolumetricFog] }).unwrap();
|
|
4476
|
+
const authorings = [];
|
|
4477
|
+
let selectedLight;
|
|
4478
|
+
let first;
|
|
4479
|
+
for (const row of query) {
|
|
4480
|
+
const source = row.get(VolumetricFog);
|
|
4481
|
+
if (source.light === null) continue;
|
|
4482
|
+
const selected = resolveSelectedVolumetricLight(world, source.light);
|
|
4483
|
+
if (selected.status === "available") {
|
|
4484
|
+
const pairSpot = source.spotLight === null ? void 0 : source.spotLight;
|
|
4485
|
+
selectedLight ??= {
|
|
4486
|
+
entity: selected.entity,
|
|
4487
|
+
kind: selected.kind,
|
|
4488
|
+
...selected.kind === "point" ? { pointLightEntity: selected.entity } : {},
|
|
4489
|
+
...pairSpot === void 0 ? {} : { spotLightEntity: pairSpot }
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
const densityHandle = toShared(Math.round(Number(source.density)));
|
|
4493
|
+
const resolved = resolveAssetHandle(world, densityHandle);
|
|
4494
|
+
if (!resolved.ok || resolved.value.kind !== "texture") {
|
|
4495
|
+
worldInternal._routeError(
|
|
4496
|
+
resolved.ok ? new RhiError({
|
|
4497
|
+
code: "asset-not-registered",
|
|
4498
|
+
expected: "VolumetricFog.density resolves to a TextureAsset",
|
|
4499
|
+
hint: "load a TextureAsset before assigning it to VolumetricFog.density",
|
|
4500
|
+
detail: { assetHandle: Number(densityHandle) }
|
|
4501
|
+
}) : resolved.error,
|
|
4502
|
+
{ severity: Severity.Error, systemName: "RenderSystem.extract (volumetric-density)" }
|
|
4503
|
+
);
|
|
4504
|
+
return { status: "degraded" };
|
|
4505
|
+
}
|
|
4506
|
+
const densityAsset = resolved.value;
|
|
4507
|
+
const guid = assets?.guidOf(densityAsset) ?? `handle:${Number(densityHandle)}`;
|
|
4508
|
+
const shape = densityAsset.shape;
|
|
4509
|
+
const density = shape.viewDimension === "3d" ? {
|
|
4510
|
+
guid,
|
|
4511
|
+
generation: 1,
|
|
4512
|
+
shape: {
|
|
4513
|
+
viewDimension: "3d",
|
|
4514
|
+
extent: {
|
|
4515
|
+
width: shape.extent.width,
|
|
4516
|
+
height: shape.extent.height,
|
|
4517
|
+
depth: shape.extent.depth
|
|
4518
|
+
}
|
|
4519
|
+
},
|
|
4520
|
+
format: densityAsset.format,
|
|
4521
|
+
colorSpace: densityAsset.colorSpace
|
|
4522
|
+
} : {
|
|
4523
|
+
guid,
|
|
4524
|
+
generation: 1,
|
|
4525
|
+
shape: {
|
|
4526
|
+
viewDimension: shape.viewDimension,
|
|
4527
|
+
extent: shape.viewDimension === "2d-array" ? {
|
|
4528
|
+
width: shape.extent.width,
|
|
4529
|
+
height: shape.extent.height,
|
|
4530
|
+
layers: shape.extent.layers
|
|
4531
|
+
} : { width: shape.extent.width, height: shape.extent.height }
|
|
4532
|
+
},
|
|
4533
|
+
format: densityAsset.format,
|
|
4534
|
+
colorSpace: densityAsset.colorSpace
|
|
4535
|
+
};
|
|
4536
|
+
const authoring = {
|
|
4537
|
+
light: source.light,
|
|
4538
|
+
density,
|
|
4539
|
+
bounds: {
|
|
4540
|
+
min: [source.boundsMin[0] ?? 0, source.boundsMin[1] ?? 0, source.boundsMin[2] ?? 0],
|
|
4541
|
+
max: [source.boundsMax[0] ?? 0, source.boundsMax[1] ?? 0, source.boundsMax[2] ?? 0]
|
|
4542
|
+
},
|
|
4543
|
+
extinction: [source.extinction[0] ?? 0, source.extinction[1] ?? 0, source.extinction[2] ?? 0],
|
|
4544
|
+
albedo: [source.albedo[0] ?? 0, source.albedo[1] ?? 0, source.albedo[2] ?? 0],
|
|
4545
|
+
emission: [source.emission[0] ?? 0, source.emission[1] ?? 0, source.emission[2] ?? 0],
|
|
4546
|
+
anisotropy: source.anisotropy,
|
|
4547
|
+
maxDistance: source.maxDistance
|
|
4548
|
+
};
|
|
4549
|
+
authorings.push(authoring);
|
|
4550
|
+
first ??= { densityHandle, densityAsset, guid };
|
|
4551
|
+
}
|
|
4552
|
+
if (authorings.length === 0) return void 0;
|
|
4553
|
+
const extracted = extractVolumetricFog(authorings);
|
|
4554
|
+
if (!extracted.ok) {
|
|
4555
|
+
worldInternal._routeError(extracted.error, {
|
|
4556
|
+
severity: Severity.Error,
|
|
4557
|
+
systemName: "RenderSystem.extract (volumetric-fog)"
|
|
4558
|
+
});
|
|
4559
|
+
return {
|
|
4560
|
+
status: "degraded",
|
|
4561
|
+
...first === void 0 ? {} : {
|
|
4562
|
+
densityHandle: first.densityHandle,
|
|
4563
|
+
densityAsset: first.densityAsset,
|
|
4564
|
+
guid: first.guid,
|
|
4565
|
+
generation: 1,
|
|
4566
|
+
digest: textureDigest(first.densityAsset),
|
|
4567
|
+
...selectedLight === void 0 ? {} : {
|
|
4568
|
+
lightEntity: selectedLight.entity,
|
|
4569
|
+
lightKind: selectedLight.kind,
|
|
4570
|
+
...selectedLight.pointLightEntity === void 0 ? {} : { pointLightEntity: selectedLight.pointLightEntity },
|
|
4571
|
+
...selectedLight.spotLightEntity === void 0 ? {} : { spotLightEntity: selectedLight.spotLightEntity }
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
if (extracted.value.status === "off" || first === void 0) return { status: "off" };
|
|
4577
|
+
const selectedLightFields = selectedLight === void 0 ? {} : {
|
|
4578
|
+
lightEntity: selectedLight.entity,
|
|
4579
|
+
lightKind: selectedLight.kind,
|
|
4580
|
+
...selectedLight.pointLightEntity === void 0 ? {} : { pointLightEntity: selectedLight.pointLightEntity },
|
|
4581
|
+
...selectedLight.spotLightEntity === void 0 ? {} : { spotLightEntity: selectedLight.spotLightEntity }
|
|
4582
|
+
};
|
|
4583
|
+
return {
|
|
4584
|
+
status: "available",
|
|
4585
|
+
fog: extracted.value.fog,
|
|
4586
|
+
densityHandle: first.densityHandle,
|
|
4587
|
+
densityAsset: first.densityAsset,
|
|
4588
|
+
guid: first.guid,
|
|
4589
|
+
generation: 1,
|
|
4590
|
+
digest: textureDigest(first.densityAsset),
|
|
4591
|
+
...selectedLightFields
|
|
4592
|
+
};
|
|
4543
4593
|
}
|
|
4544
4594
|
var PROBE_R_MIN = R_MIN;
|
|
4545
4595
|
var PROBE_MAX_CONTRIBUTORS = PROBE_BLEND_RECORD_CAPACITY;
|
|
@@ -5080,6 +5130,6 @@ var ProbeBlendSceneProjection = class {
|
|
|
5080
5130
|
}
|
|
5081
5131
|
};
|
|
5082
5132
|
|
|
5083
|
-
export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, createCookieProjectionMatrixData, createExtendedLightingState, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
|
|
5084
|
-
//# sourceMappingURL=chunk-
|
|
5085
|
-
//# sourceMappingURL=chunk-
|
|
5133
|
+
export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, createCookieProjectionMatrixData, createExtendedLightingState, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
|
|
5134
|
+
//# sourceMappingURL=chunk-N3RT2EUR.mjs.map
|
|
5135
|
+
//# sourceMappingURL=chunk-N3RT2EUR.mjs.map
|