@forgeax/engine-render 0.1.34 → 0.1.35
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 +52 -3
- package/dist/assembly/device-feature-admission.d.ts +2 -2
- package/dist/assembly/host-contract.d.ts +3 -2
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +5 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts +1 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -4
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-3XUBWRY2.mjs +1842 -0
- package/dist/chunk-3XUBWRY2.mjs.map +1 -0
- package/dist/{chunk-UI5SFODX.mjs → chunk-G6HDNGY7.mjs} +2329 -1776
- package/dist/chunk-G6HDNGY7.mjs.map +1 -0
- package/dist/{chunk-HEB564WF.mjs → chunk-LM5IE7GF.mjs} +4 -4
- package/dist/{chunk-HEB564WF.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
- package/dist/{chunk-MKDIT2EM.mjs → chunk-LNIUIKQ7.mjs} +143 -246
- package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
- package/dist/chunk-MXTWKZO4.mjs +3268 -0
- package/dist/chunk-MXTWKZO4.mjs.map +1 -0
- package/dist/{chunk-ODZWR6JQ.mjs → chunk-MZ4C7EHF.mjs} +2042 -27
- package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
- package/dist/chunk-RIPAEGI6.mjs +48 -0
- package/dist/chunk-RIPAEGI6.mjs.map +1 -0
- package/dist/{chunk-OCDLEI6I.mjs → chunk-SGPUJW3F.mjs} +117 -5
- package/dist/chunk-SGPUJW3F.mjs.map +1 -0
- package/dist/{chunk-ELJFJ2BU.mjs → chunk-X2KA6WHM.mjs} +29 -4
- package/dist/chunk-X2KA6WHM.mjs.map +1 -0
- package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
- package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
- package/dist/cloud/frame-context.d.ts +2 -2
- package/dist/cloud/frame-context.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +810 -2073
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -19
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/errors/render.d.ts +3 -2
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/material-context.d.ts +7 -0
- package/dist/extract/material-context.d.ts.map +1 -0
- package/dist/features/host.d.ts +5 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +2 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/types.d.ts +4 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +1 -1
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-ownership.d.ts +3 -3
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +4 -4
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +530 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instances.d.ts +3 -4
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -8
- package/dist/internal.mjs.map +1 -1
- package/dist/pbr-pipeline.d.ts +3 -3
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
- package/dist/pipeline/standard-output/resources.d.ts +2 -2
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
- package/dist/publication/contract.d.ts +77 -0
- package/dist/publication/contract.d.ts.map +1 -0
- package/dist/publication/dependencies.d.ts +7 -0
- package/dist/publication/dependencies.d.ts.map +1 -0
- package/dist/publication/prepare-geometry.d.ts +9 -0
- package/dist/publication/prepare-geometry.d.ts.map +1 -0
- package/dist/publication/programs.d.ts +5 -0
- package/dist/publication/programs.d.ts.map +1 -0
- package/dist/publication/publisher.d.ts +33 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/receiver.d.ts +29 -0
- package/dist/publication/receiver.d.ts.map +1 -0
- package/dist/publication/resource-scope.d.ts +18 -0
- package/dist/publication/resource-scope.d.ts.map +1 -0
- package/dist/publication/targets.d.ts +33 -0
- package/dist/publication/targets.d.ts.map +1 -0
- package/dist/publication/video.d.ts +5 -0
- package/dist/publication/video.d.ts.map +1 -0
- package/dist/record/fold-buckets.d.ts +3 -3
- package/dist/record/fold-buckets.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +6 -6
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +5 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +2 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +2 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -9
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +3 -16
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts +3 -3
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +2 -2
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/sprite-instance-buffer.d.ts +31 -0
- package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
- package/dist/record/target-capture-graph.d.ts +19 -0
- package/dist/record/target-capture-graph.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +2 -13
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +2 -2
- package/dist/record/volume-params.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +5 -5
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/render-contract.d.ts +4 -1
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +2 -0
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +2 -2
- package/dist/render-system-presentation.d.ts.map +1 -1
- package/dist/render-system-projections.d.ts +3 -2
- package/dist/render-system-projections.d.ts.map +1 -1
- package/dist/render-system-residency.d.ts +2 -2
- package/dist/render-system-residency.d.ts.map +1 -1
- package/dist/render-system.d.ts +3 -7
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +8 -4
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/render-source.d.ts +42 -0
- package/dist/scene/render-source.d.ts.map +1 -0
- package/dist/scene/source-systems.d.ts +6 -0
- package/dist/scene/source-systems.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +10 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +2 -2
- package/dist/systems/transparent-dispatch.d.ts.map +1 -1
- package/dist/systems/transparent-sort-config.d.ts +2 -1
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -7
- package/package.json +21 -21
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
- package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +3 -4
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +0 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
- package/src/__tests__/physical-clearcoat.integration.test.ts +23 -23
- package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +1 -1
- package/src/assembly/device-feature-admission.ts +2 -2
- package/src/assembly/host-contract.ts +5 -2
- package/src/assembly/recovery/renderer-recover.ts +9 -0
- package/src/assembly/render-target-host.ts +57 -47
- package/src/assembly/renderer-facade.ts +3 -1
- package/src/assembly/webgpu-ready.ts +1 -1
- package/src/assembly/webgpu-renderer.ts +89 -61
- package/src/cloud/frame-context.ts +2 -2
- package/src/device/gpu-residency.ts +26 -25
- package/src/errors/render.ts +3 -1
- package/src/extract/material-context.ts +21 -0
- package/src/features/host.ts +13 -5
- package/src/features/plan.ts +2 -0
- package/src/features/types.ts +4 -0
- package/src/glyph-text-layout-system.ts +2 -2
- package/src/gpu-driven/shadow-ownership.ts +3 -3
- package/src/ibl/frame-resources.ts +0 -1
- package/src/ibl/skylight-bind-group.ts +13 -25
- package/src/index.ts +9 -0
- package/src/instances.ts +9 -6
- package/src/pbr-pipeline.ts +11 -17
- package/src/pipeline/standard-output/lut-gpu.ts +3 -3
- package/src/pipeline/standard-output/resources.ts +2 -2
- package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
- package/src/publication/__tests__/features.integration.test.ts +122 -0
- package/src/publication/__tests__/programs.unit.test.ts +25 -0
- package/src/publication/__tests__/publication.integration.test.ts +370 -0
- package/src/publication/__tests__/targets.integration.test.ts +120 -0
- package/src/publication/__tests__/video.browser.test.ts +50 -0
- package/src/publication/contract.ts +104 -0
- package/src/publication/dependencies.ts +54 -0
- package/src/publication/prepare-geometry.ts +94 -0
- package/src/publication/programs.ts +45 -0
- package/src/publication/publisher.ts +618 -0
- package/src/publication/receiver.ts +297 -0
- package/src/publication/resource-scope.ts +31 -0
- package/src/publication/targets.ts +182 -0
- package/src/publication/video.ts +33 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +8 -10
- package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
- package/src/record/fold-buckets.ts +8 -5
- package/src/record/frame-snapshot.ts +6 -6
- package/src/record/frame.ts +42 -22
- package/src/record/helpers.ts +2 -2
- package/src/record/main-pass-geometry.ts +21 -2
- package/src/record/main-pass-material.ts +37 -33
- package/src/record/main-pass-sprite-draws.ts +6 -152
- package/src/record/main-pass.ts +8 -7
- package/src/record/prepared-material-bindings.ts +11 -6
- package/src/record/render-context.ts +2 -2
- package/src/record/shadow-pass.ts +0 -3
- package/src/record/sprite-instance-buffer.ts +155 -0
- package/src/record/target-capture-graph.ts +258 -0
- package/src/record/typed-frame-graph.ts +6 -206
- package/src/record/view-ubo.ts +1 -1
- package/src/record/volume-params.ts +6 -6
- package/src/recovery/render-system-candidate.ts +10 -10
- package/src/render-contract.ts +6 -1
- package/src/render-system-extract-tail.ts +33 -17
- package/src/render-system-extract.ts +2 -0
- package/src/render-system-presentation.ts +2 -2
- package/src/render-system-projections.ts +3 -2
- package/src/render-system-residency.ts +2 -2
- package/src/render-system.ts +82 -53
- package/src/scene/render-scene.ts +110 -100
- package/src/scene/render-source.ts +90 -0
- package/src/scene/source-systems.ts +33 -0
- package/src/systems/skin-palette-allocator.ts +1 -0
- package/src/systems/skin-palette-types.ts +11 -0
- package/src/systems/transparent-dispatch.ts +2 -2
- package/src/systems/transparent-sort-config.ts +3 -1
- package/dist/chunk-BLXGONR2.mjs.map +0 -1
- package/dist/chunk-ELJFJ2BU.mjs.map +0 -1
- package/dist/chunk-ILQ5MEZF.mjs +0 -32
- package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
- package/dist/chunk-MKDIT2EM.mjs.map +0 -1
- package/dist/chunk-OCDLEI6I.mjs.map +0 -1
- package/dist/chunk-ODZWR6JQ.mjs.map +0 -1
- package/dist/chunk-RXZ3RGOU.mjs +0 -53
- package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
- package/dist/chunk-SHFUFJ5N.mjs +0 -1781
- package/dist/chunk-SHFUFJ5N.mjs.map +0 -1
- package/dist/chunk-UI5SFODX.mjs.map +0 -1
- package/dist/chunk-UINHLCZA.mjs +0 -2389
- package/dist/chunk-UINHLCZA.mjs.map +0 -1
- package/dist/chunk-WEX45HKH.mjs +0 -1524
- package/dist/chunk-WEX45HKH.mjs.map +0 -1
|
@@ -1,29 +1,17 @@
|
|
|
1
1
|
import { RuntimeMaterialValue, RuntimeMeshVertices } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { EntityHandle,
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type StateProjectionBatch,
|
|
2
|
+
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
3
|
+
import type {
|
|
4
|
+
RenderReadLease,
|
|
5
|
+
RenderReadVersion,
|
|
6
|
+
StateProjection,
|
|
7
|
+
StateProjectionBatch,
|
|
9
8
|
} from '@forgeax/engine-ecs/projection';
|
|
10
9
|
import { box3, frustum, mat4 } from '@forgeax/engine-math';
|
|
11
10
|
import { type RhiDevice, RhiError } from '@forgeax/engine-rhi';
|
|
12
|
-
import { ChildOf, Children, GlobalTransform, MorphWeights
|
|
11
|
+
import { ChildOf, Children, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
|
|
13
12
|
import { Skin } from '@forgeax/engine-skinning';
|
|
14
13
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
15
|
-
import {
|
|
16
|
-
Instances,
|
|
17
|
-
Layer,
|
|
18
|
-
Lines,
|
|
19
|
-
MeshFilter,
|
|
20
|
-
MeshRenderer,
|
|
21
|
-
Points,
|
|
22
|
-
SortKey,
|
|
23
|
-
SpriteInstances,
|
|
24
|
-
SpriteRegionOverride,
|
|
25
|
-
Visibility,
|
|
26
|
-
} from '../components';
|
|
14
|
+
import { Instances, Lines, Points, SpriteInstances, Visibility } from '../components';
|
|
27
15
|
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
28
16
|
import { gpuDrivenShadowDrawKey } from '../extract/gpu-driven';
|
|
29
17
|
import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
|
|
@@ -41,6 +29,8 @@ import type { InstanceProjectionStore } from '../instances';
|
|
|
41
29
|
import { fingerprintNumericArray, InstanceBoundsCache } from '../instances-derived-bounds';
|
|
42
30
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
43
31
|
import type { PointsLinesRetainedSnapshot } from '../points-lines/snapshot';
|
|
32
|
+
import type { PreparedRenderPublication } from '../publication/receiver';
|
|
33
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
44
34
|
import { worldEntityKey } from '../record/frame-snapshot';
|
|
45
35
|
import {
|
|
46
36
|
type ReflectionProbeFact,
|
|
@@ -76,6 +66,13 @@ import type {
|
|
|
76
66
|
RenderSceneResyncReason,
|
|
77
67
|
RenderSceneSlot,
|
|
78
68
|
} from './render-scene-types';
|
|
69
|
+
import {
|
|
70
|
+
createGlobalTransformChangeQuery,
|
|
71
|
+
createRenderSourceState,
|
|
72
|
+
type GlobalTransformChangeQuery,
|
|
73
|
+
isRenderableMember,
|
|
74
|
+
RENDERABLE_SOURCE_COMPONENTS,
|
|
75
|
+
} from './render-source';
|
|
79
76
|
import { buildShadowFrusta } from './shadow-visibility';
|
|
80
77
|
import { createVisibilityBudget, type VisibilityBudget } from './visibility/budget';
|
|
81
78
|
import {
|
|
@@ -118,8 +115,6 @@ interface WorldTransformSpan {
|
|
|
118
115
|
readonly worlds: Readonly<Float32Array>;
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
type GlobalTransformChangeQuery = Query<readonly [typeof GlobalTransform]>;
|
|
122
|
-
|
|
123
118
|
function sameInstanceIdentitySet(
|
|
124
119
|
current: Uint32Array | undefined,
|
|
125
120
|
previous: Uint32Array | undefined,
|
|
@@ -1151,7 +1146,7 @@ type PersistentGpuSceneInspection = PersistentRenderSceneInspection['gpu'];
|
|
|
1151
1146
|
|
|
1152
1147
|
interface PersistentCompositionEntry {
|
|
1153
1148
|
readonly token: object;
|
|
1154
|
-
readonly worlds: readonly
|
|
1149
|
+
readonly worlds: readonly RenderResourceScope[];
|
|
1155
1150
|
readonly projection: RenderScene;
|
|
1156
1151
|
readonly topology: BatchTopology;
|
|
1157
1152
|
readonly transmissionDemand: PersistentTransmissionDemandProjection;
|
|
@@ -1187,73 +1182,6 @@ interface PersistentCompositionEntry {
|
|
|
1187
1182
|
gpuDrivenSceneRequired: boolean;
|
|
1188
1183
|
}
|
|
1189
1184
|
|
|
1190
|
-
// Retained geometry consumes these component changes. Camera, lighting and
|
|
1191
|
-
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
1192
|
-
// their edits must not recreate unrelated geometry or its submission history.
|
|
1193
|
-
const RENDERABLE_SOURCE_COMPONENTS = [
|
|
1194
|
-
ChildOf,
|
|
1195
|
-
MeshFilter,
|
|
1196
|
-
MeshRenderer,
|
|
1197
|
-
Instances,
|
|
1198
|
-
SpriteInstances,
|
|
1199
|
-
SpriteRegionOverride,
|
|
1200
|
-
Skin,
|
|
1201
|
-
Layer,
|
|
1202
|
-
Visibility,
|
|
1203
|
-
MorphWeights,
|
|
1204
|
-
Points,
|
|
1205
|
-
Lines,
|
|
1206
|
-
SortKey,
|
|
1207
|
-
] as const;
|
|
1208
|
-
function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
1209
|
-
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
1210
|
-
if (!result.ok) throw result.error;
|
|
1211
|
-
const query = result.value as GlobalTransformChangeQuery;
|
|
1212
|
-
for (const _span of query.spans().unwrap()) {
|
|
1213
|
-
// The full rebuild consumed these values; establish the observation baseline.
|
|
1214
|
-
}
|
|
1215
|
-
return query;
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
function createRenderSourceState(world: World) {
|
|
1219
|
-
// Numerical poses already have one span reader. Keep their table membership
|
|
1220
|
-
// in this projection, without scanning their changed rows a second time.
|
|
1221
|
-
const components = [...RENDERABLE_SOURCE_COMPONENTS, RuntimeMaterialValue, RuntimeMeshVertices];
|
|
1222
|
-
const projection = createStateProjection(world, components, [
|
|
1223
|
-
...components,
|
|
1224
|
-
Transform,
|
|
1225
|
-
GlobalTransform,
|
|
1226
|
-
]);
|
|
1227
|
-
const entities = new Map<number, EntityHandle>();
|
|
1228
|
-
const contentHandles = new Map<number, readonly number[]>();
|
|
1229
|
-
const batch = projection.read();
|
|
1230
|
-
for (const index of batch.indices) {
|
|
1231
|
-
const entity = projection.entity(index);
|
|
1232
|
-
if (entity !== undefined) {
|
|
1233
|
-
entities.set(index, entity);
|
|
1234
|
-
const handles: number[] = [];
|
|
1235
|
-
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
1236
|
-
? world.get(entity, RuntimeMaterialValue)
|
|
1237
|
-
: undefined;
|
|
1238
|
-
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
1239
|
-
? world.get(entity, RuntimeMeshVertices)
|
|
1240
|
-
: undefined;
|
|
1241
|
-
if (material?.ok) handles.push(Number(material.value.asset));
|
|
1242
|
-
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
1243
|
-
if (handles.length > 0) contentHandles.set(index, handles);
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
return { projection, entities, contentHandles, batch };
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
function isRenderableMember(world: World, entity: number): boolean {
|
|
1250
|
-
return (
|
|
1251
|
-
world.hasComponent(entity as EntityHandle, MeshRenderer) &&
|
|
1252
|
-
world.hasComponent(entity as EntityHandle, Transform) &&
|
|
1253
|
-
world.hasComponent(entity as EntityHandle, MeshFilter)
|
|
1254
|
-
);
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
1185
|
function sourceMembershipChanged(world: World, slot: RenderSceneSlot): boolean {
|
|
1258
1186
|
const entity = slot.entityKey as EntityHandle;
|
|
1259
1187
|
const snapshot = slot.snapshot;
|
|
@@ -1608,7 +1536,7 @@ export class PersistentRenderScene {
|
|
|
1608
1536
|
return this.visibilityBudget;
|
|
1609
1537
|
}
|
|
1610
1538
|
|
|
1611
|
-
private visibilityWorldKey(world:
|
|
1539
|
+
private visibilityWorldKey(world: RenderResourceScope | undefined, fallback: number): number {
|
|
1612
1540
|
if (world === undefined) return fallback;
|
|
1613
1541
|
const existing = this.visibilityWorldKeys.get(world.identity);
|
|
1614
1542
|
if (existing !== undefined) return existing;
|
|
@@ -1618,12 +1546,12 @@ export class PersistentRenderScene {
|
|
|
1618
1546
|
return key;
|
|
1619
1547
|
}
|
|
1620
1548
|
|
|
1621
|
-
private worldKeyAt(worlds: readonly
|
|
1549
|
+
private worldKeyAt(worlds: readonly RenderResourceScope[], worldId: number): number {
|
|
1622
1550
|
return this.visibilityWorldKey(worlds[worldId], worldId);
|
|
1623
1551
|
}
|
|
1624
1552
|
|
|
1625
1553
|
/** Stable World routing keys for the current worlds[] frame projection. */
|
|
1626
|
-
visibilityWorldKeysFor(worlds: readonly
|
|
1554
|
+
visibilityWorldKeysFor(worlds: readonly RenderResourceScope[]): readonly number[] {
|
|
1627
1555
|
return worlds.map((world, worldId) => this.visibilityWorldKey(world, worldId));
|
|
1628
1556
|
}
|
|
1629
1557
|
|
|
@@ -1632,6 +1560,10 @@ export class PersistentRenderScene {
|
|
|
1632
1560
|
return this.composition?.projection.slotsSnapshot() ?? [];
|
|
1633
1561
|
}
|
|
1634
1562
|
|
|
1563
|
+
compositionSlot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
1564
|
+
return this.composition?.projection.slot(worldId, entityKey);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1635
1567
|
shadowCasterProjection(): PersistentShadowCasterProjection | undefined {
|
|
1636
1568
|
return this.shadowProjection;
|
|
1637
1569
|
}
|
|
@@ -1642,7 +1574,7 @@ export class PersistentRenderScene {
|
|
|
1642
1574
|
}
|
|
1643
1575
|
|
|
1644
1576
|
private stableEntityKey(
|
|
1645
|
-
worlds: readonly
|
|
1577
|
+
worlds: readonly RenderResourceScope[],
|
|
1646
1578
|
renderable: Pick<RenderableSnapshot, 'worldId' | 'entityKey'>,
|
|
1647
1579
|
): number {
|
|
1648
1580
|
return worldEntityKey(this.worldKeyAt(worlds, renderable.worldId), renderable.entityKey);
|
|
@@ -1650,7 +1582,7 @@ export class PersistentRenderScene {
|
|
|
1650
1582
|
|
|
1651
1583
|
/** Feed the facet from extracted renderables using persistent slot identity. */
|
|
1652
1584
|
updateVisibilityFacet(
|
|
1653
|
-
worlds: readonly
|
|
1585
|
+
worlds: readonly RenderResourceScope[],
|
|
1654
1586
|
camera: CameraSnapshot | undefined,
|
|
1655
1587
|
renderables: readonly RenderableSnapshot[],
|
|
1656
1588
|
): void {
|
|
@@ -1710,7 +1642,7 @@ export class PersistentRenderScene {
|
|
|
1710
1642
|
* visible through `decideVisibility`.
|
|
1711
1643
|
*/
|
|
1712
1644
|
projectVisibility(
|
|
1713
|
-
worlds: readonly
|
|
1645
|
+
worlds: readonly RenderResourceScope[],
|
|
1714
1646
|
camera: CameraSnapshot | undefined,
|
|
1715
1647
|
renderables: readonly RenderableSnapshot[],
|
|
1716
1648
|
dispatch: readonly DispatchEntry[],
|
|
@@ -1884,6 +1816,77 @@ export class PersistentRenderScene {
|
|
|
1884
1816
|
return this.reflectionProbes.snapshot();
|
|
1885
1817
|
}
|
|
1886
1818
|
|
|
1819
|
+
consumePublication(input: PreparedRenderPublication): ExtractedFrame {
|
|
1820
|
+
const { resources, packet, frame } = input;
|
|
1821
|
+
let entry = this.composition;
|
|
1822
|
+
if (entry === undefined || packet.baseline) {
|
|
1823
|
+
this.invalidate();
|
|
1824
|
+
const projection = new RenderScene();
|
|
1825
|
+
entry = {
|
|
1826
|
+
token: {},
|
|
1827
|
+
worlds: [resources],
|
|
1828
|
+
projection,
|
|
1829
|
+
topology: new BatchTopology(),
|
|
1830
|
+
transmissionDemand: new PersistentTransmissionDemandProjection(),
|
|
1831
|
+
hiddenEntityReports: [],
|
|
1832
|
+
worldKeys: this.visibilityWorldKeysFor([resources]),
|
|
1833
|
+
readVersions: [],
|
|
1834
|
+
leaseIdentities: [],
|
|
1835
|
+
transformQueries: [],
|
|
1836
|
+
sourceStates: [],
|
|
1837
|
+
dispatchBySlot: new Map(),
|
|
1838
|
+
dispatchRevision: 0,
|
|
1839
|
+
dispatchCache: undefined,
|
|
1840
|
+
skinConsumersByJoint: new Map(),
|
|
1841
|
+
pendingRenderableEntitiesByWorld: [],
|
|
1842
|
+
unavailableSlots: new Set(),
|
|
1843
|
+
catalogEpoch: 0,
|
|
1844
|
+
probeProjection: new ProbeBlendSceneProjection(),
|
|
1845
|
+
probeObjects: undefined,
|
|
1846
|
+
temporalDemanded: false,
|
|
1847
|
+
gpuDrivenSceneRequired: true,
|
|
1848
|
+
};
|
|
1849
|
+
this.composition = entry;
|
|
1850
|
+
this.fullRebuilds++;
|
|
1851
|
+
this.lastResyncReason = 'attach';
|
|
1852
|
+
}
|
|
1853
|
+
this.worldEntitiesScanned = 0;
|
|
1854
|
+
this.sceneTableUploadBytes = 0;
|
|
1855
|
+
const removedDemand: TransmissionDemandOperation[] = [];
|
|
1856
|
+
for (const operation of input.operations) {
|
|
1857
|
+
if (operation.kind !== 'remove' && operation.snapshot === undefined) continue;
|
|
1858
|
+
const previous = entry.projection.slot(0, operation.entityKey);
|
|
1859
|
+
for (let index = 0; index < (previous?.snapshot.materials.length ?? 0); index++)
|
|
1860
|
+
removedDemand.push({ kind: 'remove', key: `0:${operation.entityKey}:${index}` });
|
|
1861
|
+
}
|
|
1862
|
+
const delta = entry.projection.apply(input.operations);
|
|
1863
|
+
for (const removed of delta.removedSlots) {
|
|
1864
|
+
entry.dispatchBySlot.delete(removed.slot);
|
|
1865
|
+
this.stableSlotByEntity.delete(worldEntityKey(entry.worldKeys[0] ?? 0, removed.entityKey));
|
|
1866
|
+
}
|
|
1867
|
+
for (const recreated of delta.recreatedSlots) entry.dispatchBySlot.delete(recreated.slot);
|
|
1868
|
+
for (const [slot, dispatch] of dispatchEntriesBySlot(frame, entry.projection))
|
|
1869
|
+
entry.dispatchBySlot.set(slot, dispatch);
|
|
1870
|
+
if (frame.renderables.length || packet.removed.length) {
|
|
1871
|
+
entry.dispatchRevision++;
|
|
1872
|
+
entry.dispatchCache = undefined;
|
|
1873
|
+
this.visibilityFacets.clear();
|
|
1874
|
+
this.invalidateActiveEntityRevision();
|
|
1875
|
+
}
|
|
1876
|
+
for (const slot of [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots])
|
|
1877
|
+
this.stableSlotByEntity.set(worldEntityKey(entry.worldKeys[0] ?? 0, slot.entityKey), slot);
|
|
1878
|
+
entry.transmissionDemand.apply([
|
|
1879
|
+
...removedDemand,
|
|
1880
|
+
...transmissionDemandOperations(frame.renderables),
|
|
1881
|
+
]);
|
|
1882
|
+
entry.topology.apply(delta);
|
|
1883
|
+
this.syncGpuOwner(entry.token, entry.projection, delta);
|
|
1884
|
+
if (input.operations.length) this.deltaFrames++;
|
|
1885
|
+
else this.noChangeFrames++;
|
|
1886
|
+
this.transformUpdates += delta.updated;
|
|
1887
|
+
return this.deriveFramePlan(entry, frame);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1887
1890
|
extractComposition(
|
|
1888
1891
|
worlds: readonly World[],
|
|
1889
1892
|
owner: { readonly cameraOwner: number; readonly resourceOwner: number },
|
|
@@ -1897,7 +1900,7 @@ export class PersistentRenderScene {
|
|
|
1897
1900
|
const sameWorldSet =
|
|
1898
1901
|
entry !== undefined &&
|
|
1899
1902
|
entry.worlds.length === worlds.length &&
|
|
1900
|
-
entry.worlds.every((world) => worlds.
|
|
1903
|
+
entry.worlds.every((world) => worlds.some((local) => local === world));
|
|
1901
1904
|
const worldOrderChanged =
|
|
1902
1905
|
entry !== undefined &&
|
|
1903
1906
|
sameWorldSet &&
|
|
@@ -2708,7 +2711,7 @@ export class PersistentRenderScene {
|
|
|
2708
2711
|
preserveVisibilityOnReorder = false,
|
|
2709
2712
|
): ExtractedFrame {
|
|
2710
2713
|
const previousEntry = this.composition;
|
|
2711
|
-
const sourceStates = worlds.map(createRenderSourceState);
|
|
2714
|
+
const sourceStates = worlds.map((world) => createRenderSourceState(world));
|
|
2712
2715
|
const candidateFrame = buildCandidateFrame({
|
|
2713
2716
|
kind: 'partial',
|
|
2714
2717
|
entitiesByWorld: sourceStates.map((source) => new Set(source.entities.values())),
|
|
@@ -2745,7 +2748,11 @@ export class PersistentRenderScene {
|
|
|
2745
2748
|
const renderables = candidateFrame.renderables;
|
|
2746
2749
|
const projection = previousEntry?.projection ?? new RenderScene();
|
|
2747
2750
|
if (previousEntry !== undefined) {
|
|
2748
|
-
projection.remapWorlds(
|
|
2751
|
+
projection.remapWorlds(
|
|
2752
|
+
previousEntry.worlds.map((world) =>
|
|
2753
|
+
(worlds as readonly RenderResourceScope[]).indexOf(world),
|
|
2754
|
+
),
|
|
2755
|
+
);
|
|
2749
2756
|
}
|
|
2750
2757
|
const desired = new Set(
|
|
2751
2758
|
renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey)),
|
|
@@ -2895,7 +2902,10 @@ export class PersistentRenderScene {
|
|
|
2895
2902
|
const candidateFrame: ExtractedFrame = {
|
|
2896
2903
|
...resourceFrame,
|
|
2897
2904
|
hiddenEntityReports: entry.hiddenEntityReports,
|
|
2898
|
-
visibilityStats:
|
|
2905
|
+
visibilityStats:
|
|
2906
|
+
entry.sourceStates.length === 0
|
|
2907
|
+
? resourceFrame.visibilityStats
|
|
2908
|
+
: { explicitlyHidden: entry.hiddenEntityReports.length },
|
|
2899
2909
|
dispatch,
|
|
2900
2910
|
};
|
|
2901
2911
|
entry.temporalDemanded = frameDemandsTemporal(candidateFrame);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { RuntimeMaterialValue, RuntimeMeshVertices } from '@forgeax/engine-assets-runtime';
|
|
2
|
+
import type { Component, EntityHandle, Query, World } from '@forgeax/engine-ecs';
|
|
3
|
+
import { createStateProjection } from '@forgeax/engine-ecs/projection';
|
|
4
|
+
import { ChildOf, GlobalTransform, MorphWeights, Transform } from '@forgeax/engine-scene';
|
|
5
|
+
import { Skin } from '@forgeax/engine-skinning';
|
|
6
|
+
import {
|
|
7
|
+
Instances,
|
|
8
|
+
Layer,
|
|
9
|
+
Lines,
|
|
10
|
+
MeshFilter,
|
|
11
|
+
MeshRenderer,
|
|
12
|
+
Points,
|
|
13
|
+
SortKey,
|
|
14
|
+
SpriteInstances,
|
|
15
|
+
SpriteRegionOverride,
|
|
16
|
+
Visibility,
|
|
17
|
+
} from '../components';
|
|
18
|
+
export type GlobalTransformChangeQuery = Query<readonly [typeof GlobalTransform]>;
|
|
19
|
+
|
|
20
|
+
// Retained geometry consumes these component changes. Camera, lighting and
|
|
21
|
+
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
22
|
+
// their edits must not recreate unrelated geometry or its submission history.
|
|
23
|
+
export const RENDERABLE_SOURCE_COMPONENTS = [
|
|
24
|
+
ChildOf,
|
|
25
|
+
MeshFilter,
|
|
26
|
+
MeshRenderer,
|
|
27
|
+
Instances,
|
|
28
|
+
SpriteInstances,
|
|
29
|
+
SpriteRegionOverride,
|
|
30
|
+
Skin,
|
|
31
|
+
Layer,
|
|
32
|
+
Visibility,
|
|
33
|
+
MorphWeights,
|
|
34
|
+
Points,
|
|
35
|
+
Lines,
|
|
36
|
+
SortKey,
|
|
37
|
+
] as const;
|
|
38
|
+
export function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
39
|
+
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
40
|
+
if (!result.ok) throw result.error;
|
|
41
|
+
const query = result.value as GlobalTransformChangeQuery;
|
|
42
|
+
for (const _span of query.spans().unwrap()) {
|
|
43
|
+
// The full rebuild consumed these values; establish the observation baseline.
|
|
44
|
+
}
|
|
45
|
+
return query;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function createRenderSourceState(world: World, additional: readonly Component[] = []) {
|
|
49
|
+
// Numerical poses already have one span reader. Keep their table membership
|
|
50
|
+
// in this projection, without scanning their changed rows a second time.
|
|
51
|
+
const components = [
|
|
52
|
+
...RENDERABLE_SOURCE_COMPONENTS,
|
|
53
|
+
RuntimeMaterialValue,
|
|
54
|
+
RuntimeMeshVertices,
|
|
55
|
+
...additional,
|
|
56
|
+
];
|
|
57
|
+
const projection = createStateProjection(world, components, [
|
|
58
|
+
...components,
|
|
59
|
+
Transform,
|
|
60
|
+
GlobalTransform,
|
|
61
|
+
]);
|
|
62
|
+
const entities = new Map<number, EntityHandle>();
|
|
63
|
+
const contentHandles = new Map<number, readonly number[]>();
|
|
64
|
+
const batch = projection.read();
|
|
65
|
+
for (const index of batch.indices) {
|
|
66
|
+
const entity = projection.entity(index);
|
|
67
|
+
if (entity !== undefined) {
|
|
68
|
+
entities.set(index, entity);
|
|
69
|
+
const handles: number[] = [];
|
|
70
|
+
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
71
|
+
? world.get(entity, RuntimeMaterialValue)
|
|
72
|
+
: undefined;
|
|
73
|
+
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
74
|
+
? world.get(entity, RuntimeMeshVertices)
|
|
75
|
+
: undefined;
|
|
76
|
+
if (material?.ok) handles.push(Number(material.value.asset));
|
|
77
|
+
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
78
|
+
if (handles.length > 0) contentHandles.set(index, handles);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { projection, entities, contentHandles, batch };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isRenderableMember(world: World, entity: number): boolean {
|
|
85
|
+
return (
|
|
86
|
+
world.hasComponent(entity as EntityHandle, MeshRenderer) &&
|
|
87
|
+
world.hasComponent(entity as EntityHandle, Transform) &&
|
|
88
|
+
world.hasComponent(entity as EntityHandle, MeshFilter)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
2
|
+
import { Update, type World } from '@forgeax/engine-ecs';
|
|
3
|
+
import { registerPropagateTransforms } from '@forgeax/engine-scene';
|
|
4
|
+
import type { GpuResidencyCache } from '../device/gpu-residency';
|
|
5
|
+
import { glyphTextLayoutSystem } from '../glyph-text-layout-system';
|
|
6
|
+
import { tilemapChunkExtractSystem } from '../tilemap-chunk-extract-system';
|
|
7
|
+
|
|
8
|
+
let nextId = 0;
|
|
9
|
+
/** Derived authoring stays beside World; only completed mesh data reaches the Renderer. */
|
|
10
|
+
export function registerRenderSourceSystems(
|
|
11
|
+
world: World,
|
|
12
|
+
assets: AssetRegistry,
|
|
13
|
+
meshes: Pick<GpuResidencyCache, 'updateMesh'>,
|
|
14
|
+
): () => void {
|
|
15
|
+
const releaseTransforms = registerPropagateTransforms(world);
|
|
16
|
+
const name = `renderDerived:${++nextId}`;
|
|
17
|
+
const result = world.addSystem(Update, {
|
|
18
|
+
name,
|
|
19
|
+
queries: [],
|
|
20
|
+
fn: (world) => {
|
|
21
|
+
tilemapChunkExtractSystem(world, (guid) => assets.lookup(guid));
|
|
22
|
+
glyphTextLayoutSystem(world, meshes).unwrap();
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
if (!result.ok) {
|
|
26
|
+
releaseTransforms();
|
|
27
|
+
throw result.error;
|
|
28
|
+
}
|
|
29
|
+
return () => {
|
|
30
|
+
world.removeSystem(Update, name).unwrap();
|
|
31
|
+
releaseTransforms();
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -460,6 +460,7 @@ export function createSkinPaletteAllocator(
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
function releasePersistentSlice(identity: string): void {
|
|
463
|
+
frameSeenPersistent.delete(identity);
|
|
463
464
|
const allocation = persistent.get(identity);
|
|
464
465
|
persistent.delete(identity);
|
|
465
466
|
pendingDirty.delete(identity);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Mat4 } from '@forgeax/engine-math';
|
|
1
2
|
import type { Buffer } from '@forgeax/engine-rhi';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -29,3 +30,13 @@ export interface SkinPaletteReceipt extends SkinPaletteSlice {
|
|
|
29
30
|
readonly uploadBytes: number;
|
|
30
31
|
readonly retiredByteOffset?: number;
|
|
31
32
|
}
|
|
33
|
+
|
|
34
|
+
/** Frozen source facts; GPU addresses are assigned only by the consuming Renderer. */
|
|
35
|
+
export interface SkinPose {
|
|
36
|
+
readonly identity: string;
|
|
37
|
+
readonly generation: number;
|
|
38
|
+
readonly jointCount: number;
|
|
39
|
+
readonly bounds?: Float32Array;
|
|
40
|
+
readonly inverseBindMatrices: readonly Float32Array[];
|
|
41
|
+
readonly jointWorlds: readonly Mat4[];
|
|
42
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
2
1
|
import { RenderQueue } from '@forgeax/engine-types';
|
|
2
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
3
3
|
import type { CameraSnapshot } from '../render-contract';
|
|
4
4
|
import type { DispatchEntry, RenderableSnapshot } from '../render-system-extract';
|
|
5
5
|
import {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
*/
|
|
17
17
|
export function sortTransparentDispatch(
|
|
18
18
|
dispatch: DispatchEntry[],
|
|
19
|
-
world:
|
|
19
|
+
world: RenderResourceScope,
|
|
20
20
|
cameras: readonly CameraSnapshot[],
|
|
21
21
|
renderables: readonly RenderableSnapshot[],
|
|
22
22
|
): DispatchEntry[] {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
1
2
|
// @forgeax/engine-runtime - TransparentSortConfig KV resource + helpers.
|
|
2
3
|
//
|
|
3
4
|
// feat-20260520-2d-sprite-layer-mvp M-2 w14 / requirements AC-08 + AC-18
|
|
@@ -168,7 +169,8 @@ const HINT_MODE = '0=layer-z, 1=layer-y, 2=layer-yz, 3=distance';
|
|
|
168
169
|
* const cfg = getTransparentSortConfig(world);
|
|
169
170
|
* // cfg.mode === 1, cfg.yzAlpha === 1.0 (yzAlpha ignored by mode=1).
|
|
170
171
|
*/
|
|
171
|
-
export function getTransparentSortConfig(world:
|
|
172
|
+
export function getTransparentSortConfig(world: RenderResourceScope): TransparentSortConfig {
|
|
173
|
+
if ('resolveAsset' in world) return world.transparentSort;
|
|
172
174
|
if (!world.hasResource(TRANSPARENT_SORT_CONFIG_KEY)) {
|
|
173
175
|
return DEFAULT_CONFIG;
|
|
174
176
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/assembly/material/surface-projection.ts","../src/materials.ts"],"names":["pass"],"mappings":"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","file":"chunk-BLXGONR2.mjs","sourcesContent":["import { DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';\nimport type {\n MaterialPass,\n MaterialRenderState,\n MaterialValue,\n StandardLayerPlan,\n} from '@forgeax/engine-types';\n\nexport const STANDARD_MATERIAL_MODULE = 'forgeax_material::standard';\nexport { DEFAULT_STANDARD_SURFACE_MODULE };\n\nexport type StandardSurfacePassName = 'forward' | 'deferred' | 'shadow-caster';\nexport type StandardSurfaceGeometryVariant = 'rigid' | 'skinned' | 'instanced';\nexport type StandardSurfaceLightingLane = 'direct' | 'clustered';\nexport type StandardSurfaceKind = 'standard' | 'full-custom';\n\nexport interface StandardSurfaceProjectionOptions {\n readonly surfaceModule: string;\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n readonly renderState?: MaterialRenderState;\n readonly castShadow?: boolean;\n readonly queue?: number;\n readonly geometryVariant?: StandardSurfaceGeometryVariant;\n readonly lightingLane?: StandardSurfaceLightingLane;\n readonly alphaClip?: boolean;\n readonly surfaceKind?: StandardSurfaceKind;\n readonly declaredPasses?: readonly StandardSurfacePassName[];\n readonly layerPlan?: StandardLayerPlan;\n}\n\nfunction pass(\n name: StandardSurfacePassName,\n options: StandardSurfaceProjectionOptions,\n fragmentEntry: string,\n): MaterialPass {\n const authoredState = options.renderState ?? {};\n const authoredRecord = authoredState as Readonly<Record<string, unknown>>;\n const tags = (authoredRecord.tags ?? {}) as Readonly<Record<string, string>>;\n const lightMode =\n name === 'shadow-caster' ? 'ShadowCaster' : name === 'forward' ? 'Forward' : 'Deferred';\n return {\n name,\n program: {\n module:\n name === 'shadow-caster' ? 'forgeax::default-shadow-caster' : STANDARD_MATERIAL_MODULE,\n fragmentEntry,\n moduleSlots: { surface: options.surfaceModule },\n },\n renderState: {\n ...authoredState,\n tags:\n options.surfaceModule === DEFAULT_STANDARD_SURFACE_MODULE\n ? { LightMode: lightMode, ...tags }\n : {\n ...tags,\n LightMode: lightMode,\n SurfaceModule: options.surfaceModule,\n SurfaceKind: options.surfaceKind ?? 'standard',\n GeometryVariant: options.geometryVariant ?? 'rigid',\n LightingLane: options.lightingLane ?? 'direct',\n AlphaClip: options.alphaClip === true ? 'enabled' : 'disabled',\n },\n ...(options.queue === undefined ? {} : { queue: options.queue }),\n },\n };\n}\n\n/** Project one custom or default Surface into the existing Standard pass family. */\nexport function projectStandardSurfacePasses(\n options: StandardSurfaceProjectionOptions,\n): [MaterialPass, ...MaterialPass[]] {\n const authoredPasses = options.declaredPasses;\n const passNames: StandardSurfacePassName[] =\n options.surfaceKind === 'full-custom' && authoredPasses !== undefined\n ? [...authoredPasses]\n : (['forward'] as StandardSurfacePassName[]);\n if (authoredPasses === undefined || options.surfaceKind !== 'full-custom') {\n const blended = options.renderState?.blend !== undefined;\n if (!blended && options.layerPlan?.mode !== 'physical') passNames.push('deferred');\n if (options.castShadow !== false) passNames.push('shadow-caster');\n }\n const entries = passNames.map((name) =>\n pass(\n name,\n options,\n name === 'forward' ? 'fs_main' : name === 'deferred' ? 'fs_gbuffer' : 'fs_shadow',\n ),\n );\n const passes = entries as [MaterialPass, ...MaterialPass[]];\n return passes;\n}\n","import { color } from '@forgeax/engine-math';\nimport { DEFAULT_STANDARD_PBR_PARAM_SCHEMA } from '@forgeax/engine-shader';\nimport type {\n MaterialAsset,\n MaterialColorSpace,\n MaterialParameter,\n MaterialPass,\n MaterialRenderState,\n MaterialValue,\n} from '@forgeax/engine-types';\nimport { deriveStandardLayerPlan, standardSurfaceParameters } from '@forgeax/engine-types';\nimport {\n DEFAULT_STANDARD_SURFACE_MODULE,\n projectStandardSurfacePasses,\n} from './assembly/material/surface-projection';\n\nexport type MaterialTransmissionValidationReason =\n | 'non-finite'\n | 'range'\n | 'shape'\n | 'blend'\n | 'depth-write';\n\nexport type MaterialAuthoringValidationReason = 'non-finite' | 'range';\n\n/** Structured authoring failure for a built-in Standard material parameter. */\nexport class MaterialAuthoringContractError extends Error {\n readonly code = 'material-authoring-contract-invalid' as const;\n readonly expected =\n 'Standard material authoring values are finite and within their declared ranges';\n readonly hint =\n 'repair the named Standard material parameter alphaCutoff before publishing the material';\n readonly detail: {\n readonly code: 'material-authoring-contract-invalid';\n readonly material: 'Standard';\n readonly parameter: 'alphaCutoff';\n readonly reason: MaterialAuthoringValidationReason;\n readonly actual?: unknown;\n };\n\n constructor(reason: MaterialAuthoringValidationReason, actual?: unknown) {\n super(`Materials.standard: alphaCutoff violates the authoring contract (${reason})`);\n this.name = 'MaterialAuthoringContractError';\n this.detail = {\n code: 'material-authoring-contract-invalid',\n material: 'Standard',\n parameter: 'alphaCutoff',\n reason,\n ...(actual === undefined ? {} : { actual }),\n };\n }\n}\n\n/** Structured authoring failure for the Standard transmission contract. */\nexport class MaterialTransmissionContractError extends Error {\n readonly code = 'material-transmission-contract-invalid' as const;\n readonly expected = 'transmission material values satisfy finite ranges and Forward depth rules';\n readonly hint =\n 'repair the named transmission value or pass state before publishing the material';\n readonly detail: {\n readonly code: 'material-transmission-contract-invalid';\n readonly material: 'Standard';\n readonly parameter:\n | 'transmission'\n | 'ior'\n | 'thickness'\n | 'attenuationColor'\n | 'attenuationDistance';\n readonly reason: MaterialTransmissionValidationReason;\n readonly actual?: unknown;\n };\n\n constructor(\n parameter: (typeof MaterialTransmissionContractError.prototype.detail)['parameter'],\n reason: MaterialTransmissionValidationReason,\n actual?: unknown,\n ) {\n super(`Materials.standard: ${parameter} violates the transmission contract (${reason})`);\n this.name = 'MaterialTransmissionContractError';\n this.detail = {\n code: 'material-transmission-contract-invalid',\n material: 'Standard',\n parameter,\n reason,\n ...(actual === undefined ? {} : { actual }),\n };\n }\n}\n\nexport const SPRITE_PREMULTIPLIED_ALPHA_BLEND: GPUBlendState = {\n color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n};\n\nconst UNLIT_MODULE = 'forgeax_material::unlit';\nconst SPRITE_MODULE = 'forgeax_material::sprite';\n\nexport type MaterialColorTuple3 = readonly [number, number, number];\nexport type MaterialColorTuple4 = readonly [number, number, number, number];\nexport type MaterialColorInput3 = MaterialColorTuple3 | string | number;\nexport type MaterialColorInput4 = MaterialColorTuple4 | string | number;\n\nfunction colorHexFromNumber(value: number): string {\n if (!Number.isInteger(value) || value < 0 || value > 0xffffff) {\n throw new Error(`material color number must be an integer in [0, 0xffffff], got ${value}`);\n }\n return `#${value.toString(16).padStart(6, '0')}`;\n}\n\nfunction linearColorFromInput(\n input: MaterialColorInput3 | MaterialColorInput4,\n channels: 3 | 4,\n): readonly number[] {\n if (typeof input === 'number' || typeof input === 'string') {\n const parsed = color.create();\n color.fromCss(parsed, typeof input === 'number' ? colorHexFromNumber(input) : input);\n return channels === 3\n ? [parsed[0] as number, parsed[1] as number, parsed[2] as number]\n : Array.from(parsed);\n }\n if (input.length !== channels) {\n throw new Error(`material color tuple must contain ${channels} channels, got ${input.length}`);\n }\n return [...input];\n}\n\n/** Convert an explicit sRGB numeric tuple into the linear tuple factories store. */\nexport function srgb(input: MaterialColorTuple3): MaterialColorTuple3;\nexport function srgb(input: MaterialColorTuple4): MaterialColorTuple4;\nexport function srgb(input: readonly number[]): readonly number[] {\n if (input.length !== 3 && input.length !== 4) {\n throw new Error(`sRGB material color tuple must contain 3 or 4 channels, got ${input.length}`);\n }\n const parsed = color.create(input[0] ?? 0, input[1] ?? 0, input[2] ?? 0, input[3] ?? 1);\n color.srgbToLinear(parsed, parsed);\n return input.length === 3\n ? [parsed[0] as number, parsed[1] as number, parsed[2] as number]\n : [parsed[0] as number, parsed[1] as number, parsed[2] as number, parsed[3] as number];\n}\n\nfunction authoredColorParameter(\n name: string,\n type: 'color' | 'vec3',\n colorSpace: MaterialColorSpace,\n optional = false,\n): MaterialParameter {\n return {\n name,\n type,\n ...(type === 'color' && colorSpace === 'srgb' ? {} : { colorSpace }),\n ...(optional ? { optional: true } : {}),\n };\n}\n\nfunction standardParameters(\n colorSpace: MaterialColorSpace,\n opts: StandardOpts,\n): readonly MaterialParameter[] {\n const physicalNames = new Set<string>();\n const addPhysical = (...names: readonly string[]) => {\n for (const name of names) physicalNames.add(name);\n };\n if (\n opts.clearcoat !== undefined ||\n opts.clearcoatRoughness !== undefined ||\n opts.clearcoatNormalScale !== undefined ||\n opts.clearcoatTexture !== undefined ||\n opts.clearcoatRoughnessTexture !== undefined ||\n opts.clearcoatNormalTexture !== undefined\n ) {\n addPhysical(\n 'clearcoat',\n 'clearcoatRoughness',\n 'clearcoatNormalScale',\n ...(opts.clearcoatTexture === undefined ? [] : ['clearcoatTexture']),\n ...(opts.clearcoatRoughnessTexture === undefined ? [] : ['clearcoatRoughnessTexture']),\n ...(opts.clearcoatNormalTexture === undefined ? [] : ['clearcoatNormalTexture']),\n );\n }\n if (\n opts.anisotropyStrength !== undefined ||\n opts.anisotropyRotation !== undefined ||\n opts.anisotropyTexture !== undefined\n ) {\n addPhysical('anisotropyStrength', 'anisotropyRotation');\n if (opts.anisotropyTexture !== undefined) addPhysical('anisotropyTexture');\n }\n if (\n opts.sheenColor !== undefined ||\n opts.sheenRoughness !== undefined ||\n opts.sheenColorTexture !== undefined ||\n opts.sheenRoughnessTexture !== undefined\n ) {\n addPhysical('sheenColor', 'sheenRoughness');\n if (opts.sheenColorTexture !== undefined) addPhysical('sheenColorTexture');\n if (opts.sheenRoughnessTexture !== undefined) addPhysical('sheenRoughnessTexture');\n }\n if (\n opts.iridescence !== undefined ||\n opts.iridescenceIor !== undefined ||\n opts.iridescenceThicknessMinimum !== undefined ||\n opts.iridescenceThicknessMaximum !== undefined ||\n opts.iridescenceTexture !== undefined ||\n opts.iridescenceThicknessTexture !== undefined\n ) {\n addPhysical(\n 'iridescence',\n 'iridescenceIor',\n 'iridescenceThicknessMinimum',\n 'iridescenceThicknessMaximum',\n ...(opts.iridescenceTexture === undefined ? [] : ['iridescenceTexture']),\n ...(opts.iridescenceThicknessTexture === undefined ? [] : ['iridescenceThicknessTexture']),\n );\n }\n const baseNames = new Set([\n 'baseColor',\n 'metallic',\n 'roughness',\n 'metallicChannel',\n 'roughnessChannel',\n 'aoChannel',\n 'extraChannel',\n 'emissive',\n 'emissiveIntensity',\n 'occlusionStrength',\n 'alphaCutoff',\n 'normalScale',\n 'specular',\n 'specularColor',\n // IOR is part of the always-present dielectric F0 contract. The\n // transmission layer may be absent, but the Standard shader still\n // consumes this scalar for the base reflection path.\n 'ior',\n ]);\n if (opts.specularTexture !== undefined) baseNames.add('specularTexture');\n if (opts.specularColorTexture !== undefined) baseNames.add('specularColorTexture');\n if (\n opts.transmission !== undefined ||\n opts.ior !== undefined ||\n opts.thickness !== undefined ||\n opts.transmissionTexture !== undefined ||\n opts.thicknessTexture !== undefined ||\n opts.attenuationColor !== undefined ||\n opts.attenuationDistance !== undefined\n ) {\n for (const name of [\n 'transmission',\n 'ior',\n 'thickness',\n 'attenuationColor',\n 'attenuationDistance',\n ]) {\n baseNames.add(name);\n }\n }\n // A texture declaration selects its compiled sampling path. Loading state\n // does not: an authored but not-yet-resident slot still needs its fallback.\n for (const parameter of DEFAULT_STANDARD_PBR_PARAM_SCHEMA) {\n if (\n parameter.type === 'texture2d' &&\n opts[parameter.name as keyof StandardOpts] !== undefined\n ) {\n baseNames.add(parameter.name);\n }\n }\n // All Standard fields come from one root schema. Physical fields are\n // projected by the authored option membership above; appending a second\n // physical schema would create a parallel ABI authority.\n const availableSchema = DEFAULT_STANDARD_PBR_PARAM_SCHEMA;\n // Keep the generated Standard UBO's numeric run contiguous before any\n // texture coordinate records. The built-in WGSL places the complete\n // physical root (including clearcoat scalars) after the base numeric run\n // and before all coordinate pairs; appending physical entries after the\n // base texture records would otherwise derive a different ABI.\n const numericSchema = availableSchema.filter((entry) => !entry.type.startsWith('texture'));\n const textureSchema = availableSchema.filter((entry) => entry.type.startsWith('texture'));\n const orderedSchema = [...numericSchema, ...textureSchema];\n return orderedSchema\n .filter((entry) => baseNames.has(entry.name) || physicalNames.has(entry.name))\n .map((entry) => {\n const type = entry.type.startsWith('texture') ? 'texture' : entry.type;\n const isRequired =\n entry.name === 'baseColor' || entry.name === 'metallic' || entry.name === 'roughness';\n const authoredColor =\n entry.type === 'color' || (entry.type === 'vec3' && entry.name !== 'attenuationColor');\n const schemaColorSpace = 'colorSpace' in entry ? entry.colorSpace : undefined;\n const colorSpaceProjection: { colorSpace?: MaterialColorSpace } = {};\n if (authoredColor && !(type === 'color' && colorSpace === 'srgb')) {\n colorSpaceProjection.colorSpace = colorSpace;\n } else if (!authoredColor && schemaColorSpace !== undefined) {\n colorSpaceProjection.colorSpace = schemaColorSpace;\n }\n return {\n name: entry.name,\n type,\n ...colorSpaceProjection,\n ...(isRequired ? {} : { optional: true }),\n } as MaterialParameter;\n });\n}\n\nfunction unlitParameters(colorSpace: MaterialColorSpace): readonly MaterialParameter[] {\n return [\n authoredColorParameter('baseColor', 'color', colorSpace),\n { name: 'alphaCutoff', type: 'f32', optional: true },\n { name: 'baseColorTexture', type: 'texture', optional: true },\n ];\n}\n\nfunction pass(\n name: string,\n module: string,\n renderState: MaterialRenderState | undefined,\n fragmentEntry?: string,\n queue?: number,\n): MaterialPass {\n const lightMode =\n name === 'shadow-caster' ? 'ShadowCaster' : name === 'deferred' ? 'Deferred' : 'Forward';\n const authoredState = (renderState ?? {}) as Readonly<Record<string, unknown>>;\n const authoredTags = authoredState.tags as Readonly<Record<string, string>> | undefined;\n return {\n name,\n program: {\n module,\n ...(fragmentEntry === undefined ? {} : { fragmentEntry }),\n },\n renderState: {\n ...authoredState,\n tags: { LightMode: lightMode, ...authoredTags },\n ...(queue === undefined ? {} : { queue }),\n },\n };\n}\n\nfunction shadowCasterRenderState(\n renderState: MaterialRenderState | undefined,\n): MaterialRenderState | undefined {\n if (renderState?.cullMode === undefined && renderState?.frontFace === undefined) return undefined;\n return {\n ...(renderState.cullMode === undefined ? {} : { cullMode: renderState.cullMode }),\n ...(renderState.frontFace === undefined ? {} : { frontFace: renderState.frontFace }),\n };\n}\n\ninterface UnlitOpts {\n readonly castShadow?: boolean;\n readonly baseColorTexture?: MaterialValue;\n readonly alphaCutoff?: number;\n readonly renderState?: MaterialRenderState;\n readonly queue?: number;\n}\n\nfunction unlit(rgba: MaterialColorInput4, opts?: UnlitOpts): MaterialAsset {\n if (opts?.alphaCutoff !== undefined && (opts.alphaCutoff < 0 || opts.alphaCutoff > 1)) {\n throw new Error(`Materials.unlit: alphaCutoff must be in [0, 1], got ${opts.alphaCutoff}`);\n }\n const values: Record<string, MaterialValue> = { baseColor: linearColorFromInput(rgba, 4) };\n if (opts?.baseColorTexture !== undefined) values.baseColorTexture = opts.baseColorTexture;\n if (opts?.alphaCutoff !== undefined) values.alphaCutoff = opts.alphaCutoff;\n const passes: [MaterialPass, ...MaterialPass[]] = [\n pass('forward', UNLIT_MODULE, opts?.renderState, undefined, opts?.queue),\n ];\n if (opts?.castShadow !== false) {\n passes.push(pass('shadow-caster', UNLIT_MODULE, shadowCasterRenderState(opts?.renderState)));\n }\n return {\n kind: 'material',\n colorSpace: 'linear',\n passes,\n parameters: unlitParameters('linear'),\n values,\n };\n}\n\ninterface StandardOpts {\n /** Numeric tuples are linear; Hex/CSS strings and numbers are sRGB inputs. */\n readonly baseColor: MaterialColorInput4;\n readonly metallic?: number;\n readonly roughness?: number;\n /** Texture channel used for the metallic factor; glTF defaults to B (2). */\n readonly metallicChannel?: number;\n /** Texture channel used for the roughness factor; glTF defaults to G (1). */\n readonly roughnessChannel?: number;\n readonly clearcoat?: number;\n readonly clearcoatRoughness?: number;\n readonly clearcoatTexture?: MaterialValue;\n readonly clearcoatRoughnessTexture?: MaterialValue;\n readonly clearcoatNormalTexture?: MaterialValue;\n readonly clearcoatNormalScale?: number;\n readonly anisotropyStrength?: number;\n readonly anisotropyRotation?: number;\n readonly anisotropyTexture?: MaterialValue;\n readonly sheenColor?: MaterialColorInput3;\n readonly sheenRoughness?: number;\n readonly sheenColorTexture?: MaterialValue;\n readonly sheenRoughnessTexture?: MaterialValue;\n readonly iridescence?: number;\n readonly iridescenceIor?: number;\n readonly iridescenceThicknessMinimum?: number;\n readonly iridescenceThicknessMaximum?: number;\n readonly iridescenceTexture?: MaterialValue;\n readonly iridescenceThicknessTexture?: MaterialValue;\n readonly specular?: number;\n readonly specularColor?: MaterialColorInput3;\n readonly specularTexture?: MaterialValue;\n readonly specularColorTexture?: MaterialValue;\n readonly emissive?: MaterialColorInput3;\n readonly emissiveIntensity?: number;\n readonly emissiveTexture?: MaterialValue;\n readonly baseColorTexture?: MaterialValue;\n readonly metallicRoughnessTexture?: MaterialValue;\n readonly normalTexture?: MaterialValue;\n readonly occlusionTexture?: MaterialValue;\n readonly occlusionStrength?: number;\n readonly alphaCutoff?: number;\n readonly transmission?: number;\n readonly transmissionTexture?: MaterialValue;\n readonly ior?: number;\n readonly thickness?: number;\n readonly thicknessTexture?: MaterialValue;\n readonly attenuationColor?: readonly [number, number, number];\n readonly attenuationDistance?: number;\n readonly renderState?: MaterialRenderState;\n readonly castShadow?: boolean;\n readonly queue?: number;\n}\n\n/** Built-in Standard authoring surface with engine-owned parameter defaults. */\nexport interface DefaultStandardOptions extends StandardOpts {\n readonly surfaceModule?: never;\n readonly parameters?: never;\n readonly values?: never;\n}\n\n/** Import-first Standard Surface authoring; the root parameter contract stays caller-owned. */\nexport interface CustomStandardSurfaceOptions {\n readonly surfaceModule: string;\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue>>;\n readonly colorSpace?: MaterialColorSpace;\n readonly renderState?: MaterialRenderState;\n readonly castShadow?: boolean;\n readonly queue?: number;\n readonly baseColor?: never;\n readonly metallic?: never;\n readonly roughness?: never;\n readonly metallicChannel?: never;\n readonly roughnessChannel?: never;\n readonly clearcoat?: never;\n readonly clearcoatRoughness?: never;\n readonly clearcoatTexture?: never;\n readonly clearcoatRoughnessTexture?: never;\n readonly clearcoatNormalTexture?: never;\n readonly clearcoatNormalScale?: never;\n readonly anisotropyStrength?: never;\n readonly anisotropyRotation?: never;\n readonly anisotropyTexture?: never;\n readonly sheenColor?: never;\n readonly sheenRoughness?: never;\n readonly sheenColorTexture?: never;\n readonly sheenRoughnessTexture?: never;\n readonly iridescence?: never;\n readonly iridescenceIor?: never;\n readonly iridescenceThicknessMinimum?: never;\n readonly iridescenceThicknessMaximum?: never;\n readonly iridescenceTexture?: never;\n readonly iridescenceThicknessTexture?: never;\n readonly specular?: never;\n readonly specularColor?: never;\n readonly specularTexture?: never;\n readonly specularColorTexture?: never;\n readonly emissive?: never;\n readonly emissiveIntensity?: never;\n readonly emissiveTexture?: never;\n readonly baseColorTexture?: never;\n readonly metallicRoughnessTexture?: never;\n readonly normalTexture?: never;\n readonly occlusionTexture?: never;\n readonly occlusionStrength?: never;\n readonly alphaCutoff?: never;\n readonly transmission?: never;\n readonly transmissionTexture?: never;\n readonly ior?: never;\n readonly thickness?: never;\n readonly thicknessTexture?: never;\n readonly attenuationColor?: never;\n readonly attenuationDistance?: never;\n}\n\nexport type StandardOptions = DefaultStandardOptions | CustomStandardSurfaceOptions;\n\nfunction validateChannel(\n name: 'metallicChannel' | 'roughnessChannel',\n value: number | undefined,\n): void {\n if (value !== undefined && (!Number.isInteger(value) || value < 0 || value > 3)) {\n throw new Error(`Materials.standard: ${name} must be an integer in [0, 3], got ${value}`);\n }\n}\n\nfunction validateFiniteRange(\n name: 'transmission' | 'ior' | 'thickness' | 'attenuationDistance',\n value: number | undefined,\n minimum: number,\n maximum?: number,\n): void {\n if (value === undefined || !Number.isFinite(value)) {\n if (value === undefined) return;\n throw new MaterialTransmissionContractError(name, 'non-finite', value);\n }\n if (value < minimum || (maximum !== undefined && value > maximum)) {\n throw new MaterialTransmissionContractError(name, 'range', value);\n }\n}\n\nfunction standardDefault(opts: DefaultStandardOptions): MaterialAsset {\n const occlusionStrength = opts.occlusionStrength ?? 1;\n if (occlusionStrength < 0 || occlusionStrength > 1) {\n throw new Error(\n `Materials.standard: occlusionStrength must be in [0, 1], got ${occlusionStrength}`,\n );\n }\n if (opts.alphaCutoff !== undefined && !Number.isFinite(opts.alphaCutoff)) {\n throw new MaterialAuthoringContractError('non-finite', opts.alphaCutoff);\n }\n if (opts.alphaCutoff !== undefined && (opts.alphaCutoff < 0 || opts.alphaCutoff > 1)) {\n throw new MaterialAuthoringContractError('range', opts.alphaCutoff);\n }\n validateChannel('metallicChannel', opts.metallicChannel);\n validateChannel('roughnessChannel', opts.roughnessChannel);\n const transmission = opts.transmission ?? 0;\n const ior = opts.ior ?? 1.5;\n const thickness = opts.thickness ?? 0;\n const attenuationColor = opts.attenuationColor ?? [1, 1, 1];\n validateFiniteRange('transmission', transmission, 0, 1);\n validateFiniteRange('ior', ior, 1);\n validateFiniteRange('thickness', thickness, 0);\n validateFiniteRange('attenuationDistance', opts.attenuationDistance, Number.MIN_VALUE);\n if (\n attenuationColor.length !== 3 ||\n attenuationColor.some((value) => !Number.isFinite(value) || value < 0 || value > 1)\n ) {\n throw new MaterialTransmissionContractError('attenuationColor', 'shape', attenuationColor);\n }\n if (transmission > 0 && opts.renderState?.blend !== undefined) {\n throw new MaterialTransmissionContractError('transmission', 'blend', opts.renderState.blend);\n }\n if (transmission > 0 && opts.renderState?.depthWriteEnabled === true) {\n throw new MaterialTransmissionContractError('transmission', 'depth-write', true);\n }\n const values: Record<string, MaterialValue> = {\n baseColor: linearColorFromInput(opts.baseColor, 4),\n metallic: opts.metallic ?? 0,\n roughness: opts.roughness ?? 0.5,\n occlusionStrength,\n specular: opts.specular ?? 1,\n specularColor:\n opts.specularColor === undefined ? [1, 1, 1] : linearColorFromInput(opts.specularColor, 3),\n transmission,\n ior,\n thickness,\n attenuationColor,\n };\n if (opts.metallicChannel !== undefined) values.metallicChannel = opts.metallicChannel;\n if (opts.roughnessChannel !== undefined) values.roughnessChannel = opts.roughnessChannel;\n if (opts.clearcoat !== undefined) values.clearcoat = opts.clearcoat;\n if (opts.clearcoatRoughness !== undefined) values.clearcoatRoughness = opts.clearcoatRoughness;\n if (opts.clearcoatTexture !== undefined) values.clearcoatTexture = opts.clearcoatTexture;\n if (opts.clearcoatRoughnessTexture !== undefined) {\n values.clearcoatRoughnessTexture = opts.clearcoatRoughnessTexture;\n }\n if (opts.clearcoatNormalTexture !== undefined) {\n values.clearcoatNormalTexture = opts.clearcoatNormalTexture;\n }\n if (opts.clearcoatNormalScale !== undefined)\n values.clearcoatNormalScale = opts.clearcoatNormalScale;\n if (opts.anisotropyStrength !== undefined) values.anisotropyStrength = opts.anisotropyStrength;\n if (opts.anisotropyRotation !== undefined) values.anisotropyRotation = opts.anisotropyRotation;\n if (opts.anisotropyTexture !== undefined) values.anisotropyTexture = opts.anisotropyTexture;\n if (opts.sheenColor !== undefined) values.sheenColor = linearColorFromInput(opts.sheenColor, 3);\n if (opts.sheenRoughness !== undefined) values.sheenRoughness = opts.sheenRoughness;\n if (opts.sheenColorTexture !== undefined) values.sheenColorTexture = opts.sheenColorTexture;\n if (opts.sheenRoughnessTexture !== undefined) {\n values.sheenRoughnessTexture = opts.sheenRoughnessTexture;\n }\n if (opts.iridescence !== undefined) values.iridescence = opts.iridescence;\n if (opts.iridescenceIor !== undefined) values.iridescenceIor = opts.iridescenceIor;\n if (opts.iridescenceThicknessMinimum !== undefined) {\n values.iridescenceThicknessMinimum = opts.iridescenceThicknessMinimum;\n }\n if (opts.iridescenceThicknessMaximum !== undefined) {\n values.iridescenceThicknessMaximum = opts.iridescenceThicknessMaximum;\n }\n if (opts.iridescenceTexture !== undefined) values.iridescenceTexture = opts.iridescenceTexture;\n if (opts.iridescenceThicknessTexture !== undefined) {\n values.iridescenceThicknessTexture = opts.iridescenceThicknessTexture;\n }\n if (opts.emissive !== undefined) values.emissive = linearColorFromInput(opts.emissive, 3);\n if (opts.emissiveIntensity !== undefined) values.emissiveIntensity = opts.emissiveIntensity;\n if (opts.emissiveTexture !== undefined) values.emissiveTexture = opts.emissiveTexture;\n if (opts.baseColorTexture !== undefined) values.baseColorTexture = opts.baseColorTexture;\n if (opts.metallicRoughnessTexture !== undefined) {\n values.metallicRoughnessTexture = opts.metallicRoughnessTexture;\n }\n if (opts.normalTexture !== undefined) values.normalTexture = opts.normalTexture;\n if (opts.occlusionTexture !== undefined) values.occlusionTexture = opts.occlusionTexture;\n if (opts.specularTexture !== undefined) values.specularTexture = opts.specularTexture;\n if (opts.specularColorTexture !== undefined) {\n values.specularColorTexture = opts.specularColorTexture;\n }\n if (opts.alphaCutoff !== undefined) values.alphaCutoff = opts.alphaCutoff;\n if (opts.transmissionTexture !== undefined) values.transmissionTexture = opts.transmissionTexture;\n if (opts.thicknessTexture !== undefined) values.thicknessTexture = opts.thicknessTexture;\n if (opts.attenuationDistance !== undefined) values.attenuationDistance = opts.attenuationDistance;\n const forwardRenderState =\n transmission > 0 ? { ...(opts.renderState ?? {}), depthWriteEnabled: false } : opts.renderState;\n const parameters = standardSurfaceParameters(standardParameters('linear', opts));\n const declaredNames = new Set(parameters.map((parameter) => parameter.name));\n for (const name of Object.keys(values)) {\n if (!declaredNames.has(name)) delete values[name];\n }\n const layerPlan = deriveStandardLayerPlan(parameters);\n const projected = projectStandardSurfacePasses({\n surfaceModule: DEFAULT_STANDARD_SURFACE_MODULE,\n values,\n ...(forwardRenderState === undefined ? {} : { renderState: forwardRenderState }),\n ...(opts.castShadow === undefined ? {} : { castShadow: opts.castShadow }),\n ...(opts.queue === undefined ? {} : { queue: opts.queue }),\n layerPlan,\n });\n const passes = (\n transmission > 0 ? projected.filter((entry) => entry.name !== 'deferred') : projected\n ) as [MaterialPass, ...MaterialPass[]];\n return {\n kind: 'material',\n colorSpace: 'linear',\n passes,\n parameters,\n values,\n };\n}\n\nfunction standardCustom(opts: CustomStandardSurfaceOptions): MaterialAsset {\n const layerPlan = deriveStandardLayerPlan(\n opts.parameters.filter((parameter) => parameter.optional !== true),\n );\n return {\n kind: 'material',\n ...(opts.colorSpace === undefined || opts.colorSpace === 'srgb'\n ? {}\n : { colorSpace: opts.colorSpace }),\n passes: projectStandardSurfacePasses({\n surfaceModule: opts.surfaceModule,\n values: opts.values,\n ...(opts.renderState === undefined ? {} : { renderState: opts.renderState }),\n ...(opts.castShadow === undefined ? {} : { castShadow: opts.castShadow }),\n ...(opts.queue === undefined ? {} : { queue: opts.queue }),\n layerPlan,\n }),\n parameters: standardSurfaceParameters(opts.parameters),\n values: opts.values,\n };\n}\n\nexport function standard(options: StandardOptions): MaterialAsset {\n return options.surfaceModule === undefined ? standardDefault(options) : standardCustom(options);\n}\n\nexport const Materials = { unlit, standard, srgb } as const;\n\nexport { SPRITE_MODULE };\n"]}
|