@needle-tools/materialx 1.1.1-next.714bc32 → 1.1.1-next.8e8afe1

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.
@@ -4,7 +4,6 @@
4
4
  //
5
5
  import * as THREE from 'three';
6
6
  import { debug, debugUpdate } from './utils.js';
7
- import { MaterialX } from './materialx.types.js';
8
7
 
9
8
  const IMAGE_PROPERTY_SEPARATOR = "_";
10
9
  const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
@@ -13,13 +12,13 @@ const FILTER_TYPE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "filtertype";
13
12
  const IMAGE_PATH_SEPARATOR = "/";
14
13
 
15
14
  /**
16
- * Initialized the environment texture as MaterialX expects it
15
+ * Initializes the environment texture as MaterialX expects it
17
16
  * @param {THREE.Texture} texture
18
17
  * @param {Object} capabilities
19
18
  * @returns {THREE.Texture}
20
19
  */
21
20
  export function prepareEnvTexture(texture, capabilities) {
22
- let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type);
21
+ let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, /** @type {any} */ (texture.format), texture.type);
23
22
  newTexture.wrapS = THREE.RepeatWrapping;
24
23
  newTexture.anisotropy = capabilities.getMaxAnisotropy();
25
24
  newTexture.minFilter = THREE.LinearMipmapLinearFilter;
