@forgeax/engine-render 0.1.25 → 0.1.27
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 +18 -0
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +4 -17
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -1
- package/dist/assembly/material/surface-projection.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts +0 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-JSEDTZYS.mjs → chunk-GF523LHF.mjs} +6 -6
- package/dist/chunk-GF523LHF.mjs.map +1 -0
- package/dist/{chunk-TCLDX7SZ.mjs → chunk-TMIASV2N.mjs} +403 -457
- package/dist/chunk-TMIASV2N.mjs.map +1 -0
- package/dist/{chunk-N3RT2EUR.mjs → chunk-XDP6XE5V.mjs} +104 -56
- package/dist/chunk-XDP6XE5V.mjs.map +1 -0
- package/dist/construct-renderer.mjs +153 -13
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/extract/contracts.d.ts +6 -6
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/internal.mjs +1 -1
- package/dist/pipeline-spec-types.d.ts +2 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/record/frame.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 +20 -2
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +3 -3
- 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/material-uniforms.d.ts +4 -0
- package/dist/record/material-uniforms.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +2 -2
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -3
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +2 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +27 -10
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/temporal/index.mjs +2 -2
- package/package.json +20 -20
- package/src/__tests__/fixtures/ai-weapon-spirit/README.md +20 -0
- package/src/__tests__/fixtures/ai-weapon-spirit/low-poly-toon.wgsl +178 -0
- package/src/__tests__/fixtures/ai-weapon-spirit/material.json +97 -0
- package/src/__tests__/fixtures/ai-weapon-spirit/painterly-surface.wgsl +55 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +3 -3
- package/src/__tests__/gpu-driven-view.browser.test.ts +11 -3
- package/src/__tests__/material-contract-inventory.unit.test.ts +43 -0
- package/src/__tests__/{material-static-dynamic-route.unit.test.ts → material-layer-projection.unit.test.ts} +30 -47
- package/src/__tests__/material-program-dispatch.unit.test.ts +48 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +2 -2
- package/src/__tests__/skinned-shadow-caster.test.ts +14 -14
- package/src/__tests__/surface-variant-provenance.integration.test.ts +1 -1
- package/src/assembly/factory.ts +0 -3
- package/src/assembly/material/assembly.ts +8 -40
- package/src/assembly/material/standard-layer-projection.ts +3 -1
- package/src/assembly/material/surface-projection.ts +2 -1
- package/src/assembly/webgpu-renderer.ts +17 -9
- package/src/extract/contracts.ts +6 -6
- package/src/materials.ts +3 -3
- package/src/pipeline-spec-types.ts +2 -0
- package/src/pipeline-spec.ts +7 -3
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +68 -1
- package/src/record/frame.ts +7 -1
- package/src/record/main-pass-geometry.ts +340 -279
- package/src/record/main-pass-material.ts +87 -2
- package/src/record/main-pass-sprite-draws.ts +65 -168
- package/src/record/main-pass.ts +24 -246
- package/src/record/material-uniforms.ts +186 -0
- package/src/record/render-context.ts +4 -0
- package/src/record/shadow-pass.ts +86 -28
- package/src/recovery/render-system-candidate.ts +5 -1
- package/src/render-system-extract-tail.ts +54 -13
- package/src/render-system-extract.ts +103 -64
- package/src/render-system.ts +19 -0
- package/dist/assembly/material/pipeline-projection.d.ts +0 -30
- package/dist/assembly/material/pipeline-projection.d.ts.map +0 -1
- package/dist/chunk-JSEDTZYS.mjs.map +0 -1
- package/dist/chunk-N3RT2EUR.mjs.map +0 -1
- package/dist/chunk-TCLDX7SZ.mjs.map +0 -1
- package/src/assembly/material/pipeline-projection.ts +0 -63
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MaterialCookProgramContext } from '@forgeax/engine-pack/material-cook';
|
|
1
2
|
// @forgeax/engine-runtime - RenderSystem Extract stage (D-S2 + plan-strategy R-15
|
|
2
3
|
// fallback split). Pure ECS query phase: walks Camera / DirectionalLight /
|
|
3
4
|
// the merged-MeshRenderer renderable archetype and produces SoA-free snapshot
|
|
@@ -81,7 +82,9 @@
|
|
|
81
82
|
|
|
82
83
|
import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
83
84
|
import {
|
|
85
|
+
materialParametersToParamSchema as projectMaterialParametersToParamSchema,
|
|
84
86
|
resolveAssetHandle,
|
|
87
|
+
selectMaterialPassProgram,
|
|
85
88
|
walkMaterialPassesOverSharedRefs,
|
|
86
89
|
} from '@forgeax/engine-assets-runtime';
|
|
87
90
|
import type { Component, ComponentSchema, EntityHandle, Query, World } from '@forgeax/engine-ecs';
|
|
@@ -91,6 +94,7 @@ import { AssetGuid, type AssetGuid as AssetGuidBytes } from '@forgeax/engine-pac
|
|
|
91
94
|
import { RhiError } from '@forgeax/engine-rhi';
|
|
92
95
|
import { GlobalTransform, Transform } from '@forgeax/engine-scene';
|
|
93
96
|
import {
|
|
97
|
+
DEFAULT_STANDARD_SURFACE_MODULE,
|
|
94
98
|
type MaterialShaderArtifact,
|
|
95
99
|
STANDARD_PIPELINE_PARAM_SCHEMA,
|
|
96
100
|
} from '@forgeax/engine-shader';
|
|
@@ -909,6 +913,7 @@ export interface MaterialSnapshot {
|
|
|
909
913
|
* discriminator (M4-T06).
|
|
910
914
|
*/
|
|
911
915
|
readonly materialShaderId?: string | undefined;
|
|
916
|
+
readonly materialProgramKeys?: Readonly<Record<string, string>> | undefined;
|
|
912
917
|
/**
|
|
913
918
|
* Stable source handle for the material asset. Record uses this only for
|
|
914
919
|
* same-frame assembly reuse; GPU bind-group validity still comes from the
|
|
@@ -1015,12 +1020,9 @@ export interface MaterialSnapshot {
|
|
|
1015
1020
|
* from the legacy `shadingModel` discriminant (feat-20260625 M2 D-3,
|
|
1016
1021
|
* finalised in w15; `shadingModel` field removed in tweak-20260701 M1).
|
|
1017
1022
|
*
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1021
|
-
* pipeline cache key"). Multi-pass materials whose mix of opaque +
|
|
1022
|
-
* transparent passes need finer routing should split into separate
|
|
1023
|
-
* MaterialAsset entries (the normal forgeax pattern).
|
|
1023
|
+
* This describes the primary-pass snapshot for consumers that need a
|
|
1024
|
+
* material summary. Actual draw routing and the LDR split read the selected
|
|
1025
|
+
* DispatchEntry.renderState, so mixed opaque/transparent Passes remain valid.
|
|
1024
1026
|
*
|
|
1025
1027
|
* Type is `boolean | undefined` (derived): `undefined` means "no
|
|
1026
1028
|
* passes / unknown"; consumers must read `=== true` / `!== true` to
|
|
@@ -1125,7 +1127,7 @@ export function appendMaterialDispatchEntries(
|
|
|
1125
1127
|
layer: number,
|
|
1126
1128
|
paramSnapshot: Readonly<Record<string, number | number[] | string>> | undefined,
|
|
1127
1129
|
passIndexOffset = 0,
|
|
1128
|
-
|
|
1130
|
+
materialProgramKeys?: Readonly<Record<string, string>>,
|
|
1129
1131
|
): void {
|
|
1130
1132
|
const matchedPasses = selectPasses(passes, {});
|
|
1131
1133
|
for (let pIdx = 0; pIdx < matchedPasses.length; pIdx++) {
|
|
@@ -1138,9 +1140,9 @@ export function appendMaterialDispatchEntries(
|
|
|
1138
1140
|
};
|
|
1139
1141
|
const authoredShaderId = runtimeMaterialShaderId(pass.program.module, pass.name);
|
|
1140
1142
|
const dispatchShaderId =
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1143
|
+
materialProgramKeys === undefined ? authoredShaderId : materialProgramKeys[pass.name];
|
|
1144
|
+
if (materialProgramKeys !== undefined && dispatchShaderId === undefined)
|
|
1145
|
+
throw new Error(`Missing published material program for Pass ${pass.name}`);
|
|
1144
1146
|
pendingDispatch.push({
|
|
1145
1147
|
entityIndex: entity,
|
|
1146
1148
|
materialHandle,
|
|
@@ -1155,13 +1157,6 @@ export function appendMaterialDispatchEntries(
|
|
|
1155
1157
|
defines: undefined,
|
|
1156
1158
|
vertexEntry: pass.program.vertexEntry,
|
|
1157
1159
|
fragmentEntry: pass.program.fragmentEntry,
|
|
1158
|
-
// A cooked Standard publication supplies one specialization key for its
|
|
1159
|
-
// forward/deferred artifact, but its ShadowCaster pass still owns the
|
|
1160
|
-
// engine depth-only shader. Keep the pass-local canonical identity so a
|
|
1161
|
-
// specialized Standard source (which only declares fs_main/fs_gbuffer)
|
|
1162
|
-
// is never asked to build an fs_shadow pipeline. Authored non-Standard
|
|
1163
|
-
// ShadowCaster modules retain the publication override and continue to
|
|
1164
|
-
// use their producer-owned source.
|
|
1165
1160
|
materialShaderId: dispatchShaderId,
|
|
1166
1161
|
paramSnapshot,
|
|
1167
1162
|
...(passState.stencilReference !== undefined && {
|
|
@@ -1419,13 +1414,50 @@ export function runtimeMaterialShaderId(
|
|
|
1419
1414
|
* owns the composed material artifact identity; the authored pass module is
|
|
1420
1415
|
* the built-in fallback used before that publication is ready.
|
|
1421
1416
|
*/
|
|
1422
|
-
export function
|
|
1417
|
+
export function materialProgramKeysForMaterial(
|
|
1423
1418
|
material: MaterialAsset,
|
|
1424
|
-
passes: readonly MaterialPass[],
|
|
1425
1419
|
assets: AssetRegistry,
|
|
1420
|
+
context: MaterialCookProgramContext | undefined,
|
|
1421
|
+
): Readonly<Record<string, string>> | undefined {
|
|
1422
|
+
const projection = assets.getMaterialProjectionForPayload(material);
|
|
1423
|
+
if (projection === undefined) return undefined;
|
|
1424
|
+
if (context === undefined)
|
|
1425
|
+
throw new Error('Published material selection requires renderer-owned compiler context');
|
|
1426
|
+
return Object.fromEntries(
|
|
1427
|
+
projection.passes.map((pass) => {
|
|
1428
|
+
const mode = String(
|
|
1429
|
+
(pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
|
|
1430
|
+
);
|
|
1431
|
+
const selectedContext: MaterialCookProgramContext = {
|
|
1432
|
+
...context,
|
|
1433
|
+
pass: /shadow/i.test(mode) ? 'shadow' : /depth/i.test(mode) ? 'depth' : 'forward',
|
|
1434
|
+
pipeline: /deferred|gbuffer/i.test(mode) ? 'deferred' : context.pipeline,
|
|
1435
|
+
};
|
|
1436
|
+
return [
|
|
1437
|
+
pass.name,
|
|
1438
|
+
selectMaterialPassProgram(projection, pass.name, selectedContext).specializationKey,
|
|
1439
|
+
];
|
|
1440
|
+
}),
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
export function runtimeMaterialShaderIdForMaterial(
|
|
1445
|
+
passes: readonly MaterialPass[],
|
|
1446
|
+
programs: Readonly<Record<string, string>> | undefined,
|
|
1426
1447
|
): string | undefined {
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1448
|
+
const pass =
|
|
1449
|
+
passes.find(
|
|
1450
|
+
(pass) =>
|
|
1451
|
+
!/shadow|depth/i.test(
|
|
1452
|
+
String(
|
|
1453
|
+
(pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
|
|
1454
|
+
),
|
|
1455
|
+
),
|
|
1456
|
+
) ?? passes[0];
|
|
1457
|
+
if (pass === undefined) return undefined;
|
|
1458
|
+
return programs === undefined
|
|
1459
|
+
? runtimeMaterialShaderId(pass.program.module, pass.name)
|
|
1460
|
+
: programs[pass.name];
|
|
1429
1461
|
}
|
|
1430
1462
|
|
|
1431
1463
|
export function pipelineRenderState(
|
|
@@ -1732,49 +1764,48 @@ export function isEngineInjectedTextureField(
|
|
|
1732
1764
|
return isStandardPbrMaterialShader(shaderId) && ENGINE_INJECTED_TEXTURE_FIELDS.has(fieldName);
|
|
1733
1765
|
}
|
|
1734
1766
|
|
|
1767
|
+
/**
|
|
1768
|
+
* Project one material's authoring parameters into the runtime ABI.
|
|
1769
|
+
*
|
|
1770
|
+
* Engine-owned Standard roots are compiled against the canonical superset
|
|
1771
|
+
* schema even when the authoring asset omits optional physical fields. A
|
|
1772
|
+
* compact authored schema would move later UBO members (for example `ior`)
|
|
1773
|
+
* into the wrong slots. Custom material roots keep their own published
|
|
1774
|
+
* parameter projection.
|
|
1775
|
+
*/
|
|
1735
1776
|
export function materialParametersToParamSchema(
|
|
1736
1777
|
parameters: readonly MaterialParameter[],
|
|
1737
|
-
shaderId
|
|
1778
|
+
shaderId?: string,
|
|
1738
1779
|
): readonly ParamSchemaEntry[] {
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
: undefined;
|
|
1769
|
-
const numericEntry = {
|
|
1770
|
-
name: parameter.name,
|
|
1771
|
-
type: parameter.type,
|
|
1772
|
-
...(parameter.colorSpace === undefined ? {} : { colorSpace: parameter.colorSpace }),
|
|
1773
|
-
};
|
|
1774
|
-
return numericDefault === undefined
|
|
1775
|
-
? [numericEntry]
|
|
1776
|
-
: [{ ...numericEntry, default: numericDefault }];
|
|
1777
|
-
});
|
|
1780
|
+
if (isCanonicalStandardPbrMaterialShader(shaderId)) return STANDARD_PIPELINE_PARAM_SCHEMA;
|
|
1781
|
+
return projectMaterialParametersToParamSchema(parameters);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
/**
|
|
1785
|
+
* Select the parameter ABI for one resolved material. The canonical Standard
|
|
1786
|
+
* schema is valid only for the engine-owned default Surface; a Standard root
|
|
1787
|
+
* with a project Surface keeps the custom fields that its cooked WGSL reads.
|
|
1788
|
+
*/
|
|
1789
|
+
export function materialParamSchemaForMaterial(
|
|
1790
|
+
parameters: readonly MaterialParameter[],
|
|
1791
|
+
authoredShaderId: string | undefined,
|
|
1792
|
+
passes: readonly MaterialPass[],
|
|
1793
|
+
): readonly ParamSchemaEntry[] {
|
|
1794
|
+
const firstPass =
|
|
1795
|
+
passes.find(
|
|
1796
|
+
(pass) =>
|
|
1797
|
+
!/shadow|depth/i.test(
|
|
1798
|
+
String(
|
|
1799
|
+
(pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
|
|
1800
|
+
),
|
|
1801
|
+
),
|
|
1802
|
+
) ?? passes[0];
|
|
1803
|
+
const surfaceModule = firstPass?.program.moduleSlots?.surface;
|
|
1804
|
+
const schemaShaderId =
|
|
1805
|
+
surfaceModule === undefined || surfaceModule === DEFAULT_STANDARD_SURFACE_MODULE
|
|
1806
|
+
? authoredShaderId
|
|
1807
|
+
: undefined;
|
|
1808
|
+
return materialParametersToParamSchema(parameters, schemaShaderId);
|
|
1778
1809
|
}
|
|
1779
1810
|
|
|
1780
1811
|
/**
|
|
@@ -1921,6 +1952,7 @@ export function resolveMaterialSnapshot(
|
|
|
1921
1952
|
assetsRef: AssetRegistry,
|
|
1922
1953
|
materialSnapshotCache?: MaterialSnapshotCache,
|
|
1923
1954
|
persistentMaterialSnapshotCache?: MaterialSnapshotCache,
|
|
1955
|
+
materialContext?: MaterialCookProgramContext,
|
|
1924
1956
|
): MaterialSnapshot {
|
|
1925
1957
|
if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
|
|
1926
1958
|
const cached = materialSnapshotCache?.get(handleRaw);
|
|
@@ -1952,7 +1984,9 @@ export function resolveMaterialSnapshot(
|
|
|
1952
1984
|
if (!resolvedResult.ok) return defaultMaterialSnapshot(handleRaw);
|
|
1953
1985
|
const resolved = resolvedResult.value;
|
|
1954
1986
|
const allPasses = resolved.passes;
|
|
1955
|
-
const
|
|
1987
|
+
const materialProgramKeys = materialProgramKeysForMaterial(asset, assetsRef, materialContext);
|
|
1988
|
+
const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, undefined);
|
|
1989
|
+
const firstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, materialProgramKeys);
|
|
1956
1990
|
const pv = materialValuesToLinearRuntime(
|
|
1957
1991
|
resolved.values,
|
|
1958
1992
|
materialColorParameterSchema(resolved.parameters ?? [], firstPassShader, assetsRef),
|
|
@@ -1977,9 +2011,10 @@ export function resolveMaterialSnapshot(
|
|
|
1977
2011
|
paramSnap[k] = v as number[];
|
|
1978
2012
|
}
|
|
1979
2013
|
}
|
|
1980
|
-
const materialParamSchema =
|
|
2014
|
+
const materialParamSchema = materialParamSchemaForMaterial(
|
|
1981
2015
|
resolved.parameters ?? [],
|
|
1982
|
-
|
|
2016
|
+
authoredFirstPassShader,
|
|
2017
|
+
allPasses,
|
|
1983
2018
|
);
|
|
1984
2019
|
// feat-20260614 M8 (D-19): texture / sampler values are embedded GUIDs
|
|
1985
2020
|
// (dash-form strings) after loadByGuid. Resolve each to a user-tier column
|
|
@@ -2047,6 +2082,7 @@ export function resolveMaterialSnapshot(
|
|
|
2047
2082
|
}),
|
|
2048
2083
|
normalScale: normalScalePv,
|
|
2049
2084
|
materialShaderId: firstPassShader,
|
|
2085
|
+
materialProgramKeys,
|
|
2050
2086
|
materialHandle: handleRaw,
|
|
2051
2087
|
renderState: pipelineRenderState(allPasses[0]?.renderState),
|
|
2052
2088
|
paramSnapshot: paramSnap,
|
|
@@ -2548,6 +2584,7 @@ export interface ExtractFramesOwner {
|
|
|
2548
2584
|
}
|
|
2549
2585
|
|
|
2550
2586
|
export interface PreparedExtractContext {
|
|
2587
|
+
readonly materialContext?: MaterialCookProgramContext | undefined;
|
|
2551
2588
|
readonly assets: AssetRegistry | null | undefined;
|
|
2552
2589
|
readonly pipelineState: ExtractPipelineSurface | null | undefined;
|
|
2553
2590
|
readonly materialSnapshotCache: MaterialSnapshotCache | undefined;
|
|
@@ -2748,6 +2785,7 @@ export function tonemapParams(camera: CameraSnapshot): Uint8Array {
|
|
|
2748
2785
|
export function prepareExtractContext(
|
|
2749
2786
|
world: World,
|
|
2750
2787
|
options: {
|
|
2788
|
+
readonly materialContext?: MaterialCookProgramContext;
|
|
2751
2789
|
readonly assets?: AssetRegistry | null;
|
|
2752
2790
|
readonly pipelineState?: ExtractPipelineSurface | null;
|
|
2753
2791
|
readonly materialSnapshotCache?: MaterialSnapshotCache;
|
|
@@ -2765,6 +2803,7 @@ export function prepareExtractContext(
|
|
|
2765
2803
|
): PreparedExtractContext {
|
|
2766
2804
|
const renderables = options.renderables ?? 'full';
|
|
2767
2805
|
return {
|
|
2806
|
+
materialContext: options.materialContext,
|
|
2768
2807
|
assets: options.assets,
|
|
2769
2808
|
pipelineState: options.pipelineState,
|
|
2770
2809
|
materialSnapshotCache: options.materialSnapshotCache,
|
package/src/render-system.ts
CHANGED
|
@@ -2586,6 +2586,25 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2586
2586
|
internals.getPipelineState(),
|
|
2587
2587
|
persistentRenderScene.materialSnapshotCacheStore(),
|
|
2588
2588
|
{
|
|
2589
|
+
...(internals.device.caps.backendKind === 'null'
|
|
2590
|
+
? {}
|
|
2591
|
+
: {
|
|
2592
|
+
materialContext: {
|
|
2593
|
+
backend:
|
|
2594
|
+
internals.device.caps.backendKind === 'wgpu-webgl2'
|
|
2595
|
+
? ('webgl2' as const)
|
|
2596
|
+
: internals.device.caps.backendKind,
|
|
2597
|
+
capability: internals.device.caps.storageBuffer
|
|
2598
|
+
? ('storage-buffer' as const)
|
|
2599
|
+
: ('uniform-fallback' as const),
|
|
2600
|
+
pipeline: 'forward' as const,
|
|
2601
|
+
geometry: 'mesh' as const,
|
|
2602
|
+
pass: 'forward' as const,
|
|
2603
|
+
profile: 'forgeax-material-wgsl-v1' as const,
|
|
2604
|
+
toolchain: 'naga-oil' as const,
|
|
2605
|
+
instrumentation: 'none' as const,
|
|
2606
|
+
},
|
|
2607
|
+
}),
|
|
2589
2608
|
cull: 'none',
|
|
2590
2609
|
renderables: request === 'none' ? 'none' : 'full',
|
|
2591
2610
|
...(request === 'none' || request === 'full'
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { MaterialRuntimeArtifact } from '@forgeax/engine-shader';
|
|
2
|
-
import type { MaterialValue } from '@forgeax/engine-types';
|
|
3
|
-
import type { MaterialRenderProjection } from './assembly.js';
|
|
4
|
-
export interface MaterialPipelineProjection {
|
|
5
|
-
readonly specializationKey: string;
|
|
6
|
-
readonly artifactHash: string;
|
|
7
|
-
readonly passes: MaterialRenderProjection['passes'];
|
|
8
|
-
}
|
|
9
|
-
export interface MaterialPipelineReady extends MaterialPipelineProjection {
|
|
10
|
-
readonly kind: 'ready';
|
|
11
|
-
readonly artifact: MaterialRuntimeArtifact;
|
|
12
|
-
}
|
|
13
|
-
export interface MaterialPipelineMiss {
|
|
14
|
-
readonly kind: 'error';
|
|
15
|
-
readonly error: {
|
|
16
|
-
readonly code: 'material-specialization-not-cooked';
|
|
17
|
-
readonly expected: string;
|
|
18
|
-
readonly hint: string;
|
|
19
|
-
readonly detail: {
|
|
20
|
-
readonly specializationKey: string;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export declare function projectMaterialPipeline(projection: MaterialRenderProjection): MaterialPipelineProjection;
|
|
25
|
-
export declare function updateMaterialRuntimeValues(projection: MaterialRenderProjection, values: Readonly<Record<string, MaterialValue | null>>): MaterialRenderProjection;
|
|
26
|
-
export declare function routeMaterialPipeline(args: {
|
|
27
|
-
readonly projection: MaterialRenderProjection;
|
|
28
|
-
readonly lookupArtifact: (key: string) => MaterialRuntimeArtifact | undefined;
|
|
29
|
-
}): MaterialPipelineReady | MaterialPipelineMiss;
|
|
30
|
-
//# sourceMappingURL=pipeline-projection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-projection.d.ts","sourceRoot":"","sources":["../../../src/assembly/material/pipeline-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,qBAAsB,SAAQ,0BAA0B;IACvE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,oCAAoC,CAAC;QACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;SAAE,CAAC;KACzD,CAAC;CACH;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,wBAAwB,GACnC,0BAA0B,CAM5B;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,wBAAwB,EACpC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC,CAAC,GACrD,wBAAwB,CAK1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,uBAAuB,GAAG,SAAS,CAAC;CAC/E,GAAG,qBAAqB,GAAG,oBAAoB,CAc/C"}
|
|
@@ -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-JSEDTZYS.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: 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 } 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\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 'baseColorTexture',\n 'metallicRoughnessTexture',\n 'normalTexture',\n 'emissiveTexture',\n 'occlusionTexture',\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 'transmissionTexture',\n 'thicknessTexture',\n ]) {\n baseNames.add(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 && (opts.alphaCutoff < 0 || opts.alphaCutoff > 1)) {\n throw new Error(`Materials.standard: alphaCutoff must be in [0, 1], got ${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 = 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: 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"]}
|