@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.
Files changed (87) hide show
  1. package/README.md +18 -0
  2. package/dist/assembly/factory.d.ts +1 -1
  3. package/dist/assembly/factory.d.ts.map +1 -1
  4. package/dist/assembly/material/assembly.d.ts +4 -17
  5. package/dist/assembly/material/assembly.d.ts.map +1 -1
  6. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -1
  7. package/dist/assembly/material/surface-projection.d.ts.map +1 -1
  8. package/dist/assembly/webgpu-renderer.d.ts +0 -1
  9. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  10. package/dist/authoring.mjs +1 -1
  11. package/dist/{chunk-JSEDTZYS.mjs → chunk-GF523LHF.mjs} +6 -6
  12. package/dist/chunk-GF523LHF.mjs.map +1 -0
  13. package/dist/{chunk-TCLDX7SZ.mjs → chunk-TMIASV2N.mjs} +403 -457
  14. package/dist/chunk-TMIASV2N.mjs.map +1 -0
  15. package/dist/{chunk-N3RT2EUR.mjs → chunk-XDP6XE5V.mjs} +104 -56
  16. package/dist/chunk-XDP6XE5V.mjs.map +1 -0
  17. package/dist/construct-renderer.mjs +153 -13
  18. package/dist/construct-renderer.mjs.map +1 -1
  19. package/dist/extract/contracts.d.ts +6 -6
  20. package/dist/extract/contracts.d.ts.map +1 -1
  21. package/dist/index.mjs +1 -1
  22. package/dist/internal.mjs +1 -1
  23. package/dist/pipeline-spec-types.d.ts +2 -0
  24. package/dist/pipeline-spec-types.d.ts.map +1 -1
  25. package/dist/pipeline-spec.d.ts.map +1 -1
  26. package/dist/record/frame.d.ts.map +1 -1
  27. package/dist/record/main-pass-geometry.d.ts +2 -2
  28. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  29. package/dist/record/main-pass-material.d.ts +20 -2
  30. package/dist/record/main-pass-material.d.ts.map +1 -1
  31. package/dist/record/main-pass-sprite-draws.d.ts +3 -3
  32. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  33. package/dist/record/main-pass.d.ts.map +1 -1
  34. package/dist/record/material-uniforms.d.ts +4 -0
  35. package/dist/record/material-uniforms.d.ts.map +1 -0
  36. package/dist/record/render-context.d.ts +2 -2
  37. package/dist/record/render-context.d.ts.map +1 -1
  38. package/dist/record/shadow-pass.d.ts +2 -3
  39. package/dist/record/shadow-pass.d.ts.map +1 -1
  40. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  41. package/dist/render-system-extract-tail.d.ts +2 -0
  42. package/dist/render-system-extract-tail.d.ts.map +1 -1
  43. package/dist/render-system-extract.d.ts +27 -10
  44. package/dist/render-system-extract.d.ts.map +1 -1
  45. package/dist/render-system.d.ts.map +1 -1
  46. package/dist/temporal/index.mjs +2 -2
  47. package/package.json +20 -20
  48. package/src/__tests__/fixtures/ai-weapon-spirit/README.md +20 -0
  49. package/src/__tests__/fixtures/ai-weapon-spirit/low-poly-toon.wgsl +178 -0
  50. package/src/__tests__/fixtures/ai-weapon-spirit/material.json +97 -0
  51. package/src/__tests__/fixtures/ai-weapon-spirit/painterly-surface.wgsl +55 -0
  52. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +3 -3
  53. package/src/__tests__/gpu-driven-view.browser.test.ts +11 -3
  54. package/src/__tests__/material-contract-inventory.unit.test.ts +43 -0
  55. package/src/__tests__/{material-static-dynamic-route.unit.test.ts → material-layer-projection.unit.test.ts} +30 -47
  56. package/src/__tests__/material-program-dispatch.unit.test.ts +48 -0
  57. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +2 -2
  58. package/src/__tests__/skinned-shadow-caster.test.ts +14 -14
  59. package/src/__tests__/surface-variant-provenance.integration.test.ts +1 -1
  60. package/src/assembly/factory.ts +0 -3
  61. package/src/assembly/material/assembly.ts +8 -40
  62. package/src/assembly/material/standard-layer-projection.ts +3 -1
  63. package/src/assembly/material/surface-projection.ts +2 -1
  64. package/src/assembly/webgpu-renderer.ts +17 -9
  65. package/src/extract/contracts.ts +6 -6
  66. package/src/materials.ts +3 -3
  67. package/src/pipeline-spec-types.ts +2 -0
  68. package/src/pipeline-spec.ts +7 -3
  69. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +68 -1
  70. package/src/record/frame.ts +7 -1
  71. package/src/record/main-pass-geometry.ts +340 -279
  72. package/src/record/main-pass-material.ts +87 -2
  73. package/src/record/main-pass-sprite-draws.ts +65 -168
  74. package/src/record/main-pass.ts +24 -246
  75. package/src/record/material-uniforms.ts +186 -0
  76. package/src/record/render-context.ts +4 -0
  77. package/src/record/shadow-pass.ts +86 -28
  78. package/src/recovery/render-system-candidate.ts +5 -1
  79. package/src/render-system-extract-tail.ts +54 -13
  80. package/src/render-system-extract.ts +103 -64
  81. package/src/render-system.ts +19 -0
  82. package/dist/assembly/material/pipeline-projection.d.ts +0 -30
  83. package/dist/assembly/material/pipeline-projection.d.ts.map +0 -1
  84. package/dist/chunk-JSEDTZYS.mjs.map +0 -1
  85. package/dist/chunk-N3RT2EUR.mjs.map +0 -1
  86. package/dist/chunk-TCLDX7SZ.mjs.map +0 -1
  87. package/src/assembly/material/pipeline-projection.ts +0 -63
