@motion-core/motion-gpu 0.4.1 → 0.4.2

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 (205) hide show
  1. package/dist/advanced.d.ts +1 -0
  2. package/dist/advanced.d.ts.map +1 -0
  3. package/dist/advanced.js +12 -6
  4. package/dist/core/advanced.d.ts +1 -0
  5. package/dist/core/advanced.d.ts.map +1 -0
  6. package/dist/core/advanced.js +12 -5
  7. package/dist/core/current-value.d.ts +1 -0
  8. package/dist/core/current-value.d.ts.map +1 -0
  9. package/dist/core/current-value.js +35 -34
  10. package/dist/core/current-value.js.map +1 -0
  11. package/dist/core/error-diagnostics.d.ts +1 -0
  12. package/dist/core/error-diagnostics.d.ts.map +1 -0
  13. package/dist/core/error-diagnostics.js +70 -137
  14. package/dist/core/error-diagnostics.js.map +1 -0
  15. package/dist/core/error-report.d.ts +1 -0
  16. package/dist/core/error-report.d.ts.map +1 -0
  17. package/dist/core/error-report.js +184 -233
  18. package/dist/core/error-report.js.map +1 -0
  19. package/dist/core/frame-registry.d.ts +1 -0
  20. package/dist/core/frame-registry.d.ts.map +1 -0
  21. package/dist/core/frame-registry.js +546 -662
  22. package/dist/core/frame-registry.js.map +1 -0
  23. package/dist/core/index.d.ts +1 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +11 -12
  26. package/dist/core/material-preprocess.d.ts +1 -0
  27. package/dist/core/material-preprocess.d.ts.map +1 -0
  28. package/dist/core/material-preprocess.js +128 -151
  29. package/dist/core/material-preprocess.js.map +1 -0
  30. package/dist/core/material.d.ts +1 -0
  31. package/dist/core/material.d.ts.map +1 -0
  32. package/dist/core/material.js +263 -317
  33. package/dist/core/material.js.map +1 -0
  34. package/dist/core/recompile-policy.d.ts +1 -0
  35. package/dist/core/recompile-policy.d.ts.map +1 -0
  36. package/dist/core/recompile-policy.js +18 -13
  37. package/dist/core/recompile-policy.js.map +1 -0
  38. package/dist/core/render-graph.d.ts +1 -0
  39. package/dist/core/render-graph.d.ts.map +1 -0
  40. package/dist/core/render-graph.js +61 -68
  41. package/dist/core/render-graph.js.map +1 -0
  42. package/dist/core/render-targets.d.ts +1 -0
  43. package/dist/core/render-targets.d.ts.map +1 -0
  44. package/dist/core/render-targets.js +52 -53
  45. package/dist/core/render-targets.js.map +1 -0
  46. package/dist/core/renderer.d.ts +1 -0
  47. package/dist/core/renderer.d.ts.map +1 -0
  48. package/dist/core/renderer.js +942 -1081
  49. package/dist/core/renderer.js.map +1 -0
  50. package/dist/core/runtime-loop.d.ts +1 -0
  51. package/dist/core/runtime-loop.d.ts.map +1 -0
  52. package/dist/core/runtime-loop.js +305 -362
  53. package/dist/core/runtime-loop.js.map +1 -0
  54. package/dist/core/scheduler-helpers.d.ts +1 -0
  55. package/dist/core/scheduler-helpers.d.ts.map +1 -0
  56. package/dist/core/scheduler-helpers.js +52 -51
  57. package/dist/core/scheduler-helpers.js.map +1 -0
  58. package/dist/core/shader.d.ts +1 -0
  59. package/dist/core/shader.d.ts.map +1 -0
  60. package/dist/core/shader.js +92 -117
  61. package/dist/core/shader.js.map +1 -0
  62. package/dist/core/texture-loader.d.ts +1 -0
  63. package/dist/core/texture-loader.d.ts.map +1 -0
  64. package/dist/core/texture-loader.js +205 -273
  65. package/dist/core/texture-loader.js.map +1 -0
  66. package/dist/core/textures.d.ts +1 -0
  67. package/dist/core/textures.d.ts.map +1 -0
  68. package/dist/core/textures.js +106 -116
  69. package/dist/core/textures.js.map +1 -0
  70. package/dist/core/types.d.ts +1 -0
  71. package/dist/core/types.d.ts.map +1 -0
  72. package/dist/core/types.js +0 -4
  73. package/dist/core/uniforms.d.ts +1 -0
  74. package/dist/core/uniforms.d.ts.map +1 -0
  75. package/dist/core/uniforms.js +170 -191
  76. package/dist/core/uniforms.js.map +1 -0
  77. package/dist/index.d.ts +1 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +11 -6
  80. package/dist/passes/BlitPass.d.ts +1 -0
  81. package/dist/passes/BlitPass.d.ts.map +1 -0
  82. package/dist/passes/BlitPass.js +23 -18
  83. package/dist/passes/BlitPass.js.map +1 -0
  84. package/dist/passes/CopyPass.d.ts +1 -0
  85. package/dist/passes/CopyPass.d.ts.map +1 -0
  86. package/dist/passes/CopyPass.js +58 -52
  87. package/dist/passes/CopyPass.js.map +1 -0
  88. package/dist/passes/FullscreenPass.d.ts +1 -0
  89. package/dist/passes/FullscreenPass.d.ts.map +1 -0
  90. package/dist/passes/FullscreenPass.js +127 -130
  91. package/dist/passes/FullscreenPass.js.map +1 -0
  92. package/dist/passes/ShaderPass.d.ts +1 -0
  93. package/dist/passes/ShaderPass.d.ts.map +1 -0
  94. package/dist/passes/ShaderPass.js +40 -37
  95. package/dist/passes/ShaderPass.js.map +1 -0
  96. package/dist/passes/index.d.ts +1 -0
  97. package/dist/passes/index.d.ts.map +1 -0
  98. package/dist/passes/index.js +4 -3
  99. package/dist/react/FragCanvas.d.ts +1 -0
  100. package/dist/react/FragCanvas.d.ts.map +1 -0
  101. package/dist/react/FragCanvas.js +234 -211
  102. package/dist/react/FragCanvas.js.map +1 -0
  103. package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
  104. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
  105. package/dist/react/MotionGPUErrorOverlay.js +96 -13
  106. package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
  107. package/dist/react/Portal.d.ts +1 -0
  108. package/dist/react/Portal.d.ts.map +1 -0
  109. package/dist/react/Portal.js +18 -21
  110. package/dist/react/Portal.js.map +1 -0
  111. package/dist/react/advanced.d.ts +1 -0
  112. package/dist/react/advanced.d.ts.map +1 -0
  113. package/dist/react/advanced.js +12 -6
  114. package/dist/react/frame-context.d.ts +1 -0
  115. package/dist/react/frame-context.d.ts.map +1 -0
  116. package/dist/react/frame-context.js +88 -94
  117. package/dist/react/frame-context.js.map +1 -0
  118. package/dist/react/index.d.ts +1 -0
  119. package/dist/react/index.d.ts.map +1 -0
  120. package/dist/react/index.js +10 -9
  121. package/dist/react/motiongpu-context.d.ts +1 -0
  122. package/dist/react/motiongpu-context.d.ts.map +1 -0
  123. package/dist/react/motiongpu-context.js +18 -15
  124. package/dist/react/motiongpu-context.js.map +1 -0
  125. package/dist/react/use-motiongpu-user-context.d.ts +1 -0
  126. package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
  127. package/dist/react/use-motiongpu-user-context.js +83 -82
  128. package/dist/react/use-motiongpu-user-context.js.map +1 -0
  129. package/dist/react/use-texture.d.ts +1 -0
  130. package/dist/react/use-texture.d.ts.map +1 -0
  131. package/dist/react/use-texture.js +132 -152
  132. package/dist/react/use-texture.js.map +1 -0
  133. package/dist/svelte/FragCanvas.svelte.d.ts +1 -0
  134. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
  135. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
  136. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
  137. package/dist/svelte/Portal.svelte.d.ts +1 -0
  138. package/dist/svelte/Portal.svelte.d.ts.map +1 -0
  139. package/dist/svelte/advanced.d.ts +1 -0
  140. package/dist/svelte/advanced.d.ts.map +1 -0
  141. package/dist/svelte/advanced.js +11 -6
  142. package/dist/svelte/frame-context.d.ts +1 -0
  143. package/dist/svelte/frame-context.d.ts.map +1 -0
  144. package/dist/svelte/frame-context.js +27 -27
  145. package/dist/svelte/frame-context.js.map +1 -0
  146. package/dist/svelte/index.d.ts +1 -0
  147. package/dist/svelte/index.d.ts.map +1 -0
  148. package/dist/svelte/index.js +10 -9
  149. package/dist/svelte/motiongpu-context.d.ts +1 -0
  150. package/dist/svelte/motiongpu-context.d.ts.map +1 -0
  151. package/dist/svelte/motiongpu-context.js +24 -21
  152. package/dist/svelte/motiongpu-context.js.map +1 -0
  153. package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
  154. package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
  155. package/dist/svelte/use-motiongpu-user-context.js +69 -70
  156. package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
  157. package/dist/svelte/use-texture.d.ts +1 -0
  158. package/dist/svelte/use-texture.d.ts.map +1 -0
  159. package/dist/svelte/use-texture.js +125 -147
  160. package/dist/svelte/use-texture.js.map +1 -0
  161. package/package.json +12 -7
  162. package/src/lib/advanced.ts +6 -0
  163. package/src/lib/core/advanced.ts +12 -0
  164. package/src/lib/core/current-value.ts +64 -0
  165. package/src/lib/core/error-diagnostics.ts +236 -0
  166. package/src/lib/core/error-report.ts +406 -0
  167. package/src/lib/core/frame-registry.ts +1189 -0
  168. package/src/lib/core/index.ts +77 -0
  169. package/src/lib/core/material-preprocess.ts +284 -0
  170. package/src/lib/core/material.ts +667 -0
  171. package/src/lib/core/recompile-policy.ts +31 -0
  172. package/src/lib/core/render-graph.ts +143 -0
  173. package/src/lib/core/render-targets.ts +107 -0
  174. package/src/lib/core/renderer.ts +1547 -0
  175. package/src/lib/core/runtime-loop.ts +458 -0
  176. package/src/lib/core/scheduler-helpers.ts +136 -0
  177. package/src/lib/core/shader.ts +258 -0
  178. package/src/lib/core/texture-loader.ts +476 -0
  179. package/src/lib/core/textures.ts +235 -0
  180. package/src/lib/core/types.ts +582 -0
  181. package/src/lib/core/uniforms.ts +282 -0
  182. package/src/lib/index.ts +6 -0
  183. package/src/lib/passes/BlitPass.ts +54 -0
  184. package/src/lib/passes/CopyPass.ts +80 -0
  185. package/src/lib/passes/FullscreenPass.ts +173 -0
  186. package/src/lib/passes/ShaderPass.ts +88 -0
  187. package/src/lib/passes/index.ts +3 -0
  188. package/src/lib/react/FragCanvas.tsx +345 -0
  189. package/src/lib/react/MotionGPUErrorOverlay.tsx +392 -0
  190. package/src/lib/react/Portal.tsx +34 -0
  191. package/src/lib/react/advanced.ts +36 -0
  192. package/src/lib/react/frame-context.ts +169 -0
  193. package/src/lib/react/index.ts +51 -0
  194. package/src/lib/react/motiongpu-context.ts +88 -0
  195. package/src/lib/react/use-motiongpu-user-context.ts +186 -0
  196. package/src/lib/react/use-texture.ts +233 -0
  197. package/src/lib/svelte/FragCanvas.svelte +249 -0
  198. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +382 -0
  199. package/src/lib/svelte/Portal.svelte +31 -0
  200. package/src/lib/svelte/advanced.ts +32 -0
  201. package/src/lib/svelte/frame-context.ts +87 -0
  202. package/src/lib/svelte/index.ts +51 -0
  203. package/src/lib/svelte/motiongpu-context.ts +97 -0
  204. package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
  205. package/src/lib/svelte/use-texture.ts +232 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Framework-agnostic MotionGPU core entrypoint.
