@needle-tools/materialx 1.0.1-next.19d0723 → 1.0.1-next.2ca9014

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,7 @@
1
1
  # Needle MaterialX
2
2
 
3
- Load and display MaterialX materials in Needle Engine
4
-
5
3
  ## Installation
6
- `npm i @needle-tools/materialx`
4
+ `npm i @needle-tools/materialx@stable`
7
5
 
8
6
  ## How to use
9
7
 
@@ -2,9 +2,5 @@
2
2
  import { TypeStore } from "@needle-tools/engine"
3
3
 
4
4
  // Import types
5
- import { MaterialXMaterial } from "../src/materialx.material.js";
6
- import { MaterialXUniformUpdate } from "../src/loader/loader.needle.js";
7
5
 
8
6
  // Register types
9
- TypeStore.add("MaterialXMaterial", MaterialXMaterial);
10
- TypeStore.add("MaterialXUniformUpdate", MaterialXUniformUpdate);
package/index.ts CHANGED
@@ -2,4 +2,4 @@ import { registerNeedleLoader } from "./src/loader/loader.needle.js";
2
2
 
3
3
  registerNeedleLoader();
4
4
 
5
- export { ready, getMaterialXEnvironment } from "./src/index.js";
5
+ export { initializeMaterialX, getMaterialXEnvironment } from "./src/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/materialx",
3
- "version": "1.0.1-next.19d0723",
3
+ "version": "1.0.1-next.2ca9014",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "exports": {
@@ -8,11 +8,7 @@
8
8
  "import": "./index.ts",
9
9
  "require": "./index.js"
10
10
  },
11
- "./package.json": "./package.json",
12
- "./codegen/register_types.ts": {
13
- "import": "./codegen/register_types.ts",
14
- "require": "./codegen/register_types.js"
15
- }
11
+ "./package.json": "./package.json"
16
12
  },