@@ -1,15 +1,15 @@
1
1
  import { GlyphText, selectActiveCameraIndex, getActiveCamera } from './chunk-FJ6P52EE.mjs';
2
2
  import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, Camera, bloomEnabledFromF32, antialiasFromF32, tonemapFromF32, cameraProjectionFromF32 } from './chunk-ADHHVYLW.mjs';
3
3
  import { SpriteRegionOverride, SpriteInstances } from './chunk-JDWARUOI.mjs';
4
- import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, selectPasses, resolveRenderTargetMaterialSource, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE } from './chunk-HKXTW355.mjs';
4
+ import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, selectPasses, resolveRenderTargetMaterialSource, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader } from './chunk-HKXTW355.mjs';
5
5
  import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, AtmosphereInvalidParameterError } from './chunk-ZZ4YQ474.mjs';
6
6
  import { err, ok, RhiError } from '@forgeax/engine-rhi';
7
- import { resolveAssetHandle, walkMaterialPassesOverSharedRefs } from '@forgeax/engine-assets-runtime';
7
+ import { resolveAssetHandle, walkMaterialPassesOverSharedRefs, selectMaterialPassProgram, materialParametersToParamSchema as materialParametersToParamSchema$1 } from '@forgeax/engine-assets-runtime';
8
8
  import { SpawnLightInvalidBoundsError, routeWorldError, SpriteInstancesMutuallyExclusiveWithInstancesError, SpriteInstancesRequiresSpriteShaderError, SpriteInstancesCountMismatchError, InstanceTransformsStrideMismatchError, readRenderArrayView } from '@forgeax/engine-ecs/projection';
9
9
  import { vec3, mat4, frustum, box3 } from '@forgeax/engine-math';
10
10
  import { AssetGuid } from '@forgeax/engine-pack/guid';
11
11
  import { Transform, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
12
- import { STANDARD_PIPELINE_PARAM_SCHEMA } from '@forgeax/engine-shader';
12
+ import { STANDARD_PIPELINE_PARAM_SCHEMA, DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';
13
13
  import { R_MIN, err as err$1, ok as ok$1, TextError, toShared, handleSlot, AssetError, ASSET_ERROR_HINTS, materialValuesToLinearRuntime, derive, unpackSlot, materialGuidText } from '@forgeax/engine-types';
14
14
  import { PROCEDURAL_FLOATS_PER_VERTEX, deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
15
15
  import { Skin, SkinInstancesCoexistForbiddenError, SkeletonResolveFailedError, JointCountMismatchError, JointEntityDanglingError } from '@forgeax/engine-skinning';
@@ -1639,6 +1639,7 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1639
1639
  return cache;
1640
1640
  })()
1641
1641
  },
1642
+ ...options.materialContext === void 0 ? {} : { materialContext: options.materialContext },
1642
1643
  cull: options.cull === "none" ? "none" : isCameraOwner ? "self" : "external",
1643
1644
  renderables: options.renderables ?? "full",
