@needle-tools/materialx 1.1.0 → 1.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/materialx",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "exports": {
@@ -239,13 +239,16 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
239
239
  const elementName = (renderableElement as any).getNamePath ? (renderableElement as any).getNamePath() : (renderableElement as any).getName();
240
240
 
241
241
  const shader = state.materialXGenerator.generate(elementName, renderableElement, state.materialXGenContext);
242
+
242
243
  const shaderMaterial = new MaterialXMaterial({
243
244
  name: material_extension.name,
244
245
  shader,
245
- transparent: isTransparent,
246
- side: material_def.doubleSided ? DoubleSide : FrontSide,
247
246
  context: this.context,
248
- precision: this.options.parameters?.precision,
247
+ parameters: {
248
+ transparent: isTransparent,
249
+ side: material_def.doubleSided ? DoubleSide : FrontSide,
250
+ ...this.options.parameters,
251
+ },
249
252
  loaders: {
250
253
  cacheKey: this.options.cacheKey || "",
251
254
  getTexture: async url => {
@@ -466,12 +466,57 @@ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Lo
466
466
  for (let i = 0; i < uniforms.size(); ++i) {
467
467
  const variable = uniforms.get(i);
468
468
  const value = variable.getValue()?.getData();
469
- const name = variable.getVariable();
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
+ const uniformName = variable.getVariable();
470
+ const type = variable.getType().getName();
471
+ if (debug) console.log("Adding uniform", { path: variable.getPath(), name: uniformName, value: value, type: type });
472
+ threeUniforms[uniformName] = toThreeUniform(uniforms, type, value, uniformName, loaders, searchPath);
472
473
  }
473
474
  }
474
475
  }
475
476
 
476
477
  return threeUniforms;
477
478
  }
479
+
480
+ export function generateMaterialPropertiesForUniforms(material: THREE.ShaderMaterial, shaderStage: MaterialX.ShaderStage) {
481
+
482
+ const uniformBlocks = shaderStage.getUniformBlocks()
483
+ for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
484
+ // Seems struct uniforms (like in LightData) end up here as well, we should filter those out.
485
+ if (blockName === "LightData") continue;
486
+
487
+ if (!uniforms.empty()) {
488
+ for (let i = 0; i < uniforms.size(); ++i) {
489
+ const variable = uniforms.get(i);
490
+ const uniformName = variable.getVariable();
491
+ let key = variable.getPath().split('/').pop();
492
+ switch (key) {
493
+ case "_Color":
494
+ key = "color";
495
+ break;
496
+ case "_Roughness":
497
+ key = "roughness";
498
+ break;
499
+ case "_Metallic":
500
+ key = "metalness";
501
+ break;
502
+ }
503
+ if (key) {
504
+ Object.defineProperty(material, key, {
505
+ get: function () {
506
+ return this.uniforms?.[uniformName].value
507
+ },
508
+ set: function (v) {
509
+ const uniforms = this.uniforms;
510
+ if (!uniforms || !uniforms[uniformName]) {
511
+ console.warn(`[MaterialX] Uniform ${uniformName} not found in ${this.name} uniforms`);
512
+ return;
513
+ }
514
+ this.uniforms[uniformName].value = v;
515
+ this.uniformsNeedUpdate = true;
516
+ }
517
+ });
518
+ }
519
+ }
520
+ }
521
+ }
522
+ }
@@ -1,7 +1,8 @@
1
1
  import { BufferGeometry, Camera, FrontSide, GLSL3, Group, IUniform, MaterialParameters, Matrix3, Matrix4, Object3D, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
2
2
  import { debug, getFrame, getTime } from "./utils.js";
3
3
  import { MaterialXContext, MaterialXEnvironment } from "./materialx.js";
4
- import { getUniformValues, Loaders } from "./materialx.helper.js";
4
+ import { generateMaterialPropertiesForUniforms, getUniformValues, Loaders } from "./materialx.helper.js";
5
+ import { cloneUniforms, cloneUniformsGroups } from "three/src/renderers/shaders/UniformsUtils.js";
5
6
 
6
7
 
7
8
  // Add helper matrices for uniform updates (similar to MaterialX example)
@@ -14,9 +15,7 @@ declare type MaterialXMaterialInitParameters = {
14
15
  loaders: Loaders,
15
16
  context: MaterialXContext,
16
17
  // Optional parameters
17
- transparent?: boolean,
18
- side?: MaterialParameters['side'],
19
- precision?: MaterialParameters['precision'],
18
+ parameters?: MaterialParameters,
20
19
  }
21
20
 
22
21
  type Uniforms = Record<string, IUniform & { needsUpdate?: boolean }>;
@@ -27,10 +26,19 @@ export class MaterialXMaterial extends ShaderMaterial {
27
26
  copy(source: MaterialXMaterial): this {
28
27
  super.copy(source);
29
28
  this._context = source._context;
29
+ this._shader = source._shader;
30
+ this.uniforms = cloneUniforms(source.uniforms) as Uniforms;
31
+ this.uniformsGroups = cloneUniformsGroups(source.uniformsGroups);
32
+ this.envMapIntensity = source.envMapIntensity;
33
+ this.envMap = source.envMap;
34
+ generateMaterialPropertiesForUniforms(this, this._shader.getStage('pixel'));
35
+ generateMaterialPropertiesForUniforms(this, this._shader.getStage('vertex'));
36
+ this.needsUpdate = true;
30
37
  return this;
31
38
  }
32
39
 
33
40
  private _context: MaterialXContext | null = null;
41
+ private _shader: any;
34
42
 
35
43
  constructor(init?: MaterialXMaterialInitParameters) {
36
44
 
@@ -63,7 +71,7 @@ export class MaterialXMaterial extends ShaderMaterial {
63
71
  vertexShader = vertexShader.replace(/\bi_color_0\b/g, 'color');
64
72
 
65
73
  // Patch fragmentShader
66
- const precision = init.precision || "highp" as Precision;
74
+ const precision = init.parameters?.precision || "highp" as Precision;
67
75
  fragmentShader = fragmentShader.replace(/precision mediump float;/g, `precision ${precision} float;`);
68
76
  fragmentShader = fragmentShader.replace(/#define M_FLOAT_EPS 1e-8/g, precision === "highp" ? `#define M_FLOAT_EPS 1e-8` : `#define M_FLOAT_EPS 1e-3`);
69
77
 
@@ -124,19 +132,20 @@ export class MaterialXMaterial extends ShaderMaterial {
124
132
  if (hasColor) defines['USE_COLOR'] = '';
125
133
 
126
134
  const searchPath = ""; // Could be derived from the asset path if needed
127
- const isTransparent = init.transparent ?? false;
135
+ const isTransparent = init.parameters?.transparent ?? false;
128
136
  super({
129
137
  name: init.name,
130
138
  uniforms: {},
131
139
  vertexShader: vertexShader,
132
140
  fragmentShader: fragmentShader,
133
141
  glslVersion: GLSL3,
134
- transparent: isTransparent,
135
- side: init.side ? init.side : FrontSide,
136
142
  depthTest: true,
137
143
  depthWrite: !isTransparent,
138
144
  defines: defines,
145
+ ...init.parameters, // Spread any additional parameters passed to the material
139
146
  });
147
+ this._context = init.context;
148
+ this._shader = init.shader;
140
149
 
141
150
  Object.assign(this.uniforms, {
142
151
  ...getUniformValues(init.shader.getStage('vertex'), init.loaders, searchPath),
@@ -158,7 +167,9 @@ export class MaterialXMaterial extends ShaderMaterial {
158
167
  u_lightData: { value: [], needsUpdate: false }, // Array of light data. We need to set needsUpdate to false until we actually update it
159
168
  });
160
169
 
161
- this._context = init.context;
170
+ generateMaterialPropertiesForUniforms(this, init.shader.getStage('pixel'));
171
+ generateMaterialPropertiesForUniforms(this, init.shader.getStage('vertex'));
172
+
162
173
 
163
174
  if (debug) {
164
175
  // Get lighting and environment data from MaterialX environment
@@ -216,7 +227,7 @@ export class MaterialXMaterial extends ShaderMaterial {
216
227
  if (frame === undefined) frame = getFrame();
217
228
  uniforms.u_frame.value = frame;
218
229
  }
219
-
230
+
220
231
  // Update light uniforms
221
232
  this.updateEnvironmentUniforms(environment);
222
233