3
+ *
4
+ * This surface is intended for building framework adapters (Svelte/React/Vue).
5
+ */
6
+ export { defineMaterial, resolveMaterial } from './material.js';
7
+ export { toMotionGPUErrorReport } from './error-report.js';
8
+ export { createCurrentWritable } from './current-value.js';
9
+ export { createFrameRegistry } from './frame-registry.js';
10
+ export { createMotionGPURuntimeLoop } from './runtime-loop.js';
11
+ export { loadTexturesFromUrls } from './texture-loader.js';
12
+ export { BlitPass, CopyPass, ShaderPass } from '../passes/index.js';
13
+ export type { CurrentReadable, CurrentWritable, Subscribable } from './current-value.js';
14
+ export type {
15
+ MotionGPUErrorCode,
16
+ MotionGPUErrorContext,
17
+ MotionGPUErrorPhase,
18
+ MotionGPUErrorReport,
19
+ MotionGPUErrorSeverity,
20
+ MotionGPUErrorSource,
21
+ MotionGPUErrorSourceLine
22
+ } from './error-report.js';
23
+ export type {
24
+ FrameCallback,
25
+ FrameKey,
26
+ FrameProfilingSnapshot,
27
+ FrameRegistry,
28
+ FrameRunTimings,
29
+ FrameScheduleSnapshot,
30
+ FrameStage,
31
+ FrameStageCallback,
32
+ FrameTask,
33
+ FrameTaskInvalidation,
34
+ FrameTaskInvalidationToken,
35
+ FrameTimingStats,
36
+ UseFrameOptions,
37
+ UseFrameResult
38
+ } from './frame-registry.js';
39
+ export type {
40
+ FragMaterial,
41
+ FragMaterialInput,
42
+ MaterialDefineValue,
43
+ MaterialDefines,
44
+ MaterialIncludes,
45
+ ResolvedMaterial,
46
+ TypedMaterialDefineValue
47
+ } from './material.js';
48
+ export type { MotionGPURuntimeLoop, MotionGPURuntimeLoopOptions } from './runtime-loop.js';
49
+ export type { LoadedTexture, TextureDecodeOptions, TextureLoadOptions } from './texture-loader.js';
50
+ export type {
51
+ FrameInvalidationToken,
52
+ FrameState,
53
+ OutputColorSpace,
54
+ RenderPass,
55
+ RenderPassContext,
56
+ RenderPassFlags,
57
+ RenderPassInputSlot,
58
+ RenderPassOutputSlot,
59
+ RenderMode,
60
+ RenderTarget,
61
+ RenderTargetDefinition,
62
+ RenderTargetDefinitionMap,
63
+ TextureData,
64
+ TextureDefinition,
65
+ TextureDefinitionMap,
66
+ TextureMap,
67
+ TextureSource,
68
+ TextureUpdateMode,
69
+ TextureValue,
70
+ TypedUniform,
71
+ UniformLayout,
72
+ UniformLayoutEntry,
73
+ UniformMap,
74
+ UniformMat4Value,
75
+ UniformType,
76
+ UniformValue
77
+ } from './types.js';
@@ -0,0 +1,284 @@
1
+ import { assertUniformName } from './uniforms.js';
2
+ import type {
3
+ MaterialDefineValue,
4
+ MaterialDefines,
5
+ MaterialIncludes,
6
+ TypedMaterialDefineValue
7
+ } from './material.js';
8
+
9
+ const INCLUDE_DIRECTIVE_PATTERN = /^\s*#include\s+<([A-Za-z_][A-Za-z0-9_]*)>\s*$/;
10
+
11
+ /**
12
+ * Source location metadata for one generated fragment line.
13
+ */
14
+ export interface MaterialSourceLocation {
15
+ /**
16
+ * Origin category for this generated line.
17
+ */
18
+ kind: 'fragment' | 'include' | 'define';
19
+ /**
20
+ * 1-based line in the origin source.
21
+ */
22
+ line: number;
23
+ /**
24
+ * Include chunk identifier when `kind === "include"`.
25
+ */
26
+ include?: string;
27
+ /**
28
+ * Define identifier when `kind === "define"`.
29
+ */
30
+ define?: string;
31
+ }
32
+
33
+ /**
34
+ * 1-based line map from generated fragment WGSL to user source locations.
35
+ */
36
+ export type MaterialLineMap = Array<MaterialSourceLocation | null>;
37
+
38
+ /**
39
+ * Preprocess output used by material resolution and diagnostics mapping.
40
+ */
41
+ export interface PreprocessedMaterialFragment {
42
+ /**
43
+ * Final fragment source after defines/include expansion.
44
+ */
45
+ fragment: string;
46
+ /**
47
+ * 1-based generated-line source map.
48
+ */
49
+ lineMap: MaterialLineMap;
50
+ /**
51
+ * Deterministic WGSL define block used to build the final fragment source.
52
+ */
53
+ defineBlockSource: string;
54
+ }
55
+
56
+ function normalizeTypedDefine(
57
+ name: string,
58
+ define: TypedMaterialDefineValue
59
+ ): TypedMaterialDefineValue {
60
+ const value = define.value;
61
+
62
+ if (define.type === 'bool') {
63
+ if (typeof value !== 'boolean') {
64
+ throw new Error(`Invalid define value for "${name}". bool define requires boolean value.`);
65
+ }
66
+
67
+ return {
68
+ type: 'bool',
69
+ value
70
+ };
71
+ }
72
+
73
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
74
+ throw new Error(`Invalid define value for "${name}". Numeric define must be finite.`);
75
+ }
76
+
77
+ if ((define.type === 'i32' || define.type === 'u32') && !Number.isInteger(value)) {
78
+ throw new Error(`Invalid define value for "${name}". ${define.type} define requires integer.`);
79
+ }
80
+
81
+ if (define.type === 'u32' && value < 0) {
82
+ throw new Error(`Invalid define value for "${name}". u32 define must be >= 0.`);
83
+ }
84
+
85
+ return {
86
+ type: define.type,
87
+ value
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Validates and normalizes define entries.
93
+ */
94
+ export function normalizeDefines<TDefineKey extends string>(
95
+ defines: MaterialDefines<TDefineKey> | undefined
96
+ ): MaterialDefines<TDefineKey> {
97
+ const resolved: MaterialDefines<TDefineKey> = {} as MaterialDefines<TDefineKey>;
98
+
99
+ for (const [name, value] of Object.entries(defines ?? {}) as Array<
100
+ [TDefineKey, MaterialDefineValue]
101
+ >) {
102
+ assertUniformName(name);
103
+
104
+ if (typeof value === 'boolean') {
105
+ resolved[name] = value;
106
+ continue;
107
+ }
108
+
109
+ if (typeof value === 'number') {
110
+ if (!Number.isFinite(value)) {
111
+ throw new Error(`Invalid define value for "${name}". Define numbers must be finite.`);
112
+ }
113
+ resolved[name] = value;
114
+ continue;
115
+ }
116
+
117
+ const normalized = normalizeTypedDefine(name, value);
118
+ resolved[name] = Object.freeze(normalized);
119
+ }
120
+
121
+ return resolved;
122
+ }
123
+
124
+ /**
125
+ * Validates include map identifiers and source chunks.
126
+ */
127
+ export function normalizeIncludes<TIncludeKey extends string>(
128
+ includes: MaterialIncludes<TIncludeKey> | undefined
129
+ ): MaterialIncludes<TIncludeKey> {
130
+ const resolved: MaterialIncludes<TIncludeKey> = {} as MaterialIncludes<TIncludeKey>;
131
+
132
+ for (const [name, source] of Object.entries(includes ?? {}) as Array<[TIncludeKey, string]>) {
133
+ assertUniformName(name);
134
+ if (typeof source !== 'string' || source.trim().length === 0) {
135
+ throw new Error(`Invalid include "${name}". Include source must be a non-empty WGSL string.`);
136
+ }
137
+ resolved[name] = source;
138
+ }
139
+
140
+ return resolved;
141
+ }
142
+
143
+ /**
144
+ * Converts one define declaration to WGSL `const`.
145
+ */
146
+ export function toDefineLine(key: string, value: MaterialDefineValue): string {
147
+ if (typeof value === 'boolean') {
148
+ return `const ${key}: bool = ${value ? 'true' : 'false'};`;
149
+ }
150
+
151
+ if (typeof value === 'number') {
152
+ const valueLiteral = Number.isInteger(value) ? `${value}.0` : `${value}`;
153
+ return `const ${key}: f32 = ${valueLiteral};`;
154
+ }
155
+
156
+ if (value.type === 'bool') {
157
+ return `const ${key}: bool = ${value.value ? 'true' : 'false'};`;
158
+ }
159
+
160
+ if (value.type === 'f32') {
161
+ const numberValue = value.value as number;
162
+ const valueLiteral = Number.isInteger(numberValue) ? `${numberValue}.0` : `${numberValue}`;
163
+ return `const ${key}: f32 = ${valueLiteral};`;
164
+ }
165
+
166
+ if (value.type === 'i32') {
167
+ return `const ${key}: i32 = ${value.value};`;
168
+ }
169
+
170
+ return `const ${key}: u32 = ${value.value}u;`;
171
+ }
172
+
173
+ function expandChunk(
174
+ source: string,
175
+ kind: 'fragment' | 'include',
176
+ includeName: string | undefined,
177
+ includes: Record<string, string>,
178
+ stack: string[]
179
+ ): { lines: string[]; mapEntries: MaterialSourceLocation[] } {
180
+ const sourceLines = source.split('\n');
181
+ const lines: string[] = [];
182
+ const mapEntries: MaterialSourceLocation[] = [];
183
+
184
+ for (let index = 0; index < sourceLines.length; index += 1) {
185
+ const sourceLine = sourceLines[index];
186
+ if (sourceLine === undefined) {
187
+ continue;
188
+ }
189
+
190
+ const includeMatch = sourceLine.match(INCLUDE_DIRECTIVE_PATTERN);
191
+ if (!includeMatch) {
192
+ lines.push(sourceLine);
193
+ mapEntries.push({
194
+ kind,
195
+ line: index + 1,
196
+ ...(kind === 'include' && includeName ? { include: includeName } : {})
197
+ });
198
+ continue;
199
+ }
200
+
201
+ const includeKey = includeMatch[1];
202
+ if (!includeKey) {
203
+ throw new Error('Invalid include directive in fragment shader.');
204
+ }
205
+
206
+ assertUniformName(includeKey);
207
+ const includeSource = includes[includeKey];
208
+ if (!includeSource) {
209
+ throw new Error(`Unknown include "${includeKey}" referenced in fragment shader.`);
210
+ }
211
+
212
+ if (stack.includes(includeKey)) {
213
+ throw new Error(
214
+ `Circular include detected for "${includeKey}". Include stack: ${[...stack, includeKey].join(' -> ')}.`
215
+ );
216
+ }
217
+
218
+ const nested = expandChunk(includeSource, 'include', includeKey, includes, [
219
+ ...stack,
220
+ includeKey
221
+ ]);
222
+ lines.push(...nested.lines);
223
+ mapEntries.push(...nested.mapEntries);
224
+ }
225
+
226
+ return { lines, mapEntries };
227
+ }
228
+
229
+ /**
230
+ * Preprocesses material fragment with deterministic define/include expansion and line mapping.
231
+ */
232
+ export function preprocessMaterialFragment<
233
+ TDefineKey extends string,
234
+ TIncludeKey extends string
235
+ >(input: {
236
+ fragment: string;
237
+ defines?: MaterialDefines<TDefineKey>;
238
+ includes?: MaterialIncludes<TIncludeKey>;
239
+ }): PreprocessedMaterialFragment {
240
+ const normalizedDefines = normalizeDefines(input.defines);
241
+ const normalizedIncludes = normalizeIncludes(input.includes);
242
+
243
+ const fragmentExpanded = expandChunk(
244
+ input.fragment,
245
+ 'fragment',
246
+ undefined,
247
+ normalizedIncludes,
248
+ []
249
+ );
250
+ const defineEntries = (
251
+ Object.entries(normalizedDefines) as Array<[TDefineKey, MaterialDefineValue]>
252
+ ).sort(([a], [b]) => a.localeCompare(b));
253
+ const lines: string[] = [];
254
+ const defineLines: string[] = [];
255
+ const mapEntries: Array<MaterialSourceLocation | null> = [];
256
+
257
+ for (let index = 0; index < defineEntries.length; index += 1) {
258
+ const entry = defineEntries[index];
259
+ if (!entry) {
260
+ continue;
261
+ }
262
+
263
+ const [name, value] = entry;
264
+ const defineLine = toDefineLine(name, value);
265
+ lines.push(defineLine);
266
+ defineLines.push(defineLine);
267
+ mapEntries.push({ kind: 'define', line: index + 1, define: name });
268
+ }
269
+
270
+ if (defineEntries.length > 0) {
271
+ lines.push('');
272
+ mapEntries.push(null);
273
+ }
274
+
275
+ lines.push(...fragmentExpanded.lines);
276
+ mapEntries.push(...fragmentExpanded.mapEntries);
277
+
278
+ const lineMap: MaterialLineMap = [null, ...mapEntries];
279
+ return {
280
+ fragment: lines.join('\n'),
281
+ lineMap,
282
+ defineBlockSource: defineLines.join('\n')
283
+ };
284
+ }