@forgeax/engine-render 0.1.23 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/README.md +131 -9
  2. package/dist/assembly/bundler-contract.d.ts +9 -0
  3. package/dist/assembly/bundler-contract.d.ts.map +1 -0
  4. package/dist/assembly/device-feature-admission.d.ts +8 -0
  5. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  6. package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
  7. package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +7 -243
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/material/assembly.d.ts +3 -2
  11. package/dist/assembly/material/assembly.d.ts.map +1 -1
  12. package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
  13. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
  14. package/dist/assembly/material-shader-policy.d.ts +168 -0
  15. package/dist/assembly/material-shader-policy.d.ts.map +1 -0
  16. package/dist/assembly/material-shader-prewarm.d.ts +21 -0
  17. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
  18. package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
  19. package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
  20. package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
  21. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
  22. package/dist/assembly/recovery/generation.d.ts +46 -0
  23. package/dist/assembly/recovery/generation.d.ts.map +1 -0
  24. package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
  25. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
  28. package/dist/assembly/renderer-facade.d.ts +10 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -0
  30. package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
  31. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  32. package/dist/assembly/renderer-helpers.d.ts +19 -0
  33. package/dist/assembly/renderer-helpers.d.ts.map +1 -0
  34. package/dist/assembly/renderer-lifecycle.d.ts +34 -0
  35. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
  36. package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
  37. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
  38. package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
  39. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +55 -0
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -0
  42. package/dist/assembly/webgpu-renderer.d.ts +152 -0
  43. package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
  44. package/dist/authoring.mjs +1 -1
  45. package/dist/{chunk-4L3P6DT5.mjs → chunk-GE3SDD72.mjs} +37 -5
  46. package/dist/chunk-GE3SDD72.mjs.map +1 -0
  47. package/dist/{chunk-HZUPSYW7.mjs → chunk-KZFTK6DO.mjs} +102 -15
  48. package/dist/chunk-KZFTK6DO.mjs.map +1 -0
  49. package/dist/{chunk-FF7K3FSO.mjs → chunk-Q752SHI5.mjs} +89 -89
  50. package/dist/{chunk-FF7K3FSO.mjs.map → chunk-Q752SHI5.mjs.map} +1 -1
  51. package/dist/{chunk-QODA5UKU.mjs → chunk-RR5L4SRS.mjs} +2 -2
  52. package/dist/chunk-RR5L4SRS.mjs.map +1 -0
  53. package/dist/{chunk-YALPS44A.mjs → chunk-TFH5I7JJ.mjs} +47 -47
  54. package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
  55. package/dist/{chunk-FBC4R44J.mjs → chunk-UQYS7FRM.mjs} +57 -57
  56. package/dist/chunk-UQYS7FRM.mjs.map +1 -0
  57. package/dist/{chunk-4NPUASZR.mjs → chunk-YKB5DQV7.mjs} +161 -19
  58. package/dist/chunk-YKB5DQV7.mjs.map +1 -0
  59. package/dist/{chunk-ZUWKAZ2I.mjs → chunk-YRUYGA4A.mjs} +615 -237
  60. package/dist/chunk-YRUYGA4A.mjs.map +1 -0
  61. package/dist/{chunk-DIYW3M5D.mjs → chunk-Z3YYH2MB.mjs} +2210 -2213
  62. package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
  63. package/dist/construct-renderer.mjs +19841 -16190
  64. package/dist/construct-renderer.mjs.map +1 -1
  65. package/dist/device/device-scope.d.ts +2 -0
  66. package/dist/device/device-scope.d.ts.map +1 -1
  67. package/dist/device/gpu-residency.d.ts +24 -4
  68. package/dist/device/gpu-residency.d.ts.map +1 -1
  69. package/dist/environment/frame.d.ts +5 -0
  70. package/dist/environment/frame.d.ts.map +1 -1
  71. package/dist/environment/inspection.d.ts +7 -0
  72. package/dist/environment/inspection.d.ts.map +1 -1
  73. package/dist/environment/lifecycle.d.ts +20 -2
  74. package/dist/environment/lifecycle.d.ts.map +1 -1
  75. package/dist/errors/recover.d.ts +58 -2
  76. package/dist/errors/recover.d.ts.map +1 -1
  77. package/dist/errors/render.d.ts +13 -0
  78. package/dist/errors/render.d.ts.map +1 -1
  79. package/dist/extract/contracts.d.ts +899 -0
  80. package/dist/extract/contracts.d.ts.map +1 -0
  81. package/dist/features/host.d.ts +2 -0
  82. package/dist/features/host.d.ts.map +1 -1
  83. package/dist/features/prepared-gpu-work.d.ts +3 -0
  84. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  85. package/dist/features/prepared-graphics-store.d.ts +2 -0
  86. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  87. package/dist/gpu-driven/production-raster.d.ts +28 -0
  88. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  89. package/dist/gpu-scene.d.ts +1 -0
  90. package/dist/gpu-scene.d.ts.map +1 -1
  91. package/dist/ibl/IblPipelineCache.d.ts +7 -6
  92. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  93. package/dist/ibl/skylight-bind-group.d.ts +7 -1
  94. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  95. package/dist/index.d.ts +1 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.mjs +6 -6
  98. package/dist/internal.mjs +6 -6
  99. package/dist/light-buffer-layout.d.ts +3 -0
  100. package/dist/light-buffer-layout.d.ts.map +1 -1
  101. package/dist/materials.d.ts +34 -10
  102. package/dist/materials.d.ts.map +1 -1
  103. package/dist/mesh-material-bindings.d.ts +56 -0
  104. package/dist/mesh-material-bindings.d.ts.map +1 -1
  105. package/dist/occlusion-proxy.d.ts +4 -0
  106. package/dist/occlusion-proxy.d.ts.map +1 -0
  107. package/dist/pbr-pipeline.d.ts +32 -9
  108. package/dist/pbr-pipeline.d.ts.map +1 -1
  109. package/dist/points-lines/prepare.d.ts +3 -0
  110. package/dist/points-lines/prepare.d.ts.map +1 -1
  111. package/dist/points-lines/standard-owner.d.ts +33 -0
  112. package/dist/points-lines/standard-owner.d.ts.map +1 -0
  113. package/dist/record/frame-snapshot.d.ts +5 -0
  114. package/dist/record/frame-snapshot.d.ts.map +1 -1
  115. package/dist/record/frame-targets.d.ts.map +1 -1
  116. package/dist/record/frame.d.ts +14 -2
  117. package/dist/record/frame.d.ts.map +1 -1
  118. package/dist/record/main-pass-geometry.d.ts +14 -1
  119. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  120. package/dist/record/main-pass-material.d.ts +7 -17
  121. package/dist/record/main-pass-material.d.ts.map +1 -1
  122. package/dist/record/main-pass.d.ts.map +1 -1
  123. package/dist/record/mesh-ssbo.d.ts +11 -3
  124. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  125. package/dist/record/recovery-pipeline.d.ts +30 -0
  126. package/dist/record/recovery-pipeline.d.ts.map +1 -0
  127. package/dist/record/render-context.d.ts +26 -4
  128. package/dist/record/render-context.d.ts.map +1 -1
  129. package/dist/record/typed-frame-graph.d.ts +1 -1
  130. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  131. package/dist/recovery/render-system-candidate.d.ts +65 -0
  132. package/dist/recovery/render-system-candidate.d.ts.map +1 -0
  133. package/dist/render-contract.d.ts +64 -7
  134. package/dist/render-contract.d.ts.map +1 -1
  135. package/dist/render-system-extract-tail.d.ts +12 -0
  136. package/dist/render-system-extract-tail.d.ts.map +1 -0
  137. package/dist/render-system-extract.d.ts +156 -22
  138. package/dist/render-system-extract.d.ts.map +1 -1
  139. package/dist/render-system.d.ts +128 -4
  140. package/dist/render-system.d.ts.map +1 -1
  141. package/dist/scene/render-scene.d.ts +19 -0
  142. package/dist/scene/render-scene.d.ts.map +1 -1
  143. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  144. package/dist/temporal/index.mjs +6 -6
  145. package/dist/temporal/taa-history-store.d.ts +15 -1
  146. package/dist/temporal/taa-history-store.d.ts.map +1 -1
  147. package/dist/temporal/transaction.d.ts +5 -0
  148. package/dist/temporal/transaction.d.ts.map +1 -1
  149. package/package.json +20 -20
  150. package/src/__tests__/device-feature-admission.unit.test.ts +6 -0
  151. package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
  152. package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
  153. package/src/__tests__/environment-generation.integration.test.ts +23 -0
  154. package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
  155. package/src/__tests__/factory-contract.integration.test.ts +122 -7
  156. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
  157. package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
  158. package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
  159. package/src/__tests__/material-contract-inventory.unit.test.ts +24 -9
  160. package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
  161. package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
  162. package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
  163. package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
  164. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  165. package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
  166. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +1 -1
  167. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
  168. package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
  169. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
  170. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +85 -18
  171. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
  172. package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
  173. package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
  174. package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
  175. package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
  176. package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
  177. package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
  178. package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
  179. package/src/__tests__/shader-manifest-fixture.ts +13 -16
  180. package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
  181. package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
  182. package/src/__tests__/transmission-prewarm.unit.test.ts +95 -85
  183. package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
  184. package/src/assembly/bundler-contract.ts +9 -0
  185. package/src/assembly/device-feature-admission.ts +15 -5
  186. package/src/assembly/extended-lighting-fallback.ts +216 -0
  187. package/src/assembly/factory.ts +81 -10088
  188. package/src/assembly/material/assembly.ts +18 -2
  189. package/src/assembly/material/standard-layer-projection.ts +16 -0
  190. package/src/assembly/material-shader-policy.ts +854 -0
  191. package/src/assembly/material-shader-prewarm.ts +88 -0
  192. package/src/assembly/mesh-ssbo-grow.ts +270 -0
  193. package/src/assembly/recovery/device-loss-fanout.ts +89 -0
  194. package/src/assembly/recovery/generation.ts +141 -0
  195. package/src/assembly/recovery/recovery-attempt.ts +800 -0
  196. package/src/assembly/recovery/renderer-recover.ts +906 -0
  197. package/src/assembly/renderer-facade.ts +342 -0
  198. package/src/assembly/renderer-frame-transaction.ts +45 -0
  199. package/src/assembly/renderer-helpers.ts +99 -0
  200. package/src/assembly/renderer-lifecycle.ts +159 -0
  201. package/src/assembly/shader-prewarm-policy.ts +157 -0
  202. package/src/assembly/webgpu-ready-contract.ts +14 -0
  203. package/src/assembly/webgpu-ready.ts +4079 -0
  204. package/src/assembly/webgpu-renderer.ts +4095 -0
  205. package/src/components/camera.ts +1 -1
  206. package/src/debug-draw-glue.ts +1 -1
  207. package/src/device/device-scope.ts +35 -6
  208. package/src/device/gpu-residency.ts +194 -26
  209. package/src/environment/frame.ts +6 -0
  210. package/src/environment/inspection.ts +10 -0
  211. package/src/environment/lifecycle.ts +114 -8
  212. package/src/errors/recover.ts +76 -5
  213. package/src/errors/render.ts +17 -0
  214. package/src/extract/contracts.ts +974 -0
  215. package/src/features/host.ts +16 -0
  216. package/src/features/prepared-gpu-work.ts +20 -2
  217. package/src/features/prepared-graphics-store.ts +17 -0
  218. package/src/gpu-driven/production-raster.ts +97 -2
  219. package/src/gpu-scene.ts +3 -2
  220. package/src/ibl/IblPipelineCache.ts +134 -50
  221. package/src/ibl/skylight-bind-group.ts +26 -0
  222. package/src/index.ts +9 -1
  223. package/src/light-buffer-layout.ts +3 -0
  224. package/src/materials.ts +262 -45
  225. package/src/mesh-material-bindings.ts +59 -0
  226. package/src/occlusion-proxy.ts +64 -0
  227. package/src/pbr-pipeline.ts +139 -15
  228. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
  229. package/src/points-lines/prepare.ts +9 -0
  230. package/src/points-lines/standard-owner.ts +403 -0
  231. package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
  232. package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
  233. package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
  234. package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
  235. package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
  236. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
  237. package/src/record/__tests__/temporal-payload.unit.test.ts +22 -43
  238. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -1
  239. package/src/record/frame-snapshot.ts +15 -0
  240. package/src/record/frame-targets.ts +11 -1
  241. package/src/record/frame.ts +6 -2
  242. package/src/record/helpers.ts +1 -1
  243. package/src/record/main-pass-geometry.ts +230 -5
  244. package/src/record/main-pass-material.ts +316 -209
  245. package/src/record/main-pass-sprite-draws.ts +6 -7
  246. package/src/record/main-pass.ts +94 -6
  247. package/src/record/mesh-ssbo.ts +32 -10
  248. package/src/record/recovery-pipeline.ts +695 -0
  249. package/src/record/render-context.ts +35 -4
  250. package/src/record/typed-frame-graph.ts +45 -1
  251. package/src/record/view-ubo.ts +3 -3
  252. package/src/recovery/render-system-candidate.ts +839 -0
  253. package/src/render-contract.ts +65 -7
  254. package/src/render-system-extract-tail.ts +2983 -0
  255. package/src/render-system-extract.ts +124 -2977
  256. package/src/render-system.ts +868 -659
  257. package/src/scene/render-scene.ts +124 -1
  258. package/src/temporal/frame-coordinator.ts +4 -1
  259. package/src/temporal/taa-history-store.ts +46 -2
  260. package/src/temporal/temporal-view.ts +1 -1
  261. package/src/temporal/transaction.ts +9 -0
  262. package/src/tilemap-chunk-extract-system.ts +1 -1
  263. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
  264. package/dist/chunk-4L3P6DT5.mjs.map +0 -1
  265. package/dist/chunk-4NPUASZR.mjs.map +0 -1
  266. package/dist/chunk-DIYW3M5D.mjs.map +0 -1
  267. package/dist/chunk-FBC4R44J.mjs.map +0 -1
  268. package/dist/chunk-HZUPSYW7.mjs.map +0 -1
  269. package/dist/chunk-QODA5UKU.mjs.map +0 -1
  270. package/dist/chunk-YALPS44A.mjs.map +0 -1
  271. package/dist/chunk-ZUWKAZ2I.mjs.map +0 -1
