@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.
@@ -0,0 +1,216 @@
1
+ import { Camera, FrontSide, GLSL3, Matrix3, Matrix4, Object3D, ShaderMaterial, Texture, Vector3 } from "three";
2
+ import { debug } from "./utils.js";
3
+ import { MaterialXEnvironment } from "./materialx.js";
4
+ import { getUniformValues, Loaders } from "./materialx.helper.js";
5
+ import { Context } from "@needle-tools/engine";
6
+
7
+
8
+ // Add helper matrices for uniform updates (similar to MaterialX example)
9
+ const identityMatrix = new Matrix4();
10
+ const normalMat = new Matrix3();
11
+ const viewProjMat = new Matrix4();
12
+ const worldViewPos = new Vector3();
13
+
14
+ declare type MaterialXMaterialInitParameters = {
15
+ name: string,
16
+ shader: any,
17
+ loaders: Loaders,
18
+ transparent?: boolean,
19
+ }
20
+
21
+ export class MaterialXMaterial extends ShaderMaterial {
22
+
23
+ // copy(source: MaterialXMaterial): this {
24
+ // super.copy(source);
25
+ // this.name = source.name;
26
+ // this.uniforms = { ...source.uniforms }; // Shallow copy of uniforms
27
+ // this.envMapIntensity = source.envMapIntensity;
28
+ // this.envMap = source.envMap;
29
+ // this.updateUniforms = source.updateUniforms; // Copy the update function
30
+ // return this;
31
+ // }
32
+
33
+ constructor(init?: MaterialXMaterialInitParameters) {
34
+
35
+ // TODO: we need to properly copy the uniforms and other properties from the source material
36
+ if (!init) {
37
+ super();
38
+ return;
39
+ }
40
+
41
+ // Get vertex and fragment shader source, and remove #version directive for newer js.
42
+ // It's added by three.js glslVersion.
43
+ let vertexShader = init.shader.getSourceCode("vertex");
44
+ let fragmentShader = init.shader.getSourceCode("pixel");
45
+
46
+ vertexShader = vertexShader.replace(/^#version.*$/gm, '').trim();
47
+ fragmentShader = fragmentShader.replace(/^#version.*$/gm, '').trim();
48
+
49
+ // MaterialX uses different attribute names than js defaults,
50
+ // so we patch the MaterialX shaders to match the js standard names.
51
+ // Otherwise, we'd have to modify the mesh attributes (see original MaterialX for reference).
52
+
53
+ // Patch vertexShader
54
+ vertexShader = vertexShader.replace(/\bi_position\b/g, 'position');
55
+ vertexShader = vertexShader.replace(/\bi_normal\b/g, 'normal');
56
+ vertexShader = vertexShader.replace(/\bi_texcoord_0\b/g, 'uv');
57
+ vertexShader = vertexShader.replace(/\bi_texcoord_1\b/g, 'uv1');
58
+ vertexShader = vertexShader.replace(/\bi_tangent\b/g, 'tangent');
59
+ vertexShader = vertexShader.replace(/\bi_color_0\b/g, 'color');
60
+
61
+ // Patch fragmentShader
62
+ fragmentShader = fragmentShader.replace(/\bi_position\b/g, 'position');
63
+ fragmentShader = fragmentShader.replace(/\bi_normal\b/g, 'normal');
64
+ fragmentShader = fragmentShader.replace(/\bi_texcoord_0\b/g, 'uv');
65
+ fragmentShader = fragmentShader.replace(/\bi_texcoord_1\b/g, 'uv1');
66
+ fragmentShader = fragmentShader.replace(/\bi_tangent\b/g, 'tangent');
67
+ fragmentShader = fragmentShader.replace(/\bi_color_0\b/g, 'color');
68
+
69
+ // Remove `in vec3 position;` and so on since they're already declared by ShaderMaterial
70
+ vertexShader = vertexShader.replace(/in\s+vec3\s+position;/g, '');
71
+ vertexShader = vertexShader.replace(/in\s+vec3\s+normal;/g, '');
72
+ vertexShader = vertexShader.replace(/in\s+vec3\s+uv;/g, '');
73
+ vertexShader = vertexShader.replace(/in\s+vec3\s+uv1;/g, '');
74
+ vertexShader = vertexShader.replace(/in\s+vec4\s+tangent;/g, '');
75
+ vertexShader = vertexShader.replace(/in\s+vec4\s+color;/g, '');
76
+
77
+ // Patch uv 2-component to 3-component (`texcoord_0 = uv;` needs to be replaced with `texcoord_0 = vec3(uv, 0.0);`)
78
+ // TODO what if we actually have a 3-component UV? Not sure what three.js does then
79
+ vertexShader = vertexShader.replace(/texcoord_0 = uv;/g, 'texcoord_0 = vec3(uv, 0.0);');
80
+
81
+ // Patch units – seems MaterialX uses different units and we end up with wrong light values?
82
+ // result.direction = light.position - position;
83
+ fragmentShader = fragmentShader.replace(
84
+ /result\.direction\s*=\s*light\.position\s*-\s*position;/g,
85
+ 'result.direction = (light.position - position) * 10.0 / 1.0;');
86
+
87
+ // Add tonemapping and colorspace handling
88
+ // Replace `out vec4 out1;` with `out vec4 gl_FragColor;`
89
+ fragmentShader = fragmentShader.replace(
90
+ /out\s+vec4\s+out1;/,
91
+ 'layout(location = 0) out vec4 pc_fragColor;\n#define gl_FragColor pc_fragColor');
92
+
93
+ // Replace `out1 = vec4(<CAPTURE>)` with `gl_FragColor = vec4(<CAPTURE>)` and tonemapping/colorspace handling
94
+ fragmentShader = fragmentShader.replace(/^\s*out1\s*=\s*vec4\((.*)\);/gm, `
95
+ gl_FragColor = vec4($1);
96
+ #include <tonemapping_fragment>
97
+ #include <colorspace_fragment>`);
98
+
99
+ const searchPath = ""; // Could be derived from the asset path if needed
100
+ const isTransparent = init.transparent ?? false;
101
+ super({
102
+ name: init.name,
103
+ uniforms: {},
104
+ vertexShader: vertexShader,
105
+ fragmentShader: fragmentShader,
106
+ glslVersion: GLSL3,
107
+ transparent: isTransparent,
108
+ side: FrontSide,
109
+ depthTest: true,
110
+ depthWrite: !isTransparent,
111
+ });
112
+
113
+ Object.assign(this.uniforms, {
114
+ ...getUniformValues(init.shader.getStage('vertex'), init.loaders, searchPath),
115
+ ...getUniformValues(init.shader.getStage('pixel'), init.loaders, searchPath),
116
+ u_envMatrix: { value: new Matrix4() },
117
+ u_envRadiance: { value: null, type: 't' },
118
+ u_envRadianceMips: { value: 8, type: 'i' },
119
+ // TODO we need to figure out how we can set a PMREM here... doing many texture samples is prohibitively expensive
120
+ u_envRadianceSamples: { value: 8, type: 'i' },
121
+ u_envIrradiance: { value: null, type: 't' },
122
+ u_refractionEnv: { value: true },
123
+ u_numActiveLightSources: { value: 0 },
124
+ u_lightData: { value: [] }, // Array of light data
125
+ });
126
+
127
+ if (debug) {
128
+ // Get lighting and environment data from MaterialX environment
129
+ console.group("[MaterialX]: ", name);
130
+ console.log("Vertex shader length:", vertexShader.length, vertexShader);
131
+ console.log("Fragment shader length:", fragmentShader.length, fragmentShader);
132
+ console.groupEnd();
133
+ }
134
+
135
+ }
136
+
137
+
138
+ envMapIntensity: number = 1.0; // Default intensity for environment map
139
+ envMap: Texture | null = null; // Environment map texture, can be set externally
140
+ updateUniforms = (context: Context, environment: MaterialXEnvironment, object: Object3D, camera: Camera) => {
141
+
142
+ const uniforms = this.uniforms;
143
+
144
+ // TODO remove. Not sure why this is needed, but without it
145
+ // we currently get some "swimming" where matrices are not up to date.
146
+ camera.updateMatrixWorld(true);
147
+
148
+ // Update standard transformation matrices
149
+ if (uniforms.u_worldMatrix) {
150
+ if (!uniforms.u_worldMatrix.value?.isMatrix4) uniforms.u_worldMatrix.value = new Matrix4();
151
+ uniforms.u_worldMatrix.value = object.matrixWorld;
152
+ }
153
+
154
+ if (uniforms.u_viewProjectionMatrix) {
155
+ if (!uniforms.u_viewProjectionMatrix.value?.isMatrix4) uniforms.u_viewProjectionMatrix.value = new Matrix4();
156
+ uniforms.u_viewProjectionMatrix.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
157
+ }
158
+
159
+ if (uniforms.u_viewPosition) {
160
+ if (!uniforms.u_viewPosition.value?.isVector3) uniforms.u_viewPosition.value = new Vector3();
161
+ uniforms.u_viewPosition.value.copy(camera.getWorldPosition(worldViewPos));
162
+ }
163
+
164
+ if (uniforms.u_worldInverseTransposeMatrix) {
165
+ if (!uniforms.u_worldInverseTransposeMatrix.value?.isMatrix4) uniforms.u_worldInverseTransposeMatrix.value = new Matrix4();
166
+ uniforms.u_worldInverseTransposeMatrix.value.setFromMatrix3(normalMat.getNormalMatrix(object.matrixWorld));
167
+ }
168
+
169
+ // Update time uniforms
170
+ if (uniforms.u_time) {
171
+ uniforms.u_time.value = context.time.time;
172
+ }
173
+ if (uniforms.u_frame) {
174
+ uniforms.u_frame.value = context.time.frame;
175
+ }
176
+
177
+ // Update light uniforms
178
+ this.updateEnvironmentUniforms(environment);
179
+
180
+ this.uniformsNeedUpdate = true;
181
+ }
182
+
183
+ private updateEnvironmentUniforms = (environment: MaterialXEnvironment) => {
184
+
185
+ // Get lighting data from environment
186
+ const lightData = environment.lightData || null;
187
+ const lightCount = environment.lightCount || 0;
188
+ const textures = environment.getTextures(this) || null;
189
+
190
+ // Update light count
191
+ if (this.uniforms.u_numActiveLightSources && lightCount >= 0) {
192
+ this.uniforms.u_numActiveLightSources.value = lightCount;
193
+ }
194
+
195
+ // Update light data
196
+ if (lightData) {
197
+ this.uniforms.u_lightData.value = lightData;
198
+ }
199
+
200
+ // Update environment uniforms
201
+ if (this.uniforms.u_envMatrix) {
202
+ this.uniforms.u_envMatrix.value = identityMatrix;
203
+ }
204
+ if (this.uniforms.u_envRadiance) {
205
+ this.uniforms.u_envRadiance.value = textures.radianceTexture || null;
206
+ }
207
+ if (this.uniforms.u_envRadianceMips) {
208
+ this.uniforms.u_envRadianceMips.value = Math.trunc(Math.log2(Math.max(textures.radianceTexture?.source.data.width ?? 0, textures.radianceTexture?.source.data.height ?? 0))) + 1;
209
+ }
210
+ if (this.uniforms.u_envIrradiance) {
211
+ this.uniforms.u_envIrradiance.value = textures.irradianceTexture;
212
+ }
213
+
214
+ this.uniformsNeedUpdate = true;
215
+ }
216
+ }
package/src/materialx.ts CHANGED
@@ -1,13 +1,15 @@
1
- import { Context, delay, isDevEnvironment, ObjectUtils, GameObject } from "@needle-tools/engine";
1
+ import { Context, delay, isDevEnvironment, ObjectUtils, GameObject, onBeforeRender } from "@needle-tools/engine";
2
+ import type { MaterialX as MX } from "./materialx.types.js";
2
3
  import MaterialX from "../bin/JsMaterialXGenShader.js";
3
4
  import { debug } from "./utils.js";
4
5
  import { renderPMREMToEquirect } from "./textureHelper.js";
5
- import { Light, MeshBasicMaterial, Object3D, PMREMGenerator, Texture } from "three";
6
- import { registerLights, getLightData } from "./helper.js";
6
+ import { Light, Material, MeshBasicMaterial, Object3D, PMREMGenerator, Texture } from "three";
7
+ import { registerLights, getLightData } from "./materialx.helper.js";
8
+ import type { MaterialXMaterial } from "./materialx.material.js";
7
9
 
8
10
 
9
11
  export const state = new class {
10
- materialXModule: typeof MaterialX | null = null;
12
+ materialXModule: MX.MODULE | null = null;
11
13
  materialXGenerator: any = null;
12
14
  materialXGenContext: any = null;
13
15
  materialXStdLib: any = null;
@@ -59,7 +61,7 @@ export async function ready(): Promise<void> {
59
61
  },
60
62
  });
61
63
  if (debug) console.log("[MaterialX] module loaded", module);
62
- state.materialXModule = module;
64
+ state.materialXModule = module as MX.MODULE
63
65
 
64
66
  // Initialize shader generator and context
65
67
  state.materialXGenerator = module.EsslShaderGenerator.create();
@@ -95,7 +97,6 @@ export async function ready(): Promise<void> {
95
97
 
96
98
  // This prewarms the shader generation context to have all light types
97
99
  await registerLights(state.materialXModule, state.materialXGenContext);
98
- // getLightData(state.materialXModule, [], state.materialXGenContext);
99
100
 
100
101
  if (debug) console.log("[MaterialX] generator initialized successfully");
101
102
  } catch (error) {
@@ -105,91 +106,81 @@ export async function ready(): Promise<void> {
105
106
  })();
106
107
  }
