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