17
13
  "peerDependencies": {
18
14
  "@needle-tools/engine": "4.x",
@@ -5,8 +5,8 @@
5
5
 
6
6
  import { getParam, getWorldDirection } from '@needle-tools/engine';
7
7
  import * as THREE from 'three';
8
- import { debug, debugUpdate } from './utils';
9
- import { MaterialX } from './materialx.types';
8
+
9
+ const debug = getParam("debugmaterialx");
10
10
 
11
11
  const IMAGE_PROPERTY_SEPARATOR = "_";
12
12
  const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
@@ -20,7 +20,8 @@ const IMAGE_PATH_SEPARATOR = "/";
20
20
  * @param {Object} capabilities
21
21
  * @returns {THREE.Texture}
22
22
  */
23
- export function prepareEnvTexture(texture, capabilities) {
23
+ export function prepareEnvTexture(texture, capabilities)
24
+ {
24
25
  let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type);
25
26
  newTexture.wrapS = THREE.RepeatWrapping;
26
27
  newTexture.anisotropy = capabilities.getMaxAnisotropy();
@@ -38,12 +39,15 @@ export function prepareEnvTexture(texture, capabilities) {
38
39
  * @param {any} dimension
39
40
  * @returns {THREE.Uniform}
40
41
  */
41
- function fromVector(value, dimension) {
42
+ function fromVector(value, dimension)
43
+ {
42
44
  let outValue;
43
- if (value) {
45
+ if (value)
46
+ {
44
47
  outValue = [...value.data()];
45
48
  }
46
- else {
49
+ else
50
+ {
47
51
  outValue = [];
48
52
  for (let i = 0; i < dimension; ++i)
49
53
  outValue.push(0.0);
@@ -54,16 +58,23 @@ function fromVector(value, dimension) {
54
58
 
55
59
  /**
56
60
  * Get Three uniform from MaterialX matrix
61
+ * @param {mx.matrix} matrix
62
+ * @param {mx.matrix.size} dimension
57
63
  */
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) {
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
+ {
63
73
  vec.push(matrix.getItem(i, k));
64
74
  }
65
75
  }
66
- } else {
76
+ } else
77
+ {
67
78
  for (let i = 0; i < dimension; ++i)
68
79
  vec.push(0.0);
69
80
  }
@@ -71,99 +82,125 @@ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"
71
82
  return vec;
72
83
  }
73
84
 
74
-
75
- export type Loaders = {
76
- getTexture: (path: string) => THREE.Texture;
77
- }
78
-
79
85
  /**
80
86
  * Get Three uniform from MaterialX value
81
87
  * @param {mx.Uniform.type} type
82
88
  * @param {mx.Uniform.value} value
83
89
  * @param {mx.Uniform.name} name
84
90
  * @param {mx.Uniforms} uniforms
85
- * @param {Loaders} loaders
91
+ * @param {THREE.textureLoader} textureLoader
86
92
  * @param {string} searchPath
87
93
  * @param {boolean} flipY
88
94
  */
89
- function toThreeUniform(type: string, value: any, name: string, uniforms: any, loaders: Loaders, searchPath, flipY: boolean) {
90
-
91
- switch (type) {
95
+ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, flipY)
96
+ {
97
+ let outValue = null;
98
+ switch (type)
99
+ {
92
100
  case 'float':
93
101
  case 'integer':
94
102
  case 'boolean':
95
- return value;
103
+ outValue = value;
96
104
  break;
97
105
  case 'vector2':
98
- return fromVector(value, 2);
106
+ outValue = fromVector(value, 2);
99
107
  break;
100
108
  case 'vector3':
101
109
  case 'color3':
102
- return fromVector(value, 3);
110
+ outValue = fromVector(value, 3);
111
+ break;
103
112
  case 'vector4':
104
113
  case 'color4':
105
- return fromVector(value, 4);
114
+ outValue = fromVector(value, 4);
115
+ break;
106
116
  case 'matrix33':
107
- return fromMatrix(value, 9);
117
+ outValue = fromMatrix(value, 9);
118
+ break;
108
119
  case 'matrix44':
109
- return fromMatrix(value, 16);
120
+ outValue = fromMatrix(value, 16);
121
+ break;
110
122
  case 'filename':
111
- if (value) {
123
+ if (value)
124
+ {
112
125
  // Cache / reuse texture to avoid reload overhead.
113
126
  // Note: that data blobs and embedded data textures are not cached as they are transient data.
114
127
  let checkCache = false;
115
128
  let texturePath = searchPath + IMAGE_PATH_SEPARATOR + value;
116
- if (value.startsWith('blob:')) {
129
+ if (value.startsWith('blob:'))
130
+ {
117
131
  texturePath = value;
118
132
  if (debug) console.log('Load blob URL:', texturePath);
119
133
  checkCache = false;
120
134
  }
121
- else if (value.startsWith('http')) {
135
+ else if (value.startsWith('http'))
136
+ {
122
137
  texturePath = value;
123
138
  if (debug) console.log('Load HTTP URL:', texturePath);
124
139
  }
125
- else if (value.startsWith('data:')) {
140
+ else if (value.startsWith('data:'))
141
+ {
126
142
  texturePath = value;
127
143
  checkCache = false;
128
144
  if (debug) console.log('Load data URL:', texturePath);
129
145
  }
130
146
  const cachedTexture = checkCache && THREE.Cache.get(texturePath);
131
- if (cachedTexture) {
132
- if (debug) console.log('Use cached texture: ', texturePath, cachedTexture);
133
- return cachedTexture;
147
+ if (cachedTexture)
148
+ {
149
+ // Get texture from cache
150
+ outValue = cachedTexture;
151
+ if (debug) console.log('Use cached texture: ', texturePath, outValue);
134
152
  }
135
- else {
136
- const texture = loaders.getTexture(texturePath);
137
- if (checkCache) THREE.Cache.add(texturePath, texture);
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
+
138
170
  // Set address & filtering mode
139
- if (texture) setTextureParameters(texture, name, uniforms, flipY);
140
- return texture;
171
+ if (outValue)
172
+ setTextureParameters(outValue, name, uniforms, flipY);
141
173
  }
142
174
  }
143
175
  break;
144
176
  case 'samplerCube':
145
177
  case 'string':
146
- return null;
178
+ break;
147
179
  default:
148
180
  const key = type + ':' + name;
149
- if (!valueTypeWarningMap.has(key)) {
181
+ if (!valueTypeWarningMap.has(key))
182
+ {
150
183
  valueTypeWarningMap.set(key, true);
151
184
  console.warn('MaterialX: Unsupported uniform type: ' + type + ' for uniform: ' + name, value);
152
185
  }
153
- return null;
186
+ outValue = null;
154
187
  }
188
+
189
+ return outValue;
155
190
  }
156
191
 
157
- const valueTypeWarningMap = new Map<string, boolean>();
192
+ const valueTypeWarningMap = new Map();
158
193
 
159
194
  /**
160
195
  * Get Three wrapping mode
161
196
  * @param {mx.TextureFilter.wrap} mode
162
197
  * @returns {THREE.Wrapping}
163
198
  */
164
- function getWrapping(mode) {
199
+ function getWrapping(mode)
200
+ {
165
201
  let wrap;
166
- switch (mode) {
202
+ switch (mode)
203
+ {
167
204
  case 1:
168
205
  wrap = THREE.ClampToEdgeWrapping;
169
206
  break;
@@ -185,9 +222,12 @@ function getWrapping(mode) {
185
222
  * @param {mx.TextureFilter.minFilter} type
186
223
  * @param {mx.TextureFilter.generateMipmaps} generateMipmaps
187
224
  */
188
- function getMinFilter(type, generateMipmaps) {
189
- let filterType: THREE.TextureFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
190
- if (type === 0) {
225
+ function getMinFilter(type, generateMipmaps)
226
+ {
227
+ /** @type {THREE.TextureFilter} */
228
+ let filterType = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
229
+ if (type === 0)
230
+ {
191
231
  filterType = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
192
232
  }
193
233
  return filterType;
@@ -200,22 +240,25 @@ function getMinFilter(type, generateMipmaps) {
200
240
  * @param {mx.Uniforms} uniforms
201
241
  * @param {mx.TextureFilter.generateMipmaps} generateMipmaps
202
242
  */
203
- function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true) {
243
+ function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
244
+ {
204
245
  const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
205
246
  const base = name.substring(0, idx) || name;
206
247
 
207
- // texture.generateMipmaps = generateMipmaps;
208
- // texture.wrapS = THREE.RepeatWrapping;
209
- // texture.wrapT = THREE.RepeatWrapping;
210
- // texture.magFilter = THREE.LinearFilter;
211
- // texture.flipY = flipY;
248
+ texture.generateMipmaps = generateMipmaps;
249
+ texture.wrapS = THREE.RepeatWrapping;
250
+ texture.wrapT = THREE.RepeatWrapping;
251
+ texture.magFilter = THREE.LinearFilter;
252
+ texture.flipY = flipY;
212
253
 
213
- if (uniforms.find(base + UADDRESS_MODE_SUFFIX)) {
254
+ if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
255
+ {
214
256
  const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData();
215
257
  texture.wrapS = getWrapping(uaddressmode);
216
258
  }
217
259
 
218
- if (uniforms.find(base + VADDRESS_MODE_SUFFIX)) {
260
+ if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
261
+ {
219
262
  const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData();
220
263
  texture.wrapT = getWrapping(vaddressmode);
221
264
  }
@@ -227,7 +270,8 @@ function setTextureParameters(texture, name, uniforms, flipY = true, generateMip
227
270
  /**
228
271
  * Return the global light rotation matrix
229
272
  */
230
- export function getLightRotation() {
273
+ export function getLightRotation()
274
+ {
231
275
  return new THREE.Matrix4().makeRotationY(Math.PI / 2);
232
276
  }
233
277
 
@@ -236,27 +280,36 @@ export function getLightRotation() {
236
280
  * @param {mx.Document} doc
237
281
  * @returns {Array.<mx.Node>}
238
282
  */
239
- export function findLights(doc: MaterialX.Document) {
240
- let lights = new Array<any>;
241
- for (let node of doc.getNodes()) {
283
+ export function findLights(doc)
284
+ {
285
+ let lights = [];
286
+ for (let node of doc.getNodes())
287
+ {
242
288
  if (node.getType() === "lightshader")
243
289
  lights.push(node);
244
290
  }
245
291
  return lights;
246
292
  }
247
293
 
248
- let lightTypesBound = {};
249
-
250
294
  /**
251
295
  * Register lights in shader generation context
252
- * @param {MaterialX.MODULE} mx MaterialX Module
296
+ * @param {Object} mx MaterialX Module
297
+ * @param {Array.<mx.Node>} lights Light nodes
253
298
  * @param {mx.GenContext} genContext Shader generation context
299
+ * @returns {Array.<mx.Node>}
254
300
  */
255
- export async function registerLights(mx: MaterialX.MODULE, genContext: any): Promise<void> {
256
- lightTypesBound = {};
257
- const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
301
+ export async function registerLights(mx, lights, genContext)
302
+ {
258
303
  mx.HwShaderGenerator.unbindLightShaders(genContext);
304
+ // TODO Remove, not sure why we need that – something resets the value inbetween calls to registerLights
305
+ genContext.getOptions().hwMaxActiveLightSources = 4;
306
+
307
+ const lightTypesBound = {};
308
+ const lightData = [];
259
309
  let lightId = 1;
310
+ let lightCount = 0;
311
+ const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
312
+
260
313
  // All light types so that we have NodeDefs for them
261
314
  const defaultLightRigXml = `<?xml version="1.0"?>
262
315
  <materialx version="1.39">
@@ -274,7 +327,7 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
274
327
 
275
328
  // Load default light rig XML to ensure we have all light types available
276
329
  const lightRigDoc = mx.createDocument();
277
- await mx.readFromXmlString(lightRigDoc, defaultLightRigXml, "");
330
+ await mx.readFromXmlString(lightRigDoc, defaultLightRigXml);
278
331
  const document = mx.createDocument();
279
332
  const stdlib = mx.loadStandardLibraries(genContext);
280
333
  document.setDataLibrary(stdlib);
@@ -287,14 +340,16 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
287
340
 
288
341
  // Register types only – we get these from the default light rig XML above
289
342
  // This is needed to ensure that the light shaders are bound for each light type
290
- for (let light of defaultLights) {
343
+ for (let light of defaultLights)
344
+ {
291
345
  const lightDef = light.getNodeDef();
292
346
  if (debug) console.log("Default light node definition", lightDef);
293
347
  if (!lightDef) continue;
294
348
 
295
349
  const lightName = lightDef.getName();
296
350
  if (debug) console.log("Registering default light", { lightName, lightDef });
297
- if (!lightTypesBound[lightName]) {
351
+ if (!lightTypesBound[lightName])
352
+ {
298
353
  // TODO check if we need to bind light shader for each three.js light instead of once per type
299
354
  if (debug) console.log("Bind light shader for node", { lightName, lightId, lightDef });
300
355
  lightTypesBound[lightName] = lightId;
@@ -303,40 +358,52 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
303
358
  }
304
359
 
305
360
  if (debug) console.log("Light types bound in MaterialX context", lightTypesBound);
306
- }
307
361
 
308
- // Converts Three.js light type to MaterialX node name
309
- function threeLightTypeToMaterialXNodeName(threeLightType) {
310
- switch (threeLightType) {
311
- case 'PointLight':
312
- return 'ND_point_light';
313
- case 'DirectionalLight':
314
- return 'ND_directional_light';
315
- case 'SpotLight':
316
- return 'ND_spot_light';
317
- default:
318
- console.warn('MaterialX: Unsupported light type: ' + threeLightType);
319
- return 'ND_point_light'; // Default to point light
362
+ // MaterialX light nodes
363
+ for (let light of lights)
364
+ {
365
+ // Skip if light does not have a node definition
366
+ if (!("getNodeDef" in light)) continue;
367
+
368
+ let nodeDef = light.getNodeDef();
369
+ let nodeName = nodeDef.getName();
370
+ if (!lightTypesBound[nodeName])
371
+ {
372
+ if (debug) console.log("bind light shader for node", { nodeName, lightId, nodeDef });
373
+ lightTypesBound[nodeName] = lightId;
374
+ mx.HwShaderGenerator.bindLightShader(nodeDef, lightId++, genContext);
375
+ }
376
+
377
+ const lightDirection = light.getValueElement("direction").getValue().getData().data();
378
+ const lightColor = light.getValueElement("color").getValue().getData().data();
379
+ const lightIntensity = light.getValueElement("intensity").getValue().getData();
380
+
381
+ let rotatedLightDirection = new THREE.Vector3(...lightDirection)
382
+ rotatedLightDirection.transformDirection(getLightRotation())
383
+
384
+ lightData.push({
385
+ type: lightTypesBound[nodeName],
386
+ direction: rotatedLightDirection,
387
+ color: new THREE.Vector3(...lightColor),
388
+ intensity: lightIntensity,
389
+ });
320
390
  }
321
- };
322
-
323
- type LightData = {
324
- type: number, // Light type ID
325
- position: THREE.Vector3, // Position in world space
326
- direction: THREE.Vector3, // Direction in world space
327
- color: THREE.Color, // Color of the light
328
- intensity: number, // Intensity of the light
329
- decay_rate: number, // Decay rate for point and spot lights
330
- inner_angle: number, // Inner angle for spot lights
331
- outer_angle: number, // Outer angle for spot lights
332
- }
333
391
 
334
- /**
335
- * Update light data for shader uniforms
336
- */
337
- export function getLightData(lights: any, genContext: any): { lightData: LightData[], lightCount: number } {
338
- const lightData = new Array();
339
- const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
392
+ const threeLightTypeToMaterialXNodeName = (threeLightType) => {
393
+ switch (threeLightType) {
394
+ case 'PointLight':
395
+ return 'ND_point_light';
396
+ case 'DirectionalLight':
397
+ return 'ND_directional_light';
398
+ case 'SpotLight':
399
+ return 'ND_spot_light';
400
+ default:
401
+ console.warn('MaterialX: Unsupported light type: ' + threeLightType);
402
+ return 'ND_point_light'; // Default to point light
403
+ }
404
+ };
405
+
406
+ if (debug) console.log("Registering lights in MaterialX context", lights, lightData);
340
407
 
341
408
  // Three.js lights
342
409
  for (let light of lights) {
@@ -348,82 +415,76 @@ export function getLightData(lights: any, genContext: any): { lightData: LightDa
348
415
  const lightDefinitionName = threeLightTypeToMaterialXNodeName(light.type);
349
416
 
350
417
  if (!lightTypesBound[lightDefinitionName])
351
- console.error("MaterialX: Light type not registered in context. Make sure to register light types before using them.", lightDefinitionName);
418
+ {
419
+ lightTypesBound[lightDefinitionName] = lightId;
420
+ const nodeDef = null;
421
+ mx.HwShaderGenerator.bindLightShader(nodeDef, lightId++, genContext);
422
+ }
352
423
 
353
424
  const wp = light.getWorldPosition(new THREE.Vector3());
354
- const wd = getWorldDirection(light, new THREE.Vector3(0, 0, -1));
355
-
356
- // Shader math from the generated MaterialX shader:
357
- // float low = min(light.inner_angle, light.outer_angle);
358
- // float high = light.inner_angle;
359
- // float cosDir = dot(result.direction, -light.direction);
360
- // float spotAttenuation = smoothstep(low, high, cosDir);
361
-
362
- const outerAngleRad = light.angle;
363
- const innerAngleRad = outerAngleRad * (1 - light.penumbra);
364
- const inner_angle = Math.cos(innerAngleRad);
365
- const outer_angle = Math.cos(outerAngleRad);
366
-
425
+ const wd = getWorldDirection(light, new THREE.Vector3(0,0,-1));
367
426
  lightData.push({
368
427
  type: lightTypesBound[lightDefinitionName],
369
428
  position: wp.clone(),
370
429
  direction: wd.clone(),
371
- color: new THREE.Color().fromArray(light.color.toArray()),
372
- // Luminous efficacy for converting radiant power in watts (W) to luminous flux in lumens (lm) at a wavelength of 555 nm.
373
- // 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.
374
- intensity: light.intensity * (light.isPointLight ? 683.0 / 3.1415 : light.isSpotLight ? 683.0 / 3.1415 : 1.0),
375
- decay_rate: 2.0,
376
- // Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
377
- inner_angle: inner_angle,
378
- outer_angle: outer_angle,
430
+ color: new THREE.Vector3().fromArray(light.color.toArray()),
431
+ intensity: light.intensity, // Scale intensity for spot lights
432
+ decay_rate: 2.0, // physically-based default decay rate
433
+ inner_angle: 1.0,
434
+ outer_angle: 2.0,
379
435
  });
380
436
  }
381
437
 
382
438
  // Count the number of lights that are not empty
383
- const lightCount = lightData.length;
439
+ lightCount = lightData.length;
384
440
 
385
441
  // If we don't have enough entries in lightData, fill with empty lights
386
- while (lightData.length < maxLightCount) {
442
+ if (lightData.length < maxLightCount)
443
+ {
387
444
  const emptyLight = {
388
445
  type: 0, // Default light type
389
446
  position: new THREE.Vector3(0, 0, 0),
390
447
  direction: new THREE.Vector3(0, 0, -1),
391
- color: new THREE.Color(0, 0, 0),
392
- intensity: 0.0,
393
- decay_rate: 2.0,
394
- inner_angle: 0.0,
395
- outer_angle: 0.0,
448
+ color: new THREE.Vector3(0, 0, 0),
449
+ intensity: 0,
450
+ decay_rate: 2,
451
+ inner_angle: 0,
452
+ outer_angle: 0,
396
453
  };
397
- lightData.push(emptyLight);
454
+ while (lightData.length < maxLightCount) {
455
+ lightData.push(emptyLight);
456
+ }
398
457
  }
399
458
 
400
- if (debugUpdate) console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
459
+ if (debug) console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
401
460
 
402
461
  return { lightData, lightCount };
403
462
  }
404
463
 
405
464
  /**
406
465
  * Get uniform values for a shader
466
+ * @param {mx.shaderStage} shaderStage
467
+ * @param {THREE.TextureLoader} textureLoader
407
468
  */
408
- export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Loaders, searchPath: string, flipY: boolean) {
409
- const threeUniforms = {};
410
-
411
- const uniformBlocks = shaderStage.getUniformBlocks()
412
- for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
413
- // Seems struct uniforms (like in LightData) end up here as well, we should filter those out.
414
- if (blockName === "LightData") continue;
415
-
416
- if (!uniforms.empty()) {
417
- for (let i = 0; i < uniforms.size(); ++i) {
469
+ export function getUniformValues(shaderStage, textureLoader, searchPath, flipY)
470
+ {
471
+ let threeUniforms = {};
472
+
473
+ const uniformBlocks = Object.values(shaderStage.getUniformBlocks());
474
+ uniformBlocks.forEach(uniforms =>
475
+ {
476
+ if (!uniforms.empty())
477
+ {
478
+ for (let i = 0; i < uniforms.size(); ++i)
479
+ {
418
480
  const variable = uniforms.get(i);
419
481
  const value = variable.getValue()?.getData();
420
482
  const name = variable.getVariable();
421
- if (debug) console.log("Adding uniform", { path: variable.getPath(), name, value, type: variable.getType().getName() });
422
483
  threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms,
423
- loaders, searchPath, flipY));
484
+ textureLoader, searchPath, flipY));
424
485
  }
425
486
  }
426
- }
487
+ });
427
488
 
428
489
  return threeUniforms;
429
490
  }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ready, state } from "./materialx.js";
1
+ import { initializeMaterialX, state } from "./materialx.js";
2
2
 
3
3
  const getMaterialXEnvironment = () => state.materialXEnvironment;
4
4
 
5
- export { ready, getMaterialXEnvironment };
5
+ export { initializeMaterialX, getMaterialXEnvironment };