107
108
 
109
+ type EnvironmentTextureSet = {
110
+ radianceTexture: Texture | null;
111
+ irradianceTexture: Texture | null;
112
+ }
113
+
108
114
  // MaterialX Environment Manager - handles lighting and environment setup
109
115
  export class MaterialXEnvironment {
110
116
  private _context: Context | null = null;
111
117
  private _lights: Array<Light> = [];
112
118
  private _lightData: any = null;
113
119
  private _lightCount: number = 0;
114
- private _radianceTexture: Texture | null = null;
115
- private _irradianceTexture: Texture | null = null;
116
120
  private _initializePromise: Promise<boolean> | null = null;
117
121
 
122
+ private _unsubscribehook: (() => void) | null = null;
123
+
118
124
  constructor() {
119
125
  if (debug) console.log("[MaterialX] Environment created");
120
126
  }
121
127
 
122
128
  // Initialize with Needle Engine context
123
- async initializeFromContext(context: Context): Promise<boolean> {
129
+ async initialize(context: Context): Promise<boolean> {
124
130
  if (this._initializePromise) {
125
131
  return this._initializePromise;
126
132
  }
127
133
  return this._initializePromise = this._initialize(context);
128
134
  }
129
135
 
130
- getLightData() { return this._lightData; }
131
- getLightCount() { return this._lightCount; }
132
-
133
- setRadianceTexture(texture: Texture) { this._radianceTexture = texture; }
134
- getRadianceTexture() { return this._radianceTexture; }
136
+ get lightData() { return this._lightData; }
137
+ get lightCount() { return this._lightCount || 0; }
138
+ getTextures(material: MaterialXMaterial) {
139
+ if (material.envMap) {
140
+ // If the material has its own envMap, we don't use the irradiance texture
141
+ return this._getTextures(material.envMap);
142
+ }
143
+ return this._getTextures(this._context?.scene.environment);
144
+ }
135
145
 
136
- getIrradianceTexture() { return this._irradianceTexture; }
137
- setIrradianceTexture(texture: Texture) { this._irradianceTexture = texture; }
146
+ private _pmremGenerator: PMREMGenerator | null = null;
147
+ private readonly _texturesCache: Map<Texture | null, EnvironmentTextureSet> = new Map();
138
148
 
139
149
  private _initialize: (context: Context) => Promise<boolean> = async (context: Context) => {
140
150
 
141
151
  this._context = context;
152
+ this._pmremGenerator = new PMREMGenerator(context.renderer);
142
153
 
143
- // Get renderer from context
144
- const renderer = context.renderer;
145
-
146
- // Clean up previous textures if they exist
147
- if (this._radianceTexture) {
148
- if (debug) console.log("[MaterialX] Disposing previous radiance texture");
149
- this._radianceTexture.dispose();
150
- this._radianceTexture = null;
151
- }
152
- if (this._irradianceTexture) {
153
- if (debug) console.log("[MaterialX] Disposing previous irradiance texture");
154
- this._irradianceTexture.dispose();
155
- this._irradianceTexture = null;
156
- }
154
+ this._unsubscribehook?.();
155
+ this._unsubscribehook = onBeforeRender(() => {
156
+ this.updateLighting(false);
157
+ this._getTextures(context.scene.environment);
158
+ })
157
159
 
158
160
  // TODO remove this delay; we should wait for the scene lighting to be ready
159
161
  // and then update the uniforms
160
- let envMap = context.scene.environment;
161
- while (!envMap) {
162
- await delay(1000);
163
- envMap = context.scene.environment;
164
- }
165
- const pmrem = new PMREMGenerator(renderer);
166
- const target = pmrem.fromEquirectangular(envMap);
167
- const radianceRenderTarget = renderPMREMToEquirect(renderer, target.texture, 0.0, 1024, 512, target.height);
168
- const irradianceRenderTarget = renderPMREMToEquirect(renderer, target.texture, 1.0, 32, 16, target.height);
169
- this._radianceTexture = radianceRenderTarget.texture;
170
- this._irradianceTexture = irradianceRenderTarget.texture;
171
-
172
- // Clean up PMREM generator and its render target
173
- target.dispose();
174
- pmrem.dispose();
175
-
176
- if (debug) {
177
- console.log({ radiance: this._radianceTexture, irradiance: this._irradianceTexture });
178
- // Show both of them on cubes in the scene
179
- const unlitMat = new MeshBasicMaterial();
180
- unlitMat.side = 2;
181
- const radianceMat = unlitMat.clone();
182
- radianceMat.map = this._radianceTexture;
183
- const radianceCube = ObjectUtils.createPrimitive("Quad", { material: radianceMat });
184
- const irradianceMat = unlitMat.clone();
185
- irradianceMat.map = this._irradianceTexture;
186
- const irradianceCube = ObjectUtils.createPrimitive("Quad", { material: irradianceMat });
187
- context.scene.add(radianceCube);
188
- context.scene.add(irradianceCube);
189
- radianceCube.position.set(2, 0, 0);
190
- irradianceCube.position.set(-2, 0, 0);
191
- console.log("[MaterialX] environment initialized from Needle context", this, this._context.scene);
162
+ while (!context.scene.environment) {
163
+ await delay(5);
192
164
  }
165
+ this._getTextures(context.scene.environment);
166
+
167
+ // if (debug) {
168
+ // console.log({ radiance: this._radianceTexture, irradiance: this._irradianceTexture });
169
+ // // Show both of them on cubes in the scene
170
+ // const unlitMat = new MeshBasicMaterial();
171
+ // unlitMat.side = 2;
172
+ // const radianceMat = unlitMat.clone();
173
+ // radianceMat.map = this._radianceTexture;
174
+ // const radianceCube = ObjectUtils.createPrimitive("Quad", { material: radianceMat });
175
+ // const irradianceMat = unlitMat.clone();
176
+ // irradianceMat.map = this._irradianceTexture;
177
+ // const irradianceCube = ObjectUtils.createPrimitive("Quad", { material: irradianceMat });
178
+ // context.scene.add(radianceCube);
179
+ // context.scene.add(irradianceCube);
180
+ // radianceCube.position.set(2, 0, 0);
181
+ // irradianceCube.position.set(-2, 0, 0);
182
+ // console.log("[MaterialX] environment initialized from Needle context", this, this._context.scene);
183
+ // }
193
184
 
194
185
  this.updateLighting(true);
195
186
 
@@ -197,7 +188,58 @@ export class MaterialXEnvironment {
197
188
  return true;
198
189
  }
199
190
 
200
- updateLighting(collectLights: boolean) {
191
+ // Reset the environment to allow re-initialization
192
+ reset() {
193
+ if (debug) console.log("[MaterialX] Resetting environment");
194
+ this._initializePromise = null;
195
+ this._lights = [];
196
+ this._lightData = null;
197
+ this._lightCount = 0;
198
+ this._pmremGenerator?.dispose();
199
+ this._pmremGenerator = null;
200
+ for(const textureSet of this._texturesCache.values()) {
201
+ textureSet.radianceTexture?.dispose();
202
+ textureSet.irradianceTexture?.dispose();
203
+ }
204
+ this._texturesCache.clear();
205
+
206
+ this._unsubscribehook?.();
207
+ this._unsubscribehook = null;
208
+ }
209
+
210
+ private _getTextures(texture: Texture | null | undefined): {
211
+ radianceTexture: Texture | null,
212
+ irradianceTexture: Texture | null
213
+ } {
214
+
215
+ let res: EnvironmentTextureSet | undefined = this._texturesCache.get(texture || null);
216
+ if (res) {
217
+ return res;
218
+ }
219
+
220
+ if (this._context && this._pmremGenerator && texture) {
221
+ if (debug) console.log("[MaterialX] Generating environment textures", texture.name);
222
+
223
+ const target = this._pmremGenerator.fromEquirectangular(texture);
224
+ const radianceRenderTarget = renderPMREMToEquirect(this._context.renderer, target.texture, 0.0, 1024, 512, target.height);
225
+ const irradianceRenderTarget = renderPMREMToEquirect(this._context.renderer, target.texture, 1.0, 32, 16, target.height);
226
+ target.dispose();
227
+ res = {
228
+ radianceTexture: radianceRenderTarget.texture,
229
+ irradianceTexture: irradianceRenderTarget.texture
230
+ }
231
+ }
232
+ else {
233
+ res = {
234
+ radianceTexture: null,
235
+ irradianceTexture: null
236
+ }
237
+ }
238
+ this._texturesCache.set(texture || null, res);
239
+ return res;
240
+ }
241
+
242
+ private updateLighting = (collectLights: boolean = false) => {
201
243
  if (!this._context) return;
202
244
 
203
245
  // Find lights in scene
@@ -210,24 +252,10 @@ export class MaterialXEnvironment {
210
252
  this._lights = lights;
211
253
  }
212
254
 
213
- const { lightData, lightCount } = getLightData(state.materialXModule, this._lights, state.materialXGenContext);
214
- this._lightData = lightData;
215
- this._lightCount = lightCount;
216
- }
217
-
218
- // Reset the environment to allow re-initialization
219
- reset() {
220
- if (debug) console.log("[MaterialX] Resetting environment");
221
- if (this._radianceTexture) {
222
- this._radianceTexture.dispose();
223
- this._radianceTexture = null;
255
+ if (state.materialXGenContext) {
256
+ const { lightData, lightCount } = getLightData(this._lights, state.materialXGenContext);
257
+ this._lightData = lightData;
258
+ this._lightCount = lightCount;
224
259
  }
225
- if (this._irradianceTexture) {
226
- this._irradianceTexture.dispose();
227
- this._irradianceTexture = null;
228
- }
229
- this._initializePromise = null;
230
- this._lights = [];
231
- this._lightData = null;
232
260
  }
233
261
  }
@@ -0,0 +1,50 @@
1
+
2
+
3
+
4
+ export namespace MaterialX {
5
+
6
+ export type MODULE = {
7
+ ShaderInterfaceType: any;
8
+ HwSpecularEnvironmentMethod: any;
9
+ HwShaderGenerator: {
10
+ bindLightShader(def: any, id: number, genContext: GenContext): void;
11
+ unbindLightShaders(context: any): void;
12
+ };
13
+ createDocument(): Document;
14
+ readFromXmlString(doc: Document, xml: string, unknown: string): void;
15
+ loadStandardLibraries(genContext: GenContext): StandardLibrary;
16
+ isTransparentSurface(renderableElement: any, target: string): boolean;
17
+ }
18
+
19
+
20
+ export type GenContext = {
21
+ }
22
+
23
+ export type StandardLibrary = {
24
+
25
+ }
26
+
27
+ // https://github.com/AcademySoftwareFoundation/MaterialX/blob/b74787db6544283dc32afc8085ebc93cabe937cb/source/MaterialXGenShader/ShaderStage.h#L56
28
+ export type ShaderStage = {
29
+ getUniformBlocks(): Record<string, any>;
30
+ }
31
+
32
+ export type Document = {
33
+ setDataLibrary(lib: StandardLibrary): void;
34
+ importLibrary(lib: Document): void;
35
+
36
+ getNodes(): Node[];
37
+ }
38
+
39
+ export type Node = {
40
+ getType(): string;
41
+ }
42
+
43
+ export type Matrix = {
44
+ numRows(): number;
45
+ numColumns(): number;
46
+ get size(): number;
47
+ getItem(row: number, col: number): number;
48
+ }
49
+
50
+ }
@@ -40,7 +40,7 @@ export function renderPMREMToEquirect(renderer: WebGLRenderer, pmremTexture: Tex
40
40
  } else {
41
41
  imageHeight = 256; // Final fallback
42
42
  }
43
-
43
+
44
44
  const maxMip = Math.log2(imageHeight) - 2;
45
45
  const cubeUVHeight = imageHeight;
46
46
  const cubeUVWidth = 3 * Math.max(Math.pow(2, maxMip), 7 * 16);
@@ -129,14 +129,14 @@ export function renderPMREMToEquirect(renderer: WebGLRenderer, pmremTexture: Tex
129
129
  const currentAutoClear = renderer.autoClear;
130
130
  const currentXrEnabled = renderer.xr.enabled;
131
131
  const currentShadowMapEnabled = renderer.shadowMap.enabled;
132
-
132
+
133
133
  renderTarget.texture.generateMipmaps = true;
134
-
134
+
135
135
  try {
136
136
  // Disable XR and shadow mapping during our render to avoid interference
137
137
  renderer.xr.enabled = false;
138
138
  renderer.shadowMap.enabled = false;
139
-
139
+
140
140
  // Render to our target
141
141
  renderer.autoClear = true;
142
142
  renderer.setRenderTarget(renderTarget);
@@ -148,7 +148,7 @@ export function renderPMREMToEquirect(renderer: WebGLRenderer, pmremTexture: Tex
148
148
  renderer.autoClear = currentAutoClear;
149
149
  renderer.xr.enabled = currentXrEnabled;
150
150
  renderer.shadowMap.enabled = currentShadowMapEnabled;
151
-
151
+
152
152
  // Clean up temporary objects
153
153
  geometry.dispose();
154
154
  material.dispose();
@@ -159,7 +159,7 @@ export function renderPMREMToEquirect(renderer: WebGLRenderer, pmremTexture: Tex
159
159
  renderTarget.texture.mapping = EquirectangularReflectionMapping;
160
160
 
161
161
  // Log mipmap infos
162
- if (debug) console.log('PMREM to Equirect Render Target:', {
162
+ if (debug) console.log('[MaterialX] PMREM to Equirect Render Target:', {
163
163
  width: renderTarget.width,
164
164
  height: renderTarget.height,
165
165
  mipmaps: renderTarget.texture.mipmaps?.length,
package/src/utils.ts CHANGED
@@ -2,10 +2,7 @@ import { Context, getParam } from "@needle-tools/engine";
2
2
  import { Mesh } from "three";
3
3
 
4
4
  export const debug = getParam("debugmaterialx");
5
-
6
-
7
-
8
-
5
+ export const debugUpdate = getParam("debugmaterialxupdate");
9
6
 
10
7
  /**
11
8
  * =====================================
@@ -33,6 +30,44 @@ const patchWebGL2 = () => {
33
30
  }
34
31
  return uniform4fv.call(this, location, v);
35
32
  };
33
+
34
+ const uniform3fv = WebGL2RenderingContext.prototype.uniform3fv;
35
+ WebGL2RenderingContext.prototype.uniform3fv = function (location: WebGLUniformLocation | null, v: Float32Array | number[]) {
36
+ if (location) {
37
+ const uniformName = programAndNameToUniformLocation.get(location);
38
+ if (true) console.log("Calling uniform3fv", { location, v, name: uniformName?.name });
39
+ }
40
+ return uniform3fv.call(this, location, v);
41
+ };
42
+
43
+ const uniform3iv = WebGL2RenderingContext.prototype.uniform3iv;
44
+ WebGL2RenderingContext.prototype.uniform3iv = function (location: WebGLUniformLocation | null, v: Int32Array | number[]) {
45
+ if (location) {
46
+ const uniformName = programAndNameToUniformLocation.get(location);
47
+ if (true) console.log("Calling uniform3iv", { location, v, name: uniformName?.name });
48
+ }
49
+ return uniform3iv.call(this, location, v);
50
+ };
51
+
52
+ const uniform3uiv = WebGL2RenderingContext.prototype.uniform3uiv;
53
+ WebGL2RenderingContext.prototype.uniform3uiv = function (location: WebGLUniformLocation | null, v: Uint32Array | number[]) {
54
+ if (location) {
55
+ const uniformName = programAndNameToUniformLocation.get(location);
56
+ if (true) console.log("Calling uniform3uiv", { location, v, name: uniformName?.name });
57
+ }
58
+ return uniform3uiv.call(this, location, v);
59
+ };
60
+
61
+ const uniform3f = WebGL2RenderingContext.prototype.uniform3f;
62
+ WebGL2RenderingContext.prototype.uniform3f = function (location: WebGLUniformLocation
63
+ | null, x: number, y: number, z: number) {
64
+ if (location) {
65
+ const uniformName = programAndNameToUniformLocation.get(location);
66
+ if (uniformName?.name !== "diffuse")
67
+ if (true) console.log("Calling uniform3f", { location, x, y, z, name: uniformName?.name });
68
+ }
69
+ return uniform3f.call(this, location, x, y, z);
70
+ };
36
71
  };
37
72
  // patchWebGL2();
38
73