@@ -1,4 +1,6 @@
1
+ import { color } from '@forgeax/engine-math';
1
2
  import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA } from '@forgeax/engine-shader';
3
+ import { deriveStandardLayerPlan } from '@forgeax/engine-types';
2
4
 
3
5
  // src/materials.ts
4
6
  var MaterialTransmissionContractError = class extends Error {
@@ -24,22 +26,124 @@ var SPRITE_PREMULTIPLIED_ALPHA_BLEND = {
24
26
  };
25
27
  var STANDARD_MODULE = "forgeax_material::standard";
26
28
  var UNLIT_MODULE = "forgeax_material::unlit";
29
+ function colorHexFromNumber(value) {
30
+ if (!Number.isInteger(value) || value < 0 || value > 16777215) {
31
+ throw new Error(`material color number must be an integer in [0, 0xffffff], got ${value}`);
32
+ }
33
+ return `#${value.toString(16).padStart(6, "0")}`;
34
+ }
35
+ function linearColorFromInput(input, channels) {
36
+ if (typeof input === "number" || typeof input === "string") {
37
+ const parsed = color.create();
38
+ color.fromCss(parsed, typeof input === "number" ? colorHexFromNumber(input) : input);
39
+ return channels === 3 ? [parsed[0], parsed[1], parsed[2]] : Array.from(parsed);
40
+ }
41
+ if (input.length !== channels) {
42
+ throw new Error(`material color tuple must contain ${channels} channels, got ${input.length}`);
43
+ }
44
+ return [...input];
45
+ }
46
+ function srgb(input) {
47
+ if (input.length !== 3 && input.length !== 4) {
48
+ throw new Error(`sRGB material color tuple must contain 3 or 4 channels, got ${input.length}`);
49
+ }
50
+ const parsed = color.create(input[0] ?? 0, input[1] ?? 0, input[2] ?? 0, input[3] ?? 1);
51
+ color.srgbToLinear(parsed, parsed);
52
+ return input.length === 3 ? [parsed[0], parsed[1], parsed[2]] : [parsed[0], parsed[1], parsed[2], parsed[3]];
53
+ }
27
54
  function authoredColorParameter(name, type, colorSpace, optional = false) {
28
55
  return {
29
56
  name,
30
57
  type,
31
- ...colorSpace === "srgb" ? {} : { colorSpace },
58
+ ...{ colorSpace },
32
59
  ...optional ? { optional: true } : {}
33
60
  };
34
61
  }
35
- function standardParameters(colorSpace) {
36
- return DEFAULT_STANDARD_PBR_PARAM_SCHEMA.map((entry) => {
62
+ function standardParameters(colorSpace, opts) {
63
+ const physicalNames = /* @__PURE__ */ new Set();
64
+ const addPhysical = (...names) => {
65
+ for (const name of names) physicalNames.add(name);
66
+ };
67
+ if (opts.clearcoat !== void 0 || opts.clearcoatRoughness !== void 0 || opts.clearcoatNormalScale !== void 0 || opts.clearcoatTexture !== void 0 || opts.clearcoatRoughnessTexture !== void 0 || opts.clearcoatNormalTexture !== void 0) {
68
+ addPhysical(
69
+ "clearcoat",
70
+ "clearcoatRoughness",
71
+ "clearcoatNormalScale",
72
+ ...opts.clearcoatTexture === void 0 ? [] : ["clearcoatTexture"],
73
+ ...opts.clearcoatRoughnessTexture === void 0 ? [] : ["clearcoatRoughnessTexture"],
74
+ ...opts.clearcoatNormalTexture === void 0 ? [] : ["clearcoatNormalTexture"]
75
+ );
76
+ }
77
+ if (opts.anisotropyStrength !== void 0 || opts.anisotropyRotation !== void 0 || opts.anisotropyTexture !== void 0) {
78
+ addPhysical("anisotropyStrength", "anisotropyRotation");
79
+ if (opts.anisotropyTexture !== void 0) addPhysical("anisotropyTexture");
80
+ }
81
+ if (opts.sheenColor !== void 0 || opts.sheenRoughness !== void 0 || opts.sheenColorTexture !== void 0 || opts.sheenRoughnessTexture !== void 0) {
82
+ addPhysical("sheenColor", "sheenRoughness");
83
+ if (opts.sheenColorTexture !== void 0) addPhysical("sheenColorTexture");
84
+ if (opts.sheenRoughnessTexture !== void 0) addPhysical("sheenRoughnessTexture");
85
+ }
86
+ if (opts.iridescence !== void 0 || opts.iridescenceIor !== void 0 || opts.iridescenceThicknessMinimum !== void 0 || opts.iridescenceThicknessMaximum !== void 0 || opts.iridescenceTexture !== void 0 || opts.iridescenceThicknessTexture !== void 0) {
87
+ addPhysical(
88
+ "iridescence",
89
+ "iridescenceIor",
90
+ "iridescenceThicknessMinimum",
91
+ "iridescenceThicknessMaximum",
92
+ ...opts.iridescenceTexture === void 0 ? [] : ["iridescenceTexture"],
93
+ ...opts.iridescenceThicknessTexture === void 0 ? [] : ["iridescenceThicknessTexture"]
94
+ );
95
+ }
96
+ const baseNames = /* @__PURE__ */ new Set([
97
+ "baseColor",
98
+ "metallic",
99
+ "roughness",
100
+ "metallicChannel",
101
+ "roughnessChannel",
102
+ "aoChannel",
103
+ "extraChannel",
104
+ "emissive",
105
+ "emissiveIntensity",
106
+ "occlusionStrength",
107
+ "alphaCutoff",
108
+ "normalScale",
109
+ "baseColorTexture",
110
+ "metallicRoughnessTexture",
111
+ "normalTexture",
112
+ "emissiveTexture",
113
+ "occlusionTexture",
114
+ "specular",
115
+ "specularColor",
116
+ // IOR is part of the always-present dielectric F0 contract. The
117
+ // transmission layer may be absent, but the Standard shader still
118
+ // consumes this scalar for the base reflection path.
119
+ "ior"
120
+ ]);
121
+ if (opts.specularTexture !== void 0) baseNames.add("specularTexture");
122
+ if (opts.specularColorTexture !== void 0) baseNames.add("specularColorTexture");
123
+ if (opts.transmission !== void 0 || opts.ior !== void 0 || opts.thickness !== void 0 || opts.transmissionTexture !== void 0 || opts.thicknessTexture !== void 0 || opts.attenuationColor !== void 0 || opts.attenuationDistance !== void 0) {
124
+ for (const name of [
125
+ "transmission",
126
+ "ior",
127
+ "thickness",
128
+ "attenuationColor",
129
+ "attenuationDistance",
130
+ "transmissionTexture",
131
+ "thicknessTexture"
132
+ ]) {
133
+ baseNames.add(name);
134
+ }
135
+ }
136
+ const availableSchema = DEFAULT_STANDARD_PBR_PARAM_SCHEMA;
137
+ const numericSchema = availableSchema.filter((entry) => !entry.type.startsWith("texture"));
138
+ const textureSchema = availableSchema.filter((entry) => entry.type.startsWith("texture"));
139
+ const orderedSchema = [...numericSchema, ...textureSchema];
140
+ return orderedSchema.filter((entry) => baseNames.has(entry.name) || physicalNames.has(entry.name)).map((entry) => {
37
141
  const type = entry.type.startsWith("texture") ? "texture" : entry.type;
38
142
  const isRequired = entry.name === "baseColor" || entry.name === "metallic" || entry.name === "roughness";
39
143
  const authoredColor = entry.type === "color" || entry.type === "vec3" && entry.name !== "attenuationColor";
40
144
  const schemaColorSpace = "colorSpace" in entry ? entry.colorSpace : void 0;
41
145
  const colorSpaceProjection = {};
42
- if (authoredColor && !(type === "color" && colorSpace === "srgb")) {
146
+ if (authoredColor && true) {
43
147
  colorSpaceProjection.colorSpace = colorSpace;
44
148
  } else if (!authoredColor && schemaColorSpace !== void 0) {
45
149
  colorSpaceProjection.colorSpace = schemaColorSpace;
@@ -87,7 +191,7 @@ function unlit(rgba, opts) {
87
191
  if (opts?.alphaCutoff !== void 0 && (opts.alphaCutoff < 0 || opts.alphaCutoff > 1)) {
88
192
  throw new Error(`Materials.unlit: alphaCutoff must be in [0, 1], got ${opts.alphaCutoff}`);
89
193
  }
90
- const values = { baseColor: rgba };
194
+ const values = { baseColor: linearColorFromInput(rgba, 4) };
91
195
  if (opts?.baseColorTexture !== void 0) values.baseColorTexture = opts.baseColorTexture;
92
196
  if (opts?.alphaCutoff !== void 0) values.alphaCutoff = opts.alphaCutoff;
93
197
  const passes = [
@@ -98,9 +202,9 @@ function unlit(rgba, opts) {
98
202
  }
99
203
  return {
100
204
  kind: "material",
101
- ...opts?.colorSpace === void 0 || opts.colorSpace === "srgb" ? {} : { colorSpace: opts.colorSpace },
205
+ colorSpace: "linear",
102
206
  passes,
103
- parameters: unlitParameters(opts?.colorSpace ?? "srgb"),
207
+ parameters: unlitParameters("linear"),
104
208
  values
105
209
  };
106
210
  }
@@ -148,11 +252,12 @@ function standard(opts) {
148
252
  throw new MaterialTransmissionContractError("transmission", "depth-write", true);
149
253
  }
150
254
  const values = {
151
- baseColor: opts.baseColor,
255
+ baseColor: linearColorFromInput(opts.baseColor, 4),
152
256
  metallic: opts.metallic ?? 0,
153
257
  roughness: opts.roughness ?? 0.5,
154
258
  occlusionStrength,
155
- specularTint: opts.specularTint ?? [1, 1, 1],
259
+ specular: opts.specular ?? 1,
260
+ specularColor: opts.specularColor === void 0 ? [1, 1, 1] : linearColorFromInput(opts.specularColor, 3),
156
261
  transmission,
157
262
  ior,
158
263
  thickness,
@@ -162,7 +267,37 @@ function standard(opts) {
162
267
  if (opts.roughnessChannel !== void 0) values.roughnessChannel = opts.roughnessChannel;
163
268
  if (opts.clearcoat !== void 0) values.clearcoat = opts.clearcoat;
164
269
  if (opts.clearcoatRoughness !== void 0) values.clearcoatRoughness = opts.clearcoatRoughness;
165
- if (opts.emissive !== void 0) values.emissive = opts.emissive;
270
+ if (opts.clearcoatTexture !== void 0) values.clearcoatTexture = opts.clearcoatTexture;
271
+ if (opts.clearcoatRoughnessTexture !== void 0) {
272
+ values.clearcoatRoughnessTexture = opts.clearcoatRoughnessTexture;
273
+ }
274
+ if (opts.clearcoatNormalTexture !== void 0) {
275
+ values.clearcoatNormalTexture = opts.clearcoatNormalTexture;
276
+ }
277
+ if (opts.clearcoatNormalScale !== void 0)
278
+ values.clearcoatNormalScale = opts.clearcoatNormalScale;
279
+ if (opts.anisotropyStrength !== void 0) values.anisotropyStrength = opts.anisotropyStrength;
280
+ if (opts.anisotropyRotation !== void 0) values.anisotropyRotation = opts.anisotropyRotation;
281
+ if (opts.anisotropyTexture !== void 0) values.anisotropyTexture = opts.anisotropyTexture;
282
+ if (opts.sheenColor !== void 0) values.sheenColor = linearColorFromInput(opts.sheenColor, 3);
283
+ if (opts.sheenRoughness !== void 0) values.sheenRoughness = opts.sheenRoughness;
284
+ if (opts.sheenColorTexture !== void 0) values.sheenColorTexture = opts.sheenColorTexture;
285
+ if (opts.sheenRoughnessTexture !== void 0) {
286
+ values.sheenRoughnessTexture = opts.sheenRoughnessTexture;
287
+ }
288
+ if (opts.iridescence !== void 0) values.iridescence = opts.iridescence;
289
+ if (opts.iridescenceIor !== void 0) values.iridescenceIor = opts.iridescenceIor;
290
+ if (opts.iridescenceThicknessMinimum !== void 0) {
291
+ values.iridescenceThicknessMinimum = opts.iridescenceThicknessMinimum;
292
+ }
293
+ if (opts.iridescenceThicknessMaximum !== void 0) {
294
+ values.iridescenceThicknessMaximum = opts.iridescenceThicknessMaximum;
295
+ }
296
+ if (opts.iridescenceTexture !== void 0) values.iridescenceTexture = opts.iridescenceTexture;
297
+ if (opts.iridescenceThicknessTexture !== void 0) {
298
+ values.iridescenceThicknessTexture = opts.iridescenceThicknessTexture;
299
+ }
300
+ if (opts.emissive !== void 0) values.emissive = linearColorFromInput(opts.emissive, 3);
166
301
  if (opts.emissiveIntensity !== void 0) values.emissiveIntensity = opts.emissiveIntensity;
167
302
  if (opts.emissiveTexture !== void 0) values.emissiveTexture = opts.emissiveTexture;
168
303
  if (opts.baseColorTexture !== void 0) values.baseColorTexture = opts.baseColorTexture;
@@ -171,18 +306,25 @@ function standard(opts) {
171
306
  }
172
307
  if (opts.normalTexture !== void 0) values.normalTexture = opts.normalTexture;
173
308
  if (opts.occlusionTexture !== void 0) values.occlusionTexture = opts.occlusionTexture;
174
- if (opts.specularTintTexture !== void 0) {
175
- values.specularTintTexture = opts.specularTintTexture;
309
+ if (opts.specularTexture !== void 0) values.specularTexture = opts.specularTexture;
310
+ if (opts.specularColorTexture !== void 0) {
311
+ values.specularColorTexture = opts.specularColorTexture;
176
312
  }
177
313
  if (opts.alphaCutoff !== void 0) values.alphaCutoff = opts.alphaCutoff;
178
314
  if (opts.transmissionTexture !== void 0) values.transmissionTexture = opts.transmissionTexture;
179
315
  if (opts.thicknessTexture !== void 0) values.thicknessTexture = opts.thicknessTexture;
180
316
  if (opts.attenuationDistance !== void 0) values.attenuationDistance = opts.attenuationDistance;
181
317
  const forwardRenderState = transmission > 0 ? { ...opts.renderState ?? {}, depthWriteEnabled: false } : opts.renderState;
318
+ const parameters = standardParameters("linear", opts);
319
+ const declaredNames = new Set(parameters.map((parameter) => parameter.name));
320
+ for (const name of Object.keys(values)) {
321
+ if (!declaredNames.has(name)) delete values[name];
322
+ }
323
+ const physical = deriveStandardLayerPlan(parameters).mode === "physical";
182
324
  const passes = [
183
325
  pass("forward", STANDARD_MODULE, forwardRenderState, "fs_main", opts.queue)
184
326
  ];
185
- if (transmission === 0) {
327
+ if (!physical && transmission === 0) {
186
328
  passes.push(pass("deferred", STANDARD_MODULE, opts.renderState, "fs_gbuffer", opts.queue));
187
329
  }
188
330
  if (opts.castShadow !== false) {
@@ -190,14 +332,14 @@ function standard(opts) {
190
332
  }
191
333
  return {
192
334
  kind: "material",
193
- ...opts.colorSpace === void 0 || opts.colorSpace === "srgb" ? {} : { colorSpace: opts.colorSpace },
335
+ colorSpace: "linear",
194
336
  passes,
195
- parameters: standardParameters(opts.colorSpace ?? "srgb"),
337
+ parameters,
196
338
  values
197
339
  };
198
340
  }
199
- var Materials = { unlit, standard };
341
+ var Materials = { unlit, standard, srgb };
200
342
 
201
- export { MaterialTransmissionContractError, Materials, SPRITE_PREMULTIPLIED_ALPHA_BLEND };
202
- //# sourceMappingURL=chunk-4NPUASZR.mjs.map
203
- //# sourceMappingURL=chunk-4NPUASZR.mjs.map
343
+ export { MaterialTransmissionContractError, Materials, SPRITE_PREMULTIPLIED_ALPHA_BLEND, srgb };
344
+ //# sourceMappingURL=chunk-YKB5DQV7.mjs.map
345
+ //# sourceMappingURL=chunk-YKB5DQV7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/materials.ts"],"names":[],"mappings":"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","file":"chunk-YKB5DQV7.mjs","sourcesContent":["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';\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 STANDARD_MODULE = 'forgeax_material::standard';\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\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 standard(opts: StandardOpts): 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 physical = deriveStandardLayerPlan(parameters).mode === 'physical';\n const passes: [MaterialPass, ...MaterialPass[]] = [\n pass('forward', STANDARD_MODULE, forwardRenderState, 'fs_main', opts.queue),\n ];\n if (!physical && transmission === 0) {\n passes.push(pass('deferred', STANDARD_MODULE, opts.renderState, 'fs_gbuffer', opts.queue));\n }\n if (opts.castShadow !== false) {\n passes.push(pass('shadow-caster', STANDARD_MODULE, shadowCasterRenderState(opts.renderState)));\n }\n return {\n kind: 'material',\n colorSpace: 'linear',\n passes,\n parameters,\n values,\n };\n}\n\nexport const Materials = { unlit, standard, srgb } as const;\n\nexport { SPRITE_MODULE };\n"]}