@@ -34,7 +33,7 @@ export function prepareEnvTexture(texture, capabilities) {
34
33
  * Get Three uniform from MaterialX vector
35
34
  * @param {any} value
36
35
  * @param {any} dimension
37
- * @returns {THREE.Uniform}
36
+ * @returns {Array<number>}
38
37
  */
39
38
  function fromVector(value, dimension) {
40
39
  let outValue;
@@ -52,8 +51,11 @@ function fromVector(value, dimension) {
52
51
 
53
52
  /**
54
53
  * Get Three uniform from MaterialX matrix
54
+ * @param {any} matrix
55
+ * @param {number} dimension
56
+ * @returns {Array<number>}
55
57
  */
56
- function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"]) {
58
+ function fromMatrix(matrix, dimension) {
57
59
  const vec = new Array(dimension);
58
60
  if (matrix) {
59
61
  for (let i = 0; i < matrix.numRows(); ++i) {
@@ -69,19 +71,11 @@ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"
69
71
  return vec;
70
72
  }
71
73
 
72
-
73
- export type Callbacks = {
74
- /**
75
- * Cache key for the loaders, used to identify and reuse textures
76
- */
77
- readonly cacheKey?: string;
78
- /**
79
- * Get a texture by path
80
- * @param {string} path - The path to the texture
81
- * @return {Promise<THREE.Texture>} - A promise that resolves to the texture
82
- */
83
- readonly getTexture: (path: string) => Promise<THREE.Texture | null | void>;
84
- }
74
+ /**
75
+ * @typedef {Object} Callbacks
76
+ * @property {string} [cacheKey] - Cache key for the loaders, used to identify and reuse textures
77
+ * @property {(path: string) => Promise<THREE.Texture | null | void>} getTexture - Get a texture by path
78
+ */
85
79
 
86
80
  const defaultTexture = new THREE.Texture();
87
81
  defaultTexture.needsUpdate = true;
@@ -94,21 +88,28 @@ defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAA
94
88
  // defaultTexture.magFilter = THREE.NearestFilter;
95
89
  // defaultTexture.repeat = new THREE.Vector2(100, 100);
96
90
 
97
-
98
91
  const defaultNormalTexture = new THREE.Texture();
99
92
  defaultNormalTexture.needsUpdate = true;
100
93
  defaultNormalTexture.image = new Image();
101
94
  defaultNormalTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=";
102
95
 
103
-
104
- function tryGetFromCache(key: string): any {
96
+ /**
97
+ * @param {string} key
98
+ * @returns {any}
99
+ */
100
+ function tryGetFromCache(key) {
105
101
  const wasEnabled = THREE.Cache.enabled;
106
102
  THREE.Cache.enabled = true;
107
103
  const value = THREE.Cache.get(key);
108
104
  THREE.Cache.enabled = wasEnabled;
109
105
  return value;
110
106
  }
111
- function addToCache(key: string, value: any): void {
107
+
108
+ /**
109
+ * @param {string} key
110
+ * @param {any} value
111
+ */
112
+ function addToCache(key, value) {
112
113
  const wasEnabled = THREE.Cache.enabled;
113
114
  THREE.Cache.enabled = true;
114
115
  THREE.Cache.add(key, value);
@@ -118,10 +119,17 @@ function addToCache(key: string, value: any): void {
118
119
 
119
120
  /**
120
121
  * Get Three uniform from MaterialX value
122
+ * @param {any} uniforms
123
+ * @param {string} type
124
+ * @param {any} value
125
+ * @param {string} name
126
+ * @param {Callbacks} loaders
127
+ * @param {string} searchPath
128
+ * @returns {THREE.Uniform}
121
129
  */
122
- function toThreeUniform(uniforms: any, type: string, value: any, name: string, loaders: Callbacks, searchPath: string): THREE.Uniform {
130
+ function toThreeUniform(uniforms, type, value, name, loaders, searchPath) {
123
131
 
124
- const uniform = new THREE.Uniform<any>(null);
132
+ const uniform = new THREE.Uniform(/** @type {any} */ (null));
125
133
 
126
134
  switch (type) {
127
135
  case 'float':
@@ -130,21 +138,21 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
130
138
  uniform.value = value;
131
139
  break;
132
140
  case 'vector2':
133
- uniform.value = fromVector(value, 2);
141
+ uniform.value = /** @type {any} */ (fromVector(value, 2));
134
142
  break;
135
143
  case 'vector3':
136
144
  case 'color3':
137
- uniform.value = fromVector(value, 3);
145
+ uniform.value = /** @type {any} */ (fromVector(value, 3));
138
146
  break;
139
147
  case 'vector4':
140
148
  case 'color4':
141
- uniform.value = fromVector(value, 4);
149
+ uniform.value = /** @type {any} */ (fromVector(value, 4));
142
150
  break;
143
151
  case 'matrix33':
144
- uniform.value = fromMatrix(value, 9);
152
+ uniform.value = /** @type {any} */ (fromMatrix(value, 9));
145
153
  break;
146
154
  case 'matrix44':
147
- uniform.value = fromMatrix(value, 16);
155
+ uniform.value = /** @type {any} */ (fromMatrix(value, 16));
148
156
  break;
149
157
  case 'filename':
150
158
  if (value) {
@@ -182,8 +190,8 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
182
190
  else {
183
191
  if (debug) console.log('[MaterialX] Load texture:', texturePath);
184
192
 
185
- if (name.toLowerCase().includes("normal")) uniform.value = defaultNormalTexture;
186
- else uniform.value = defaultTexture;
193
+ if (name.toLowerCase().includes("normal")) uniform.value = /** @type {any} */ (defaultNormalTexture);
194
+ else uniform.value = /** @type {any} */ (defaultTexture);
187
195
  const defaultValue = uniform.value;
188
196
  // Save the loading promise in the cache
189
197
  const promise = loaders.getTexture(texturePath)
@@ -203,7 +211,7 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
203
211
  if (checkCache) addToCache(cacheKey, promise);
204
212
 
205
213
  promise?.then(res => {
206
- if (res) uniform.value = res;
214
+ if (res) uniform.value = /** @type {any} */ (res);
207
215
  else console.warn(`[MaterialX] Failed to load texture ${name} '${texturePath}'`);
208
216
  });
209
217
  }
@@ -224,12 +232,15 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
224
232
  return uniform;
225
233
  }
226
234
 
227
- const valueTypeWarningMap = new Map<string, boolean>();
235
+ /** @type {Map<string, boolean>} */
236
+ const valueTypeWarningMap = new Map();
228
237
 
229
238
  /**
230
239
  * Get Three wrapping mode
240
+ * @param {number} mode
241
+ * @returns {THREE.Wrapping}
231
242
  */
232
- function getWrapping(mode: number): THREE.Wrapping {
243
+ function getWrapping(mode) {
233
244
  let wrap;
234
245
  switch (mode) {
235
246
  case 1:
@@ -248,11 +259,14 @@ function getWrapping(mode: number): THREE.Wrapping {
248
259
  return wrap;
249
260
  }
250
261
 
251
-
252
262
  /**
253
263
  * Set Three texture parameters
264
+ * @param {THREE.Texture} texture
265
+ * @param {string} name
266
+ * @param {any} uniforms
267
+ * @param {boolean} [generateMipmaps=true]
254
268
  */
255
- function setTextureParameters(texture: THREE.Texture, name: string, uniforms: any, generateMipmaps = true) {
269
+ function setTextureParameters(texture, name, uniforms, generateMipmaps = true) {
256
270
  const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
257
271
  const base = name.substring(0, idx) || name;
258
272
 
@@ -267,15 +281,16 @@ function setTextureParameters(texture: THREE.Texture, name: string, uniforms: an
267
281
  }
268
282
 
269
283
  const mxFilterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
270
- let minFilter: THREE.TextureFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
284
+ let minFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
271
285
  if (mxFilterType === 0) {
272
- minFilter = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
286
+ minFilter = /** @type {any} */ (generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter);
273
287
  }
274
288
  texture.minFilter = minFilter;
275
289
  }
276
290
 
277
291
  /**
278
292
  * Return the global light rotation matrix
293
+ * @returns {THREE.Matrix4}
279
294
  */
280
295
  export function getLightRotation() {
281
296
  return new THREE.Matrix4().makeRotationY(Math.PI / 2);
@@ -283,11 +298,11 @@ export function getLightRotation() {
283
298
 
284
299
  /**
285
300
  * Returns all lights nodes in a MaterialX document
286
- * @param {mx.Document} doc
287
- * @returns {Array.<mx.Node>}
301
+ * @param {any} doc
302
+ * @returns {Array<any>}
288
303
  */
289
- export function findLights(doc: MaterialX.Document) {
290
- let lights = new Array<any>;
304
+ export function findLights(doc) {
305
+ let lights = new Array();
291
306
  for (let node of doc.getNodes()) {
292
307
  if (node.getType() === "lightshader")
293
308
  lights.push(node);
@@ -295,14 +310,16 @@ export function findLights(doc: MaterialX.Document) {
295
310
  return lights;
296
311
  }
297
312
 
313
+ /** @type {Object<string, number>} */
298
314
  let lightTypesBound = {};
299
315
 
300
316
  /**
301
317
  * Register lights in shader generation context
302
- * @param {MaterialX.MODULE} mx MaterialX Module
303
- * @param {mx.GenContext} genContext Shader generation context
318
+ * @param {any} mx - MaterialX Module
319
+ * @param {any} genContext - Shader generation context
320
+ * @returns {Promise<void>}
304
321
  */
305
- export async function registerLights(mx: MaterialX.MODULE, genContext: any): Promise<void> {
322
+ export async function registerLights(mx, genContext) {
306
323
  lightTypesBound = {};
307
324
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
308
325
  mx.HwShaderGenerator.unbindLightShaders(genContext);
@@ -355,7 +372,11 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
355
372
  if (debug) console.log("Light types bound in MaterialX context", lightTypesBound);
356
373
  }
357
374
 
358
- // Converts Three.js light type to MaterialX node name
375
+ /**
376
+ * Converts Three.js light type to MaterialX node name
377
+ * @param {string} threeLightType
378
+ * @returns {string}
379
+ */
359
380
  function threeLightTypeToMaterialXNodeName(threeLightType) {
360
381
  switch (threeLightType) {
361
382
  case 'PointLight':
@@ -368,23 +389,27 @@ function threeLightTypeToMaterialXNodeName(threeLightType) {
368
389
  console.warn('MaterialX: Unsupported light type: ' + threeLightType);
369
390
  return 'ND_point_light'; // Default to point light
370
391
  }
371
- };
372
-
373
- export type LightData = {
374
- type: number, // Light type ID
375
- position: THREE.Vector3, // Position in world space
376
- direction: THREE.Vector3, // Direction in world space
377
- color: THREE.Color, // Color of the light
378
- intensity: number, // Intensity of the light
379
- decay_rate: number, // Decay rate for point and spot lights
380
- inner_angle: number, // Inner angle for spot lights
381
- outer_angle: number, // Outer angle for spot lights
382
392
  }
383
393
 
394
+ /**
395
+ * @typedef {Object} LightData
396
+ * @property {number} type - Light type ID
397
+ * @property {THREE.Vector3} position - Position in world space
398
+ * @property {THREE.Vector3} direction - Direction in world space
399
+ * @property {THREE.Color} color - Color of the light
400
+ * @property {number} intensity - Intensity of the light
401
+ * @property {number} decay_rate - Decay rate for point and spot lights
402
+ * @property {number} inner_angle - Inner angle for spot lights
403
+ * @property {number} outer_angle - Outer angle for spot lights
404
+ */
405
+
384
406
  /**
385
407
  * Update light data for shader uniforms
408
+ * @param {Array<THREE.Light>} lights
409
+ * @param {any} genContext
410
+ * @returns {{ lightData: LightData[], lightCount: number }}
386
411
  */
387
- export function getLightData(lights: Array<THREE.Light>, genContext: any): { lightData: LightData[], lightCount: number } {
412
+ export function getLightData(lights, genContext) {
388
413
  const lightData = new Array();
389
414
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
390
415
 
@@ -410,8 +435,8 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
410
435
  // float cosDir = dot(result.direction, -light.direction);
411
436
  // float spotAttenuation = smoothstep(low, high, cosDir);
412
437
 
413
- const outerAngleRad = (light as THREE.SpotLight).angle;
414
- const innerAngleRad = outerAngleRad * (1 - (light as THREE.SpotLight).penumbra);
438
+ const outerAngleRad = /** @type {THREE.SpotLight} */ (light).angle;
439
+ const innerAngleRad = outerAngleRad * (1 - /** @type {THREE.SpotLight} */ (light).penumbra);
415
440
  const inner_angle = Math.cos(innerAngleRad);
416
441
  const outer_angle = Math.cos(outerAngleRad);
417
442
 
@@ -422,7 +447,7 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
422
447
  color: new THREE.Color().fromArray(light.color.toArray()),
423
448
  // Luminous efficacy for converting radiant power in watts (W) to luminous flux in lumens (lm) at a wavelength of 555 nm.
424
449
  // 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.
425
- intensity: light.intensity * ((light as THREE.PointLight).isPointLight ? 683.0 / 3.1415 : (light as THREE.SpotLight).isSpotLight ? 683.0 / 3.1415 : 1.0),
450
+ intensity: light.intensity * (/** @type {THREE.PointLight} */ (light).isPointLight ? 683.0 / 3.1415 : /** @type {THREE.SpotLight} */ (light).isSpotLight ? 683.0 / 3.1415 : 1.0),
426
451
  decay_rate: 2.0,
427
452
  // Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
428
453
  inner_angle: inner_angle,
@@ -455,8 +480,13 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
455
480
 
456
481
  /**
457
482
  * Get uniform values for a shader
483
+ * @param {any} shaderStage
484
+ * @param {Callbacks} loaders
485
+ * @param {string} searchPath
486
+ * @returns {Object<string, THREE.Uniform>}
458
487
  */
459
- export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Callbacks, searchPath: string) {
488
+ export function getUniformValues(shaderStage, loaders, searchPath) {
489
+ /** @type {Object<string, THREE.Uniform>} */
460
490
  const threeUniforms = {};
461
491
 
462
492
  const uniformBlocks = shaderStage.getUniformBlocks()
@@ -479,7 +509,11 @@ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Ca
479
509
  return threeUniforms;
480
510
  }
481
511
 
482
- export function generateMaterialPropertiesForUniforms(material: THREE.ShaderMaterial, shaderStage: MaterialX.ShaderStage) {
512
+ /**
513
+ * @param {THREE.ShaderMaterial} material
514
+ * @param {any} shaderStage
515
+ */
516
+ export function generateMaterialPropertiesForUniforms(material, shaderStage) {
483
517
 
484
518
  const uniformBlocks = shaderStage.getUniformBlocks()
485
519
  for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
@@ -1,30 +1,27 @@
1
- import type { MaterialX as MX } from "./materialx.types.js";
2
1
  import MaterialX from "../bin/JsMaterialXGenShader.js";
3
2
  import { debug } from "./utils.js";
4
3
  import { renderPMREMToEquirect } from "./utils.texture.js";
5
4
  import { Light, Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, PMREMGenerator, Scene, Texture, WebGLRenderer } from "three";
6
- import { registerLights, getLightData, LightData } from "./materialx.helper.js";
7
- import type { MaterialXMaterial } from "./materialx.material.js";
8
-
9
- export type MaterialXContext = {
10
- getTime?(): number,
11
- getFrame?(): number,
12
- }
13
-
5
+ import { registerLights, getLightData } from "./materialx.helper.js";
14
6
 
15
7
  export const state = new class {
16
- materialXModule: MX.MODULE | null = null;
17
- materialXGenerator: any = null;
18
- materialXGenContext: any = null;
19
- materialXStdLib: any = null;
20
- materialXInitPromise: Promise<void> | null = null;
8
+ /** @type {import("./materialx.types.js").MaterialX.MODULE | null} */
9
+ materialXModule = null;
10
+ /** @type {any} */
11
+ materialXGenerator = null;
12
+ /** @type {any} */
13
+ materialXGenContext = null;
14
+ /** @type {any} */
15
+ materialXStdLib = null;
16
+ /** @type {Promise<void> | null} */
17
+ materialXInitPromise = null;
21
18
  }
22
19
 
23
-
24
20
  /**
25
21
  * Wait for the MaterialX WASM module to be ready.
22
+ * @returns {Promise<void>}
26
23
  */
27
- export async function ready(): Promise<void> {
24
+ export async function ready() {
28
25
  if (state.materialXInitPromise) {
29
26
  return state.materialXInitPromise;
30
27
  }
@@ -33,18 +30,19 @@ export async function ready(): Promise<void> {
33
30
  if (debug) console.log("[MaterialX] Initializing WASM module...");
34
31
  try {
35
32
 
36
- const urls: Array<string> = await Promise.all([
33
+ /** @type {Array<string>} */
34
+ const urls = await Promise.all([
37
35
  /** @ts-ignore */
38
- import(`../bin/JsMaterialXCore.wasm?url`).then(m => m.default || m),
36
+ import( /* @vite-ignore */ `../bin/JsMaterialXCore.wasm?url`).then(m => m.default || m),
39
37
  /** @ts-ignore */
40
- import(`../bin/JsMaterialXGenShader.wasm?url`).then(m => m.default || m),
38
+ import( /* @vite-ignore */ `../bin/JsMaterialXGenShader.wasm?url`).then(m => m.default || m),
41
39
  /** @ts-ignore */
42
- import(`../bin/JsMaterialXGenShader.data.txt?url`).then(m => m.default || m),
40
+ import( /* @vite-ignore */ `../bin/JsMaterialXGenShader.data.txt?url`).then(m => m.default || m),
43
41
  ]);
44
42
  const [JsMaterialXCore, JsMaterialXGenShader, JsMaterialXGenShader_data] = urls;
45
43
 
46
44
  const module = await MaterialX({
47
- locateFile: (path: string, scriptDirectory: string) => {
45
+ locateFile: (/** @type {string} */ path, /** @type {string} */ scriptDirectory) => {
48
46
  if (debug) console.debug("[MaterialX] locateFile called:", { path, scriptDirectory });
49
47
 
50
48
  if (path.includes("JsMaterialXCore.wasm")) {
@@ -61,7 +59,7 @@ export async function ready(): Promise<void> {
61
59
  },
62
60
  });
63
61
  if (debug) console.log("[MaterialX] module loaded", module);
64
- state.materialXModule = module as MX.MODULE
62
+ state.materialXModule = /** @type {import("./materialx.types.js").MaterialX.MODULE} */ (module);
65
63
 
66
64
  // Initialize shader generator and context
67
65
  state.materialXGenerator = module.EsslShaderGenerator.create();
@@ -108,45 +106,69 @@ export async function ready(): Promise<void> {
108
106
  })();
109
107
  }
110
108
 
111
- type EnvironmentTextureSet = {
112
- radianceTexture: Texture | null;
113
- irradianceTexture: Texture | null;
114
- }
115
-
109
+ /**
110
+ * @typedef {Object} EnvironmentTextureSet
111
+ * @property {Texture | null} radianceTexture
112
+ * @property {Texture | null} irradianceTexture
113
+ */
116
114
 
117
115
  /**
118
116
  * MaterialXEnvironment manages the environment settings for MaterialX materials.
119
117
  */
120
118
  export class MaterialXEnvironment {
121
119
 
122
- static get(scene: Scene): MaterialXEnvironment | null {
120
+ /**
121
+ * @param {Scene} scene
122
+ * @returns {MaterialXEnvironment | null}
123
+ */
124
+ static get(scene) {
123
125
  return this.getEnvironment(scene);
124
126
  }
125
- private static _environments: WeakMap<Scene, MaterialXEnvironment> = new Map();
126
- private static getEnvironment(scene: Scene): MaterialXEnvironment {
127
+
128
+ /** @type {WeakMap<Scene, MaterialXEnvironment>} */
129
+ static _environments = new Map();
130
+
131
+ /**
132
+ * @param {Scene} scene
133
+ * @returns {MaterialXEnvironment}
134
+ */
135
+ static getEnvironment(scene) {
127
136
  if (this._environments.has(scene)) {
128
- return this._environments.get(scene)!;
137
+ return /** @type {MaterialXEnvironment} */ (this._environments.get(scene));
129
138
  }
130
139
  const env = new MaterialXEnvironment(scene);
131
140
  this._environments.set(scene, env);
132
141
  return env;
133
142
  }
134
143
 
135
-
136
- private _lights: Array<Light> = [];
137
- private _lightData: null | LightData[] = null;
138
- private _lightCount: number = 0;
139
-
140
- private _initializePromise: Promise<boolean> | null = null;
141
- private _isInitialized: boolean = false;
142
- private _lastUpdateFrame: number = -1;
143
-
144
- constructor(private _scene: Scene) {
144
+ /** @type {Array<Light>} */
145
+ _lights = [];
146
+ /** @type {import("./materialx.helper.js").LightData[] | null} */
147
+ _lightData = null;
148
+ /** @type {number} */
149
+ _lightCount = 0;
150
+
151
+ /** @type {Promise<boolean> | null} */
152
+ _initializePromise = null;
153
+ /** @type {boolean} */
154
+ _isInitialized = false;
155
+ /** @type {number} */
156
+ _lastUpdateFrame = -1;
157
+
158
+ /**
159
+ * @param {Scene} _scene
160
+ */
161
+ constructor(_scene) {
162
+ this._scene = _scene;
145
163
  if (debug) console.log("[MaterialX] Environment created");
146
164
  }
147
165
 
148
- // Initialize with Needle Engine context
149
- async initialize(renderer: WebGLRenderer): Promise<boolean> {
166
+ /**
167
+ * Initialize with Needle Engine context
168
+ * @param {WebGLRenderer} renderer
169
+ * @returns {Promise<boolean>}
170
+ */
171
+ async initialize(renderer) {
150
172
  if (this._initializePromise) {
151
173
  return this._initializePromise;
152
174
  }
@@ -154,7 +176,12 @@ export class MaterialXEnvironment {
154
176
  return this._initializePromise;
155
177
  }
156
178
 
157
- update(frame: number, scene: Scene, renderer: WebGLRenderer): void {
179
+ /**
180
+ * @param {number} frame
181
+ * @param {Scene} scene
182
+ * @param {WebGLRenderer} renderer
183
+ */
184
+ update(frame, scene, renderer) {
158
185
  if (!this._initializePromise) {
159
186
  this.initialize(renderer);
160
187
  return;
@@ -181,13 +208,15 @@ export class MaterialXEnvironment {
181
208
  const radianceCube = new Mesh(planeGeometry, radianceMat);
182
209
  const irradianceMat = unlitMat.clone();
183
210
  irradianceMat.map = textures.irradianceTexture;
184
- const irradianceCube = new Mesh(planeGeometry, radianceMat);
211
+ const irradianceCube = new Mesh(planeGeometry, irradianceMat);
185
212
  scene.add(radianceCube);
186
213
  scene.add(irradianceCube);
187
214
  radianceCube.name = "MaterialXRadianceCube";
188
- radianceCube.position.set(.6, 1, 0);
215
+ radianceCube.position.set(.8, 1, .01);
216
+ radianceCube.scale.set(1.5, 1, 1);
189
217
  irradianceCube.name = "MaterialXIrradianceCube";
190
- irradianceCube.position.set(-.6, 1, 0);
218
+ irradianceCube.position.set(-.8, 1, -.01);
219
+ irradianceCube.scale.set(1.5, 0.98, 1);
191
220
  console.log("[MaterialX] environment initialized from Needle context", { textures, radianceCube, irradianceCube });
192
221
  }
193
222
  }
@@ -218,7 +247,11 @@ export class MaterialXEnvironment {
218
247
  return this._lightData;
219
248
  }
220
249
  get lightCount() { return this._lightCount || 0; }
221
- getTextures(material: MaterialXMaterial) {
250
+
251
+ /**
252
+ * @param {import("./materialx.material.js").MaterialXMaterial} material
253
+ */
254
+ getTextures(material) {
222
255
  if (material.envMap) {
223
256
  // If the material has its own envMap, we don't use the irradiance texture
224
257
  return this._getTextures(material.envMap);
@@ -226,11 +259,18 @@ export class MaterialXEnvironment {
226
259
  return this._getTextures(this._scene.environment);
227
260
  }
228
261
 
229
- private _pmremGenerator: PMREMGenerator | null = null;
230
- private _renderer: WebGLRenderer | null = null;
231
- private readonly _texturesCache: Map<Texture | null, EnvironmentTextureSet> = new Map();
232
-
233
- private async _initialize(renderer: WebGLRenderer): Promise<boolean> {
262
+ /** @type {PMREMGenerator | null} */
263
+ _pmremGenerator = null;
264
+ /** @type {WebGLRenderer | null} */
265
+ _renderer = null;
266
+ /** @type {Map<Texture | null, EnvironmentTextureSet>} */
267
+ _texturesCache = new Map();
268
+
269
+ /**
270
+ * @param {WebGLRenderer} renderer
271
+ * @returns {Promise<boolean>}
272
+ */
273
+ async _initialize(renderer) {
234
274
  this._isInitialized = false;
235
275
  this._pmremGenerator = new PMREMGenerator(renderer);
236
276
  this._renderer = renderer;
@@ -239,11 +279,13 @@ export class MaterialXEnvironment {
239
279
  return true;
240
280
  }
241
281
 
242
- private _getTextures(texture: Texture | null | undefined): {
243
- radianceTexture: Texture | null,
244
- irradianceTexture: Texture | null
245
- } {
246
- let res: EnvironmentTextureSet | undefined = this._texturesCache.get(texture || null);
282
+ /**
283
+ * @param {Texture | null | undefined} texture
284
+ * @returns {{radianceTexture: Texture | null, irradianceTexture: Texture | null}}
285
+ */
286
+ _getTextures(texture) {
287
+ /** @type {EnvironmentTextureSet | undefined} */
288
+ let res = this._texturesCache.get(texture || null);
247
289
  if (res) {
248
290
  return res;
249
291
  }
@@ -269,14 +311,18 @@ export class MaterialXEnvironment {
269
311
  return res;
270
312
  }
271
313
 
272
- private updateLighting = (collectLights: boolean = false) => {
314
+ /**
315
+ * @param {boolean} collectLights
316
+ */
317
+ updateLighting = (collectLights = false) => {
273
318
  if (!this._scene) return;
274
319
  // Find lights in scene
275
320
  if (collectLights) {
276
- const lights = new Array<Light>();
277
- this._scene.traverse((object: Object3D) => {
278
- if ((object as Light).isLight && object.visible)
279
- lights.push(object as Light);
321
+ /** @type {Array<Light>} */
322
+ const lights = new Array();
323
+ this._scene.traverse((/** @type {Object3D} */ object) => {
324
+ if ((/** @type {Light} */ (object)).isLight && object.visible)
325
+ lights.push(/** @type {Light} */ (object));
280
326
  });
281
327
  this._lights = lights;
282
328
  }
@@ -0,0 +1,37 @@
1
+ import { BufferGeometry, Camera, Group, IUniform, MaterialParameters, Object3D, Scene, ShaderMaterial, Texture, WebGLRenderer } from "three";
2
+ import { MaterialXContext, MaterialXEnvironment } from "./materialx.js";
3
+ import { Callbacks } from "./materialx.helper.js";
4
+
5
+ declare type MaterialXMaterialInitParameters = {
6
+ name: string;
7
+ shaderName?: string | null;
8
+ shader: any;
9
+ loaders: Callbacks;
10
+ context: MaterialXContext;
11
+ parameters?: MaterialParameters;
12
+ debug?: boolean;
13
+ }
14
+
15
+ type Uniforms = Record<string, IUniform & { needsUpdate?: boolean }>;
16
+ type Precision = "highp" | "mediump" | "lowp";
17
+
18
+ export declare class MaterialXMaterial extends ShaderMaterial {
19
+ readonly shaderName: string | null;
20
+
21
+ copy(source: MaterialXMaterial): this;
22
+
23
+ private _context: MaterialXContext | null;
24
+ private _shader: any;
25
+ private _needsTangents: boolean;
26
+
27
+ constructor(init?: MaterialXMaterialInitParameters);
28
+
29
+ private _missingTangentsWarned: boolean;
30
+ onBeforeRender(renderer: WebGLRenderer, _scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D, _group: Group): void;
31
+
32
+ envMapIntensity: number;
33
+ envMap: Texture | null;
34
+ updateUniforms(environment: MaterialXEnvironment, _renderer: WebGLRenderer, object: Object3D, camera: Camera, time?: number, frame?: number): void;
35
+
36
+ private updateEnvironmentUniforms(environment: MaterialXEnvironment): void;
37
+ }