@needle-tools/materialx 1.0.1-next.c1bbe8d → 1.0.1-next.c315a2f

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.
@@ -5,8 +5,8 @@
5
5
 
6
6
  import { getParam, getWorldDirection } from '@needle-tools/engine';
7
7
  import * as THREE from 'three';
8
-
9
- const debug = getParam("debugmaterialx");
8
+ import { debug, debugUpdate } from './utils';
9
+ import { MaterialX } from './materialx.types';
10
10
 
11
11
  const IMAGE_PROPERTY_SEPARATOR = "_";
12
12
  const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
@@ -20,8 +20,7 @@ const IMAGE_PATH_SEPARATOR = "/";
20
20
  * @param {Object} capabilities
21
21
  * @returns {THREE.Texture}
22
22
  */
23
- export function prepareEnvTexture(texture, capabilities)
24
- {
23
+ export function prepareEnvTexture(texture, capabilities) {
25
24
  let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type);
26
25
  newTexture.wrapS = THREE.RepeatWrapping;
27
26
  newTexture.anisotropy = capabilities.getMaxAnisotropy();
@@ -39,15 +38,12 @@ export function prepareEnvTexture(texture, capabilities)
39
38
  * @param {any} dimension
40
39
  * @returns {THREE.Uniform}
41
40
  */
42
- function fromVector(value, dimension)
43
- {
41
+ function fromVector(value, dimension) {
44
42
  let outValue;
45
- if (value)
46
- {
43
+ if (value) {
47
44
  outValue = [...value.data()];
48
45
  }
49
- else
50
- {
46
+ else {
51
47
  outValue = [];
52
48
  for (let i = 0; i < dimension; ++i)
53
49
  outValue.push(0.0);
@@ -58,23 +54,16 @@ function fromVector(value, dimension)
58
54
 
59
55
  /**
60
56
  * Get Three uniform from MaterialX matrix
61
- * @param {mx.matrix} matrix
62
- * @param {mx.matrix.size} dimension
63
57
  */
64
- function fromMatrix(matrix, dimension)
65
- {
66
- let vec = [];
67
- if (matrix)
68
- {
69
- for (let i = 0; i < matrix.numRows(); ++i)
70
- {
71
- for (let k = 0; k < matrix.numColumns(); ++k)
72
- {
58
+ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"]) {
59
+ const vec = new Array(dimension);
60
+ if (matrix) {
61
+ for (let i = 0; i < matrix.numRows(); ++i) {
62
+ for (let k = 0; k < matrix.numColumns(); ++k) {
73
63
  vec.push(matrix.getItem(i, k));
74
64
  }
75
65
  }
76
- } else
77
- {
66
+ } else {
78
67
  for (let i = 0; i < dimension; ++i)
79
68
  vec.push(0.0);
80
69
  }
@@ -82,94 +71,140 @@ function fromMatrix(matrix, dimension)
82
71
  return vec;
83
72
  }
84
73
 
74
+
75
+ export type Loaders = {
76
+ /**
77
+ * Cache key for the loaders, used to identify and reuse textures
78
+ */
79
+ readonly cacheKey: string;
80
+ /**
81
+ * Get a texture by path
82
+ * @param {string} path - The path to the texture
83
+ * @return {Promise<THREE.Texture>} - A promise that resolves to the texture
84
+ */
85
+ readonly getTexture: (path: string) => Promise<THREE.Texture>;
86
+ }
87
+
88
+ const defaultTexture = new THREE.Texture();
89
+ defaultTexture.needsUpdate = true;
90
+ defaultTexture.image = new Image();
91
+ defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFr6+vGqg52AAAAAxJREFUeJxjZGBEgQAAWAAJLpjsTQAAAABJRU5ErkJggg=="
92
+ // defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAB5QTFRFAAAABAQEw8PD////v7+/vb29Xl5eQEBA+/v7PDw8GPBYkgAAAB1JREFUeJxjZGBgYFQSABIUMlxgDGMGBtaIAnIZAKwQCSDYUEZEAAAAAElFTkSuQmCC";
93
+ // defaultTexture.wrapS = THREE.RepeatWrapping;
94
+ // defaultTexture.wrapT = THREE.RepeatWrapping;
95
+ // defaultTexture.minFilter = THREE.NearestFilter;
96
+ // defaultTexture.magFilter = THREE.NearestFilter;
97
+ // defaultTexture.repeat = new THREE.Vector2(100, 100);
98
+
99
+
100
+ const defaultNormalTexture = new THREE.Texture();
101
+ defaultNormalTexture.needsUpdate = true;
102
+ defaultNormalTexture.image = new Image();
103
+ defaultNormalTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=";
104
+
105
+
106
+ function tryGetFromCache(key: string): any {
107
+ const wasEnabled = THREE.Cache.enabled;
108
+ THREE.Cache.enabled = true;
109
+ const value = THREE.Cache.get(key);
110
+ THREE.Cache.enabled = wasEnabled;
111
+ return value;
112
+ }
113
+ function addToCache(key: string, value: any): void {
114
+ const wasEnabled = THREE.Cache.enabled;
115
+ THREE.Cache.enabled = true;
116
+ THREE.Cache.add(key, value);
117
+ THREE.Cache.enabled = wasEnabled;
118
+ if (debug) console.log('[MaterialX] Added to cache:', key, value);
119
+ }
120
+
85
121
  /**
86
122
  * Get Three uniform from MaterialX value
87
- * @param {mx.Uniform.type} type
88
- * @param {mx.Uniform.value} value
89
- * @param {mx.Uniform.name} name
90
- * @param {mx.Uniforms} uniforms
91
- * @param {THREE.TextureLoader} textureLoader
92
- * @param {string} searchPath
93
- * @param {boolean} flipY
94
123
  */
95
- function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, flipY)
96
- {
97
- let outValue = null;
98
- switch (type)
99
- {
124
+ function toThreeUniform(uniforms: any, type: string, value: any, name: string, loaders: Loaders, searchPath: string): THREE.Uniform {
125
+
126
+ const uniform = new THREE.Uniform<any>(null);
127
+
128
+ switch (type) {
100
129
  case 'float':
101
130
  case 'integer':
102
131
  case 'boolean':
103
- outValue = value;
132
+ uniform.value = value;
104
133
  break;
105
134
  case 'vector2':
106
- outValue = fromVector(value, 2);
135
+ uniform.value = fromVector(value, 2);
107
136
  break;
108
137
  case 'vector3':
109
138
  case 'color3':
110
- outValue = fromVector(value, 3);
139
+ uniform.value = fromVector(value, 3);
111
140
  break;
112
141
  case 'vector4':
113
142
  case 'color4':
114
- outValue = fromVector(value, 4);
143
+ uniform.value = fromVector(value, 4);
115
144
  break;
116
145
  case 'matrix33':
117
- outValue = fromMatrix(value, 9);
146
+ uniform.value = fromMatrix(value, 9);
118
147
  break;
119
148
  case 'matrix44':
120
- outValue = fromMatrix(value, 16);
149
+ uniform.value = fromMatrix(value, 16);
121
150
  break;
122
151
  case 'filename':
123
- if (value)
124
- {
152
+ if (value) {
125
153
  // Cache / reuse texture to avoid reload overhead.
126
154
  // Note: that data blobs and embedded data textures are not cached as they are transient data.
127
- let checkCache = false;
155
+ let checkCache = true;
128
156
  let texturePath = searchPath + IMAGE_PATH_SEPARATOR + value;
129
- if (value.startsWith('blob:'))
130
- {
157
+ if (value.startsWith('blob:')) {
131
158
  texturePath = value;
132
- if (debug) console.log('Load blob URL:', texturePath);
133
159
  checkCache = false;
134
160
  }
135
- else if (value.startsWith('http'))
136
- {
161
+ else if (value.startsWith('data:')) {
137
162
  texturePath = value;
138
- if (debug) console.log('Load HTTP URL:', texturePath);
163
+ checkCache = false;
139
164
  }
140
- else if (value.startsWith('data:'))
141
- {
165
+ else if (value.startsWith('http')) {
142
166
  texturePath = value;
143
- checkCache = false;
144
- if (debug) console.log('Load data URL:', texturePath);
167
+ checkCache = true;
145
168
  }
146
- const cachedTexture = checkCache && THREE.Cache.get(texturePath);
147
- if (cachedTexture)
148
- {
149
- // Get texture from cache
150
- outValue = cachedTexture;
151
- if (debug) console.log('Use cached texture: ', texturePath, outValue);
169
+
170
+ const cacheKey = `${loaders.cacheKey}-${texturePath}`;
171
+ const cacheValue = checkCache ? tryGetFromCache(cacheKey) : null;
172
+ if (cacheValue) {
173
+ if (debug) console.log('[MaterialX] Use cached texture: ', cacheKey, cacheValue);
174
+ if (cacheValue instanceof Promise) {
175
+ cacheValue.then(res => {
176
+ if (res) uniform.value = res;
177
+ else console.warn(`[MaterialX] Failed to load texture ${name} '${texturePath}'`);
178
+ });
179
+ }
180
+ else {
181
+ uniform.value = cacheValue;
182
+ }
152
183
  }
153
- else
154
- {
155
- outValue = textureLoader.load(
156
- texturePath,
157
- function (texture) {
158
- if (debug) console.log('Load new texture: ' + texturePath, texture);
159
- outValue = texture;
160
-
161
- // Add texture to ThreeJS cache
162
- if (checkCache)
163
- THREE.Cache.add(texturePath, texture);
164
- },
165
- undefined,
166
- function (error) {
167
- console.error('Error loading texture: ', error);
168
- });
169
-
170
- // Set address & filtering mode
171
- if (outValue)
172
- setTextureParameters(outValue, name, uniforms, flipY);
184
+ else {
185
+ if (name.toLowerCase().includes("normal")) {
186
+ uniform.value = defaultNormalTexture;
187
+ }
188
+ else {
189
+ uniform.value = defaultTexture;
190
+ }
191
+
192
+ if (debug) console.log('[MaterialX] Load texture:', texturePath);
193
+ // Save the loading promise in the cache
194
+ const promise = loaders.getTexture(texturePath).then(res => {
195
+ if (res) {
196
+ res.colorSpace = THREE.LinearSRGBColorSpace;
197
+ setTextureParameters(res, name, uniforms);
198
+ }
199
+ return res;
200
+ });
201
+ if (checkCache) {
202
+ addToCache(cacheKey, promise);
203
+ }
204
+ promise.then(res => {
205
+ if (res) uniform.value = res;
206
+ else console.warn(`[MaterialX] Failed to load texture ${name} '${texturePath}'`);
207
+ });
173
208
  }
174
209
  }
175
210
  break;
@@ -178,29 +213,24 @@ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath,
178
213
  break;
179
214
  default:
180
215
  const key = type + ':' + name;
181
- if (!valueTypeWarningMap.has(key))
182
- {
216
+ if (!valueTypeWarningMap.has(key)) {
183
217
  valueTypeWarningMap.set(key, true);
184
218
  console.warn('MaterialX: Unsupported uniform type: ' + type + ' for uniform: ' + name, value);
185
219
  }
186
- outValue = null;
220
+ break;
187
221
  }
188
222
 
189
- return outValue;
223
+ return uniform;
190
224
  }
191
225
 
192
- const valueTypeWarningMap = new Map();
226
+ const valueTypeWarningMap = new Map<string, boolean>();
193
227
 
194
228
  /**
195
229
  * Get Three wrapping mode
196
- * @param {mx.TextureFilter.wrap} mode
197
- * @returns {THREE.Wrapping}
198
230
  */
199
- function getWrapping(mode)
200
- {
231
+ function getWrapping(mode: number): THREE.Wrapping {
201
232
  let wrap;
202
- switch (mode)
203
- {
233
+ switch (mode) {
204
234
  case 1:
205
235
  wrap = THREE.ClampToEdgeWrapping;
206
236
  break;
@@ -217,61 +247,36 @@ function getWrapping(mode)
217
247
  return wrap;
218
248
  }
219
249
 
220
- /**
221
- * Get Three minification filter
222
- * @param {mx.TextureFilter.minFilter} type
223
- * @param {mx.TextureFilter.generateMipmaps} generateMipmaps
224
- */
225
- function getMinFilter(type, generateMipmaps)
226
- {
227
- /** @type {THREE.TextureFilter} */
228
- let filterType = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
229
- if (type === 0)
230
- {
231
- filterType = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
232
- }
233
- return filterType;
234
- }
235
250
 
236
251
  /**
237
252
  * Set Three texture parameters
238
- * @param {THREE.Texture} texture
239
- * @param {mx.Uniform.name} name
240
- * @param {mx.Uniforms} uniforms
241
- * @param {mx.TextureFilter.generateMipmaps} generateMipmaps
242
253
  */
243
- function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
244
- {
254
+ function setTextureParameters(texture: THREE.Texture, name: string, uniforms: any, generateMipmaps = true) {
245
255
  const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
246
256
  const base = name.substring(0, idx) || name;
247
257
 
248
- texture.generateMipmaps = generateMipmaps;
249
- texture.wrapS = THREE.RepeatWrapping;
250
- texture.wrapT = THREE.RepeatWrapping;
251
- texture.magFilter = THREE.LinearFilter;
252
- texture.flipY = flipY;
253
-
254
- if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
255
- {
258
+ if (uniforms.find(base + UADDRESS_MODE_SUFFIX)) {
256
259
  const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData();
257
260
  texture.wrapS = getWrapping(uaddressmode);
258
261
  }
259
262
 
260
- if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
261
- {
263
+ if (uniforms.find(base + VADDRESS_MODE_SUFFIX)) {
262
264
  const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData();
263
265
  texture.wrapT = getWrapping(vaddressmode);
264
266
  }
265
267
 
266
- const filterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
267
- texture.minFilter = getMinFilter(filterType, generateMipmaps);
268
+ const mxFilterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
269
+ let minFilter: THREE.TextureFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
270
+ if (mxFilterType === 0) {
271
+ minFilter = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
272
+ }
273
+ texture.minFilter = minFilter;
268
274
  }
269
275
 
270
276
  /**
271
277
  * Return the global light rotation matrix
272
278
  */
273
- export function getLightRotation()
274
- {
279
+ export function getLightRotation() {
275
280
  return new THREE.Matrix4().makeRotationY(Math.PI / 2);
276
281
  }
277
282
 
@@ -280,11 +285,9 @@ export function getLightRotation()
280
285
  * @param {mx.Document} doc
281
286
  * @returns {Array.<mx.Node>}
282
287
  */
283
- export function findLights(doc)
284
- {
285
- let lights = [];
286
- for (let node of doc.getNodes())
287
- {
288
+ export function findLights(doc: MaterialX.Document) {
289
+ let lights = new Array<any>;
290
+ for (let node of doc.getNodes()) {
288
291
  if (node.getType() === "lightshader")
289
292
  lights.push(node);
290
293
  }
@@ -295,19 +298,14 @@ let lightTypesBound = {};
295
298
 
296
299
  /**
297
300
  * Register lights in shader generation context
298
- * @param {Object} mx MaterialX Module
301
+ * @param {MaterialX.MODULE} mx MaterialX Module
299
302
  * @param {mx.GenContext} genContext Shader generation context
300
- * @returns {Array.<mx.Node>}
301
303
  */
302
- export async function registerLights(mx, genContext)
303
- {
304
+ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Promise<void> {
304
305
  lightTypesBound = {};
305
306
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
306
-
307
307
  mx.HwShaderGenerator.unbindLightShaders(genContext);
308
-
309
308
  let lightId = 1;
310
-
311
309
  // All light types so that we have NodeDefs for them
312
310
  const defaultLightRigXml = `<?xml version="1.0"?>
313
311
  <materialx version="1.39">
@@ -325,30 +323,27 @@ export async function registerLights(mx, genContext)
325
323
 
326
324
  // Load default light rig XML to ensure we have all light types available
327
325
  const lightRigDoc = mx.createDocument();
328
- await mx.readFromXmlString(lightRigDoc, defaultLightRigXml);
326
+ await mx.readFromXmlString(lightRigDoc, defaultLightRigXml, "");
329
327
  const document = mx.createDocument();
330
328
  const stdlib = mx.loadStandardLibraries(genContext);
331
329
  document.setDataLibrary(stdlib);
332
330
  document.importLibrary(lightRigDoc);
333
331
  const defaultLights = findLights(document);
334
- // if (debug)
335
- console.log("Default lights in MaterialX document", defaultLights);
332
+ if (debug) console.log("Default lights in MaterialX document", defaultLights);
336
333
 
337
334
  // Loading a document seems to reset this option for some reason, so we set it again
338
335
  genContext.getOptions().hwMaxActiveLightSources = maxLightCount;
339
336
 
340
337
  // Register types only – we get these from the default light rig XML above
341
338
  // This is needed to ensure that the light shaders are bound for each light type
342
- for (let light of defaultLights)
343
- {
339
+ for (let light of defaultLights) {
344
340
  const lightDef = light.getNodeDef();
345
341
  if (debug) console.log("Default light node definition", lightDef);
346
342
  if (!lightDef) continue;
347
343
 
348
344
  const lightName = lightDef.getName();
349
345
  if (debug) console.log("Registering default light", { lightName, lightDef });
350
- if (!lightTypesBound[lightName])
351
- {
346
+ if (!lightTypesBound[lightName]) {
352
347
  // TODO check if we need to bind light shader for each three.js light instead of once per type
353
348
  if (debug) console.log("Bind light shader for node", { lightName, lightId, lightDef });
354
349
  lightTypesBound[lightName] = lightId;
@@ -374,16 +369,22 @@ function threeLightTypeToMaterialXNodeName(threeLightType) {
374
369
  }
375
370
  };
376
371
 
372
+ type LightData = {
373
+ type: number, // Light type ID
374
+ position: THREE.Vector3, // Position in world space
375
+ direction: THREE.Vector3, // Direction in world space
376
+ color: THREE.Color, // Color of the light
377
+ intensity: number, // Intensity of the light
378
+ decay_rate: number, // Decay rate for point and spot lights
379
+ inner_angle: number, // Inner angle for spot lights
380
+ outer_angle: number, // Outer angle for spot lights
381
+ }
382
+
377
383
  /**
378
384
  * Update light data for shader uniforms
379
- * @param {Object} mx MaterialX Module
380
- * @param {Array.<mx.Node>} lights Light nodes
381
- * @param {mx.GenContext} genContext Shader generation context
382
- * @returns {{ lightData: Array<any>, lightCount: number }}
383
385
  */
384
- export function getLightData(mx, lights, genContext)
385
- {
386
- const lightData = [];
386
+ export function getLightData(lights: any, genContext: any): { lightData: LightData[], lightCount: number } {
387
+ const lightData = new Array();
387
388
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
388
389
 
389
390
  // Three.js lights
@@ -399,9 +400,18 @@ export function getLightData(mx, lights, genContext)
399
400
  console.error("MaterialX: Light type not registered in context. Make sure to register light types before using them.", lightDefinitionName);
400
401
 
401
402
  const wp = light.getWorldPosition(new THREE.Vector3());
402
- const wd = getWorldDirection(light, new THREE.Vector3(0,0,-1));
403
+ const wd = getWorldDirection(light, new THREE.Vector3(0, 0, -1));
403
404
 
404
- // console.log("Registering light", light.penumbra);
405
+ // Shader math from the generated MaterialX shader:
406
+ // float low = min(light.inner_angle, light.outer_angle);
407
+ // float high = light.inner_angle;
408
+ // float cosDir = dot(result.direction, -light.direction);
409
+ // float spotAttenuation = smoothstep(low, high, cosDir);
410
+
411
+ const outerAngleRad = light.angle;
412
+ const innerAngleRad = outerAngleRad * (1 - light.penumbra);
413
+ const inner_angle = Math.cos(innerAngleRad);
414
+ const outer_angle = Math.cos(outerAngleRad);
405
415
 
406
416
  lightData.push({
407
417
  type: lightTypesBound[lightDefinitionName],
@@ -410,11 +420,11 @@ export function getLightData(mx, lights, genContext)
410
420
  color: new THREE.Color().fromArray(light.color.toArray()),
411
421
  // Luminous efficacy for converting radiant power in watts (W) to luminous flux in lumens (lm) at a wavelength of 555 nm.
412
422
  // Also, three.js lights don't have PI scale baked in, but MaterialX does, so we need to divide by PI for point and spot lights.
413
- intensity: light.intensity * (light.isPointLight ? 683.0 / 3.1415 : light.isSpotLight ? 683.0 / 3.1415: 1.0),
423
+ intensity: light.intensity * (light.isPointLight ? 683.0 / 3.1415 : light.isSpotLight ? 683.0 / 3.1415 : 1.0),
414
424
  decay_rate: 2.0,
415
425
  // Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
416
- inner_angle: 0.9,
417
- outer_angle: 0.4,
426
+ inner_angle: inner_angle,
427
+ outer_angle: outer_angle,
418
428
  });
419
429
  }
420
430
 
@@ -422,8 +432,7 @@ export function getLightData(mx, lights, genContext)
422
432
  const lightCount = lightData.length;
423
433
 
424
434
  // If we don't have enough entries in lightData, fill with empty lights
425
- while (lightData.length < maxLightCount)
426
- {
435
+ while (lightData.length < maxLightCount) {
427
436
  const emptyLight = {
428
437
  type: 0, // Default light type
429
438
  position: new THREE.Vector3(0, 0, 0),
@@ -437,38 +446,32 @@ export function getLightData(mx, lights, genContext)
437
446
  lightData.push(emptyLight);
438
447
  }
439
448
 
440
- if (debug)
441
- console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
449
+ if (debugUpdate) console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
442
450
 
443
451
  return { lightData, lightCount };
444
452
  }
445
453
 
446
454
  /**
447
455
  * Get uniform values for a shader
448
- * @param {mx.shaderStage} shaderStage
449
- * @param {THREE.TextureLoader} textureLoader
450
456
  */
451
- export function getUniformValues(shaderStage, textureLoader, searchPath, flipY)
452
- {
457
+ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Loaders, searchPath: string) {
453
458
  const threeUniforms = {};
454
459
 
455
- const uniformBlocks = Object.values(shaderStage.getUniformBlocks());
456
- uniformBlocks.forEach(uniforms =>
457
- {
458
- // TODO Seems struct uniforms (like in LightData) end up here as well, we should filter those out.
459
- if (!uniforms.empty())
460
- {
461
- for (let i = 0; i < uniforms.size(); ++i)
462
- {
460
+ const uniformBlocks = shaderStage.getUniformBlocks()
461
+ for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
462
+ // Seems struct uniforms (like in LightData) end up here as well, we should filter those out.
463
+ if (blockName === "LightData") continue;
464
+
465
+ if (!uniforms.empty()) {
466
+ for (let i = 0; i < uniforms.size(); ++i) {
463
467
  const variable = uniforms.get(i);
464
468
  const value = variable.getValue()?.getData();
465
469
  const name = variable.getVariable();
466
- if (debug) console.log("Adding uniform", { name, value, type: variable.getType().getName() });
467
- threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms,
468
- textureLoader, searchPath, flipY));
470
+ if (debug) console.log("Adding uniform", { path: variable.getPath(), name: name, value: value, type: variable.getType().getName() });
471
+ threeUniforms[name] = toThreeUniform(uniforms, variable.getType().getName(), value, name, loaders, searchPath);;
469
472
  }
470
473
  }
471
- });
474
+ }
472
475
 
473
476
  return threeUniforms;
474
477
  }