1644
1645
  ...options.renderableEntitiesByWorld?.[wi] === void 0 ? {} : { renderableEntities: options.renderableEntitiesByWorld[wi] },
@@ -2563,6 +2564,7 @@ function extractFrame(world, context) {
2563
2564
  const explicitlyHidden = /* @__PURE__ */ new Set();
2564
2565
  let dispatch = [];
2565
2566
  const materialSnapshotCache = /* @__PURE__ */ new Map();
2567
+ const skinnedMaterialSnapshotCache = /* @__PURE__ */ new Map();
2566
2568
  const meshRendererQuery = context.renderables === "none" ? [] : world.query({
2567
2569
  read: [MeshRenderer],
2568
2570
  optional: [
@@ -2777,7 +2779,7 @@ function extractFrame(world, context) {
2777
2779
  layerVal,
2778
2780
  materialSnap.paramSnapshot,
2779
2781
  0,
2780
- materialSnap.materialShaderId
2782
+ materialSnap.materialProgramKeys
2781
2783
  );
2782
2784
  }
2783
2785
  } else if (handleRaw === 0 || assets === void 0 || assets === null) {
@@ -2802,7 +2804,7 @@ function extractFrame(world, context) {
2802
2804
  layerVal,
2803
2805
  materialSnap.paramSnapshot,
2804
2806
  0,
2805
- materialSnap.materialShaderId
2807
+ materialSnap.materialProgramKeys
2806
2808
  );
2807
2809
  }
2808
2810
  } else {
@@ -2856,7 +2858,23 @@ function extractFrame(world, context) {
2856
2858
  }
2857
2859
  const resolved = resolvedResult.value;
2858
2860
  const allPasses = resolved.passes;
2859
- const firstPassShader = runtimeMaterialShaderIdForMaterial(asset, allPasses, assets);
2861
+ const materialContext = context.materialContext === void 0 ? void 0 : {
2862
+ ...context.materialContext,
2863
+ geometry: hasSkin ? "skinned" : context.materialContext.geometry
2864
+ };
2865
+ const materialProgramKeys = materialProgramKeysForMaterial(
2866
+ asset,
2867
+ assets,
2868
+ materialContext
2869
+ );
2870
+ const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(
2871
+ allPasses,
2872
+ void 0
2873
+ );
2874
+ const firstPassShader = runtimeMaterialShaderIdForMaterial(
2875
+ allPasses,
2876
+ materialProgramKeys
2877
+ );
2860
2878
  const pv = materialValuesToLinearRuntime(
2861
2879
  resolved.values,
2862
2880
  materialColorParameterSchema(resolved.parameters ?? [], firstPassShader, assets),
@@ -2880,9 +2898,10 @@ function extractFrame(world, context) {
2880
2898
  paramSnap[k] = v;
2881
2899
  }
2882
2900
  }
2883
- const materialParamSchema = materialParametersToParamSchema(
2901
+ const materialParamSchema = materialParamSchemaForMaterial(
2884
2902
  resolved.parameters ?? [],
2885
- firstPassShader
2903
+ authoredFirstPassShader,
2904
+ allPasses
2886
2905
  );
2887
2906
  {
2888
2907
  const hasSkinSkel = hasSkin && skinSkeletonView !== void 0 && skinSkeletonView !== void 0 && skinSkeletonView !== 0;
@@ -3044,6 +3063,7 @@ function extractFrame(world, context) {
3044
3063
  },
3045
3064
  normalScale: normalScalePv,
3046
3065
  materialShaderId: firstPassShader,
3066
+ materialProgramKeys,
3047
3067
  materialHandle: handleRaw,
3048
3068
  renderState: pipelineRenderState(allPasses[0]?.renderState),
3049
3069
  paramSnapshot: paramSnap,
@@ -3098,7 +3118,7 @@ function extractFrame(world, context) {
3098
3118
  layerVal,
3099
3119
  paramSnap,
3100
3120
  0,
3101
- firstPassShader
3121
+ materialProgramKeys
3102
3122
  );
3103
3123
  }
3104
3124
  }
@@ -3220,14 +3240,19 @@ function extractFrame(world, context) {
3220
3240
  if (assets !== void 0 && assets !== null) {
3221
3241
  for (let mi = 1; mi < materialHandles.length; mi++) {
3222
3242
  const subHandle = materialHandles[mi] ?? 0;
3223
- const cachedSubmaterial = materialSnapshotCache.get(subHandle);
3243
+ const subCache = hasSkin ? skinnedMaterialSnapshotCache : materialSnapshotCache;
3244
+ const cachedSubmaterial = subCache.get(subHandle);
3224
3245
  materialsArr.push(
3225
3246
  cachedSubmaterial?.snapshot ?? resolveMaterialSnapshot(
3226
3247
  subHandle,
3227
3248
  world,
3228
3249
  assets,
3229
- materialSnapshotCache,
3230
- persistentMaterialSnapshotCache
3250
+ subCache,
3251
+ hasSkin ? void 0 : persistentMaterialSnapshotCache,
3252
+ context.materialContext === void 0 ? void 0 : {
3253
+ ...context.materialContext,
3254
+ geometry: hasSkin ? "skinned" : context.materialContext.geometry
3255
+ }
3231
3256
  )
3232
3257
  );
3233
3258
  }
@@ -3236,7 +3261,11 @@ function extractFrame(world, context) {
3236
3261
  for (let mi = 1; mi < materialHandles.length; mi++) {
3237
3262
  const subHandle = materialHandles[mi] ?? 0;
3238
3263
  if (subHandle === handleRaw) continue;
3239
- const subEntry = materialSnapshotCache.get(subHandle) ?? readPersistentMaterialSnapshot(persistentMaterialSnapshotCache, subHandle, assets);
3264
+ const subEntry = (hasSkin ? skinnedMaterialSnapshotCache : materialSnapshotCache).get(subHandle) ?? (hasSkin ? void 0 : readPersistentMaterialSnapshot(
3265
+ persistentMaterialSnapshotCache,
3266
+ subHandle,
3267
+ assets
3268
+ ));
3240
3269
  appendMaterialDispatchEntries(
3241
3270
  pendingDispatch,
3242
3271
  subEntry?.passes ?? (subHandle === 0 ? [DEFAULT_FORWARD_PASS] : []),
@@ -3246,7 +3275,7 @@ function extractFrame(world, context) {
3246
3275
  layerVal,
3247
3276
  materialsArr[mi]?.paramSnapshot,
3248
3277
  0,
3249
- materialsArr[mi]?.materialShaderId
3278
+ materialsArr[mi]?.materialProgramKeys
3250
3279
  );
3251
3280
  }
3252
3281
  }
@@ -3553,14 +3582,16 @@ var DEFAULT_FORWARD_PASS = {
3553
3582
  program: { module: "forgeax::default-unlit", vertexEntry: "vs_main", fragmentEntry: "fs_main" },
3554
3583
  renderState: { tags: { LightMode: "Forward" }, queue: 2e3 }
3555
3584
  };
3556
- function appendMaterialDispatchEntries(pendingDispatch, passes, entity, materialHandle, renderableIndex, layer, paramSnapshot, passIndexOffset = 0, materialShaderIdOverride) {
3585
+ function appendMaterialDispatchEntries(pendingDispatch, passes, entity, materialHandle, renderableIndex, layer, paramSnapshot, passIndexOffset = 0, materialProgramKeys) {
3557
3586
  const matchedPasses = selectPasses(passes, {});
3558
3587
  for (let pIdx = 0; pIdx < matchedPasses.length; pIdx++) {
3559
3588
  const pass = matchedPasses[pIdx];
3560
3589
  if (pass === void 0) continue;
3561
3590
  const passState = pass.renderState ?? {};
3562
3591
  const authoredShaderId = runtimeMaterialShaderId(pass.program.module, pass.name);
3563
- const dispatchShaderId = authoredShaderId === "forgeax::default-shadow-caster" ? authoredShaderId : materialShaderIdOverride ?? authoredShaderId;
3592
+ const dispatchShaderId = materialProgramKeys === void 0 ? authoredShaderId : materialProgramKeys[pass.name];
3593
+ if (materialProgramKeys !== void 0 && dispatchShaderId === void 0)
3594
+ throw new Error(`Missing published material program for Pass ${pass.name}`);
3564
3595
  pendingDispatch.push({
3565
3596
  entityIndex: entity,
3566
3597
  materialHandle,
@@ -3575,13 +3606,6 @@ function appendMaterialDispatchEntries(pendingDispatch, passes, entity, material
3575
3606
  defines: void 0,
3576
3607
  vertexEntry: pass.program.vertexEntry,
3577
3608
  fragmentEntry: pass.program.fragmentEntry,
3578
- // A cooked Standard publication supplies one specialization key for its
3579
- // forward/deferred artifact, but its ShadowCaster pass still owns the
3580
- // engine depth-only shader. Keep the pass-local canonical identity so a
3581
- // specialized Standard source (which only declares fs_main/fs_gbuffer)
3582
- // is never asked to build an fs_shadow pipeline. Authored non-Standard
3583
- // ShadowCaster modules retain the publication override and continue to
3584
- // use their producer-owned source.
3585
3609
  materialShaderId: dispatchShaderId,
3586
3610
  paramSnapshot,
3587
3611
  ...passState.stencilReference !== void 0 && {
@@ -3678,9 +3702,38 @@ function runtimeMaterialShaderId(module, passName) {
3678
3702
  return module;
3679
3703
  }
3680
3704
  }
3681
- function runtimeMaterialShaderIdForMaterial(material, passes, assets) {
3682
- const authored = runtimeMaterialShaderId(passes[0]?.program.module, passes[0]?.name);
3683
- return assets.getMaterialProjectionForPayload(material)?.specializationKey ?? authored;
3705
+ function materialProgramKeysForMaterial(material, assets, context) {
3706
+ const projection = assets.getMaterialProjectionForPayload(material);
3707
+ if (projection === void 0) return void 0;
3708
+ if (context === void 0)
3709
+ throw new Error("Published material selection requires renderer-owned compiler context");
3710
+ return Object.fromEntries(
3711
+ projection.passes.map((pass) => {
3712
+ const mode = String(
3713
+ pass.renderState?.tags?.LightMode ?? pass.name
3714
+ );
3715
+ const selectedContext = {
3716
+ ...context,
3717
+ pass: /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward",
3718
+ pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
3719
+ };
3720
+ return [
3721
+ pass.name,
3722
+ selectMaterialPassProgram(projection, pass.name, selectedContext).specializationKey
3723
+ ];
3724
+ })
3725
+ );
3726
+ }
3727
+ function runtimeMaterialShaderIdForMaterial(passes, programs) {
3728
+ const pass = passes.find(
3729
+ (pass2) => !/shadow|depth/i.test(
3730
+ String(
3731
+ pass2.renderState?.tags?.LightMode ?? pass2.name
3732
+ )
3733
+ )
3734
+ ) ?? passes[0];
3735
+ if (pass === void 0) return void 0;
3736
+ return programs === void 0 ? runtimeMaterialShaderId(pass.program.module, pass.name) : programs[pass.name];
3684
3737
  }
3685
3738
  function pipelineRenderState(renderState) {
3686
3739
  if (renderState === void 0) return void 0;
@@ -3819,30 +3872,20 @@ function isEngineInjectedTextureField(shaderId, fieldName) {
3819
3872
  return isStandardPbrMaterialShader(shaderId) && ENGINE_INJECTED_TEXTURE_FIELDS.has(fieldName);
3820
3873
  }
3821
3874
  function materialParametersToParamSchema(parameters, shaderId) {
3822
- if (isCanonicalStandardPbrMaterialShader(shaderId)) {
3823
- return STANDARD_PIPELINE_PARAM_SCHEMA;
3824
- }
3825
- const engineInjectedTextureFields = isStandardPbrMaterialShader(shaderId) ? ENGINE_INJECTED_TEXTURE_FIELDS : void 0;
3826
- return parameters.flatMap((parameter) => {
3827
- if (parameter.type === "bool") return [];
3828
- if (parameter.type === "texture" || parameter.type === "texture_cube") {
3829
- if (engineInjectedTextureFields?.has(parameter.name) === true) return [];
3830
- return [
3831
- {
3832
- name: parameter.name,
3833
- type: parameter.type === "texture_cube" ? "texture_cube" : "texture2d",
3834
- default: parameter.default
3835
- }
3836
- ];
3837
- }
3838
- const numericDefault = typeof parameter.default === "number" ? parameter.default : Array.isArray(parameter.default) && parameter.default.every((entry) => typeof entry === "number") ? parameter.default : void 0;
3839
- const numericEntry = {
3840
- name: parameter.name,
3841
- type: parameter.type,
3842
- ...parameter.colorSpace === void 0 ? {} : { colorSpace: parameter.colorSpace }
3843
- };
3844
- return numericDefault === void 0 ? [numericEntry] : [{ ...numericEntry, default: numericDefault }];
3845
- });
3875
+ if (isCanonicalStandardPbrMaterialShader(shaderId)) return STANDARD_PIPELINE_PARAM_SCHEMA;
3876
+ return materialParametersToParamSchema$1(parameters);
3877
+ }
3878
+ function materialParamSchemaForMaterial(parameters, authoredShaderId, passes) {
3879
+ const firstPass = passes.find(
3880
+ (pass) => !/shadow|depth/i.test(
3881
+ String(
3882
+ pass.renderState?.tags?.LightMode ?? pass.name
3883
+ )
3884
+ )
3885
+ ) ?? passes[0];
3886
+ const surfaceModule = firstPass?.program.moduleSlots?.surface;
3887
+ const schemaShaderId = surfaceModule === void 0 || surfaceModule === DEFAULT_STANDARD_SURFACE_MODULE ? authoredShaderId : void 0;
3888
+ return materialParametersToParamSchema(parameters, schemaShaderId);
3846
3889
  }
3847
3890
  function materialColorParameterSchema(parameters, shaderId, assets) {
3848
3891
  if (shaderId === void 0) return parameters;
@@ -3907,7 +3950,7 @@ function storeMaterialSnapshot(cache, handleRaw, snapshot, passes, root, assets)
3907
3950
  cache.set(handleRaw, entry);
3908
3951
  return entry;
3909
3952
  }
3910
- function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache) {
3953
+ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache, materialContext) {
3911
3954
  if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
3912
3955
  const cached = materialSnapshotCache?.get(handleRaw);
3913
3956
  if (cached !== void 0) return cached.snapshot;
@@ -3938,7 +3981,9 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
3938
3981
  if (!resolvedResult.ok) return defaultMaterialSnapshot(handleRaw);
3939
3982
  const resolved = resolvedResult.value;
3940
3983
  const allPasses = resolved.passes;
3941
- const firstPassShader = runtimeMaterialShaderIdForMaterial(asset, allPasses, assetsRef);
3984
+ const materialProgramKeys = materialProgramKeysForMaterial(asset, assetsRef, materialContext);
3985
+ const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, void 0);
3986
+ const firstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, materialProgramKeys);
3942
3987
  const pv = materialValuesToLinearRuntime(
3943
3988
  resolved.values,
3944
3989
  materialColorParameterSchema(resolved.parameters ?? [], firstPassShader, assetsRef),
@@ -3962,9 +4007,10 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
3962
4007
  paramSnap[k] = v;
3963
4008
  }
3964
4009
  }
3965
- const materialParamSchema = materialParametersToParamSchema(
4010
+ const materialParamSchema = materialParamSchemaForMaterial(
3966
4011
  resolved.parameters ?? [],
3967
- firstPassShader
4012
+ authoredFirstPassShader,
4013
+ allPasses
3968
4014
  );
3969
4015
  const resolveTexLike = (value, brand) => {
3970
4016
  if (typeof value === "number") return toShared(value);
@@ -4014,6 +4060,7 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
4014
4060
  },
4015
4061
  normalScale: normalScalePv,
4016
4062
  materialShaderId: firstPassShader,
4063
+ materialProgramKeys,
4017
4064
  materialHandle: handleRaw,
4018
4065
  renderState: pipelineRenderState(allPasses[0]?.renderState),
4019
4066
  paramSnapshot: paramSnap,
@@ -4402,6 +4449,7 @@ function tonemapParams(camera) {
4402
4449
  function prepareExtractContext(world, options = {}) {
4403
4450
  const renderables = options.renderables ?? "full";
4404
4451
  return {
4452
+ materialContext: options.materialContext,
4405
4453
  assets: options.assets,
4406
4454
  pipelineState: options.pipelineState,
4407
4455
  materialSnapshotCache: options.materialSnapshotCache,
@@ -5131,5 +5179,5 @@ var ProbeBlendSceneProjection = class {
5131
5179
  };
5132
5180
 
5133
5181
  export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, createCookieProjectionMatrixData, createExtendedLightingState, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
5134
- //# sourceMappingURL=chunk-N3RT2EUR.mjs.map
5135
- //# sourceMappingURL=chunk-N3RT2EUR.mjs.map
5182
+ //# sourceMappingURL=chunk-XDP6XE5V.mjs.map
5183
+ //# sourceMappingURL=chunk-XDP6XE5V.mjs.map