@needle-tools/materialx 1.0.1-next.df0e959 → 1.0.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/README.md +0 -5
- package/codegen/register_types.ts +0 -2
- package/index.ts +1 -1
- package/package.json +4 -19
- package/src/helper.js +7 -40
- package/src/index.ts +2 -2
- package/src/loader/loader.needle.ts +13 -11
- package/src/loader/loader.three.ts +63 -78
- package/src/materialx.ts +102 -102
package/README.md
CHANGED
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/materialx",
|
|
3
|
-
"version": "1.0.1
|
|
3
|
+
"version": "1.0.1",
|
|
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",
|
|
@@ -27,16 +23,5 @@
|
|
|
27
23
|
"publishConfig": {
|
|
28
24
|
"access": "public",
|
|
29
25
|
"registry": "https://registry.npmjs.org/"
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
"needle",
|
|
33
|
-
"materialx",
|
|
34
|
-
"material",
|
|
35
|
-
"shader",
|
|
36
|
-
"threejs",
|
|
37
|
-
"three.js",
|
|
38
|
-
"webgl",
|
|
39
|
-
"mtlx",
|
|
40
|
-
"rendering"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/helper.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
//
|
|
5
5
|
|
|
6
|
-
import { getParam
|
|
6
|
+
import { getParam } from '@needle-tools/engine';
|
|
7
7
|
import * as THREE from 'three';
|
|
8
8
|
|
|
9
9
|
const debug = getParam("debugmaterialx");
|
|
@@ -88,7 +88,7 @@ function fromMatrix(matrix, dimension)
|
|
|
88
88
|
* @param {mx.Uniform.value} value
|
|
89
89
|
* @param {mx.Uniform.name} name
|
|
90
90
|
* @param {mx.Uniforms} uniforms
|
|
91
|
-
* @param {THREE.
|
|
91
|
+
* @param {THREE.textureLoader} textureLoader
|
|
92
92
|
* @param {string} searchPath
|
|
93
93
|
* @param {boolean} flipY
|
|
94
94
|
*/
|
|
@@ -301,14 +301,10 @@ export function findLights(doc)
|
|
|
301
301
|
export async function registerLights(mx, lights, genContext)
|
|
302
302
|
{
|
|
303
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
304
|
|
|
307
305
|
const lightTypesBound = {};
|
|
308
306
|
const lightData = [];
|
|
309
307
|
let lightId = 1;
|
|
310
|
-
let lightCount = 0;
|
|
311
|
-
const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
|
|
312
308
|
|
|
313
309
|
// All light types so that we have NodeDefs for them
|
|
314
310
|
const defaultLightRigXml = `<?xml version="1.0"?>
|
|
@@ -335,9 +331,6 @@ export async function registerLights(mx, lights, genContext)
|
|
|
335
331
|
const defaultLights = findLights(document);
|
|
336
332
|
if (debug) console.log("Default lights in MaterialX document", defaultLights);
|
|
337
333
|
|
|
338
|
-
// Loading a document seems to reset this option for some reason, so we set it again
|
|
339
|
-
genContext.getOptions().hwMaxActiveLightSources = maxLightCount;
|
|
340
|
-
|
|
341
334
|
// Register types only – we get these from the default light rig XML above
|
|
342
335
|
// This is needed to ensure that the light shaders are bound for each light type
|
|
343
336
|
for (let light of defaultLights)
|
|
@@ -421,44 +414,18 @@ export async function registerLights(mx, lights, genContext)
|
|
|
421
414
|
mx.HwShaderGenerator.bindLightShader(nodeDef, lightId++, genContext);
|
|
422
415
|
}
|
|
423
416
|
|
|
424
|
-
const wp = light.getWorldPosition(new THREE.Vector3());
|
|
425
|
-
const wd = getWorldDirection(light, new THREE.Vector3(0,0,-1));
|
|
426
417
|
lightData.push({
|
|
427
418
|
type: lightTypesBound[lightDefinitionName],
|
|
428
|
-
|
|
429
|
-
direction: wd.clone(),
|
|
419
|
+
direction: light.direction?.clone() || new THREE.Vector3(0, -1, 0),
|
|
430
420
|
color: new THREE.Vector3().fromArray(light.color.toArray()),
|
|
431
|
-
intensity: light.intensity,
|
|
432
|
-
decay_rate: 2.0, // physically-based default decay rate
|
|
433
|
-
inner_angle: 1.0,
|
|
434
|
-
outer_angle: 2.0,
|
|
421
|
+
intensity: light.intensity,
|
|
435
422
|
});
|
|
436
423
|
}
|
|
437
424
|
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
// If we don't have enough entries in lightData, fill with empty lights
|
|
442
|
-
if (lightData.length < maxLightCount)
|
|
443
|
-
{
|
|
444
|
-
const emptyLight = {
|
|
445
|
-
type: 0, // Default light type
|
|
446
|
-
position: new THREE.Vector3(0, 0, 0),
|
|
447
|
-
direction: new THREE.Vector3(0, 0, -1),
|
|
448
|
-
color: new THREE.Vector3(0, 0, 0),
|
|
449
|
-
intensity: 0,
|
|
450
|
-
decay_rate: 2,
|
|
451
|
-
inner_angle: 0,
|
|
452
|
-
outer_angle: 0,
|
|
453
|
-
};
|
|
454
|
-
while (lightData.length < maxLightCount) {
|
|
455
|
-
lightData.push(emptyLight);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
if (debug) console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
|
|
425
|
+
// Make sure max light count is large enough
|
|
426
|
+
genContext.getOptions().hwMaxActiveLightSources = Math.max(genContext.getOptions().hwMaxActiveLightSources, lightData.length);
|
|
460
427
|
|
|
461
|
-
return
|
|
428
|
+
return lightData;
|
|
462
429
|
}
|
|
463
430
|
|
|
464
431
|
/**
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { initializeMaterialX, state } from "./materialx.js";
|
|
2
2
|
|
|
3
3
|
const getMaterialXEnvironment = () => state.materialXEnvironment;
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export { initializeMaterialX, getMaterialXEnvironment };
|
|
@@ -52,9 +52,9 @@ export class MaterialXUniformUpdate extends Component {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
55
|
-
|
|
55
|
+
name = "MaterialXLoaderPlugin";
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
mtlxLoader: MaterialXLoader | null = null;
|
|
58
58
|
|
|
59
59
|
onImport = (loader: GLTFLoader, url: string, context: Context) => {
|
|
60
60
|
if (debug) console.log("MaterialXLoaderPlugin: Registering MaterialX extension for", url);
|
|
@@ -62,13 +62,13 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
62
62
|
// Register the MaterialX loader extension
|
|
63
63
|
// Environment initialization is now handled in the MaterialXLoader constructor
|
|
64
64
|
loader.register(p => {
|
|
65
|
-
this.
|
|
66
|
-
return this.
|
|
65
|
+
this.mtlxLoader = new MaterialXLoader(p, context);
|
|
66
|
+
return this.mtlxLoader;
|
|
67
67
|
});
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
onLoaded = (url: string, gltf: GLTF,
|
|
71
|
-
if (debug) console.log("
|
|
70
|
+
onLoaded = (url: string, gltf: GLTF, _context: Context) => {
|
|
71
|
+
if (debug) console.log("MaterialXLoaderPlugin: glTF loaded", url, gltf.scene);
|
|
72
72
|
|
|
73
73
|
// Set up onBeforeRender callbacks for objects with MaterialX materials
|
|
74
74
|
// This ensures uniforms are updated properly during rendering
|
|
@@ -78,23 +78,25 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
78
78
|
const material = mesh.material as Material;
|
|
79
79
|
|
|
80
80
|
if (material?.userData?.updateUniforms) {
|
|
81
|
-
if (debug) console.log("
|
|
81
|
+
if (debug) console.log("Adding MaterialX uniform update component to:", child.name);
|
|
82
82
|
child.addComponent(MaterialXUniformUpdate);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
if (debug) console.log("
|
|
87
|
+
if (debug) console.log("Loaded: ", this.mtlxLoader);
|
|
88
88
|
|
|
89
89
|
// Initialize MaterialX lighting system with scene data
|
|
90
90
|
const environment = state.materialXEnvironment;
|
|
91
|
-
environment.initializeFromContext(
|
|
92
|
-
this.
|
|
91
|
+
environment.initializeFromContext().then(() => {
|
|
92
|
+
if (this.mtlxLoader) {
|
|
93
|
+
this.mtlxLoader.updateLightingFromEnvironment(environment);
|
|
94
|
+
}
|
|
93
95
|
});
|
|
94
96
|
};
|
|
95
97
|
|
|
96
98
|
onExport = (_exporter: GLTFExporter, _context: Context) => {
|
|
97
|
-
console.log("
|
|
99
|
+
console.log("TODO: MaterialXLoaderPlugin: Setting up export extensions");
|
|
98
100
|
// TODO: Add MaterialX export functionality if needed
|
|
99
101
|
};
|
|
100
102
|
}
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
import { Context } from "@needle-tools/engine";
|
|
2
|
-
import {
|
|
2
|
+
import { RawShaderMaterial, Material, MeshStandardMaterial, LoadingManager, TextureLoader, Texture, NearestFilter, Matrix4, GLSL3, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, DoubleSide, Matrix3, Vector3, Object3D, Camera } from "three";
|
|
3
3
|
import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
4
|
import { getUniformValues } from "../helper.js";
|
|
5
|
-
import {
|
|
5
|
+
import { initializeMaterialX, MaterialXEnvironment, state } from "../materialx.js";
|
|
6
6
|
import { debug } from "../utils.js";
|
|
7
7
|
|
|
8
8
|
// TypeScript interfaces matching the C# data structures
|
|
9
|
-
interface
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
name: string;
|
|
14
|
-
/** MaterialX xml content */
|
|
15
|
-
mtlx: string;
|
|
9
|
+
interface MaterialXData {
|
|
10
|
+
version: string; // e.g. "1.39"
|
|
11
|
+
name: string; // e.g. "Material"
|
|
12
|
+
mtlx: string; // MaterialX XML content
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
interface
|
|
19
|
-
name: string;
|
|
15
|
+
interface MaterialXDataIndex {
|
|
16
|
+
name: string; // Material name reference
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
// MaterialX loader extension for js GLTFLoader
|
|
23
20
|
export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
24
21
|
name = "NEEDLE_materials_mtlx";
|
|
25
22
|
|
|
26
|
-
private rootMaterialXData:
|
|
23
|
+
private rootMaterialXData: MaterialXData | null = null;
|
|
27
24
|
private parsedDocument: any = null;
|
|
28
25
|
private documentParsePromise: Promise<any> | null = null;
|
|
29
26
|
private rootDataInitialized = false;
|
|
30
27
|
private environmentInitialized = false;
|
|
31
|
-
private generatedMaterials:
|
|
28
|
+
private generatedMaterials: RawShaderMaterial[] = [];
|
|
32
29
|
|
|
33
30
|
constructor(private parser: GLTFParser, private context: Context) {
|
|
34
31
|
if (debug) console.log("MaterialXLoader created for parser");
|
|
@@ -40,20 +37,22 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
40
37
|
private async initializeEnvironment(): Promise<void> {
|
|
41
38
|
if (this.environmentInitialized) return;
|
|
42
39
|
|
|
43
|
-
if (debug) console.log("
|
|
40
|
+
if (debug) console.log("MaterialXLoader: Initializing MaterialX environment...");
|
|
44
41
|
|
|
45
42
|
// Ensure MaterialX is initialized first
|
|
46
|
-
await
|
|
43
|
+
await initializeMaterialX();
|
|
47
44
|
|
|
48
45
|
// Set up environment with context
|
|
49
46
|
const environment = state.materialXEnvironment;
|
|
47
|
+
environment.setContext(this.context);
|
|
48
|
+
|
|
50
49
|
// Initialize the environment from context (properly awaited)
|
|
51
50
|
try {
|
|
52
|
-
await environment.initializeFromContext(
|
|
51
|
+
await environment.initializeFromContext();
|
|
53
52
|
this.environmentInitialized = true;
|
|
54
|
-
if (debug) console.log("
|
|
53
|
+
if (debug) console.log("MaterialXLoader: Environment initialized successfully");
|
|
55
54
|
} catch (error) {
|
|
56
|
-
console.warn("
|
|
55
|
+
console.warn("MaterialXLoader: Failed to initialize MaterialX environment:", error);
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -63,10 +62,10 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
63
62
|
|
|
64
63
|
const gltfExtensions = this.parser.json.extensions;
|
|
65
64
|
if (gltfExtensions?.[this.name]) {
|
|
66
|
-
if (debug) console.log("
|
|
65
|
+
if (debug) console.log("MaterialX extension found in root:", gltfExtensions[this.name]);
|
|
67
66
|
|
|
68
67
|
const materialXExtension = gltfExtensions[this.name];
|
|
69
|
-
this.rootMaterialXData = materialXExtension as
|
|
68
|
+
this.rootMaterialXData = materialXExtension as MaterialXData;
|
|
70
69
|
}
|
|
71
70
|
this.rootDataInitialized = true;
|
|
72
71
|
}
|
|
@@ -80,13 +79,13 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
80
79
|
this.documentParsePromise = (async () => {
|
|
81
80
|
if (this.parsedDocument) return this.parsedDocument;
|
|
82
81
|
|
|
83
|
-
if (debug) console.log("
|
|
82
|
+
if (debug) console.log("Parsing MaterialX root document...");
|
|
84
83
|
|
|
85
84
|
// Ensure MaterialX is initialized
|
|
86
|
-
await
|
|
85
|
+
await initializeMaterialX();
|
|
87
86
|
|
|
88
87
|
if (!state.materialXModule) {
|
|
89
|
-
throw new Error("
|
|
88
|
+
throw new Error("MaterialX module failed to initialize");
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
// Create MaterialX document and parse ALL the XML data from root
|
|
@@ -95,11 +94,11 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
95
94
|
|
|
96
95
|
// Parse all MaterialX XML strings from the root data
|
|
97
96
|
if (this.rootMaterialXData) {
|
|
98
|
-
if (debug) console.log(`
|
|
97
|
+
if (debug) console.log(`Parsing MaterialX XML for: ${this.rootMaterialXData.name}`);
|
|
99
98
|
await state.materialXModule.readFromXmlString(doc, this.rootMaterialXData.mtlx, "");
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
if (debug) console.log("
|
|
101
|
+
if (debug) console.log("MaterialX root document parsed successfully");
|
|
103
102
|
|
|
104
103
|
this.parsedDocument = doc;
|
|
105
104
|
return doc;
|
|
@@ -123,10 +122,10 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
123
122
|
this.initializeRootData();
|
|
124
123
|
|
|
125
124
|
const materialDef = this.parser.json.materials?.[materialIndex];
|
|
126
|
-
if (debug) console.log("
|
|
125
|
+
if (debug) console.log("MaterialX extension found in material:", materialDef.extensions[this.name]);
|
|
127
126
|
|
|
128
127
|
// Handle different types of MaterialX data
|
|
129
|
-
const dataIndex = materialDef.extensions[this.name] as
|
|
128
|
+
const dataIndex = materialDef.extensions[this.name] as MaterialXDataIndex;
|
|
130
129
|
|
|
131
130
|
if (dataIndex) {
|
|
132
131
|
// Create a new material and process MaterialX - AWAIT THIS!
|
|
@@ -140,12 +139,12 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
private rootDocument: Promise<any> | null = null;
|
|
143
|
-
private async createMaterialXMaterial(materialXData:
|
|
142
|
+
private async createMaterialXMaterial(materialXData: MaterialXDataIndex): Promise<Material> {
|
|
144
143
|
try {
|
|
145
144
|
if (debug) console.log(`Creating MaterialX material: ${materialXData.name}`);
|
|
146
145
|
|
|
147
146
|
// Ensure MaterialX is initialized and document is parsed
|
|
148
|
-
await
|
|
147
|
+
await initializeMaterialX();
|
|
149
148
|
|
|
150
149
|
if (!this.rootDocument) {
|
|
151
150
|
this.rootDocument = this.parseRootDocument();
|
|
@@ -153,7 +152,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
153
152
|
const doc = await this.rootDocument;
|
|
154
153
|
|
|
155
154
|
if (!state.materialXModule || !state.materialXGenerator || !state.materialXGenContext) {
|
|
156
|
-
console.warn("
|
|
155
|
+
console.warn("MaterialX WASM module not ready, returning fallback material");
|
|
157
156
|
const fallbackMaterial = new MeshStandardMaterial();
|
|
158
157
|
fallbackMaterial.userData.materialX = materialXData;
|
|
159
158
|
fallbackMaterial.name = `MaterialX_Fallback_${materialXData.name}`;
|
|
@@ -164,11 +163,11 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
164
163
|
let renderableElement = null;
|
|
165
164
|
let foundRenderable = false;
|
|
166
165
|
|
|
167
|
-
if (debug) console.log("
|
|
166
|
+
if (debug) console.log("Mtlx doc", doc);
|
|
168
167
|
|
|
169
168
|
// Search for material nodes first (following the reference pattern)
|
|
170
169
|
const materialNodes = doc.getMaterialNodes();
|
|
171
|
-
if (debug) console.log(`
|
|
170
|
+
if (debug) console.log(`Found ${materialNodes.length} material nodes in document`, materialNodes);
|
|
172
171
|
|
|
173
172
|
// Handle both array and vector-like APIs
|
|
174
173
|
const materialNodesLength = materialNodes.length;
|
|
@@ -176,13 +175,13 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
176
175
|
const materialNode = materialNodes[i];
|
|
177
176
|
if (materialNode) {
|
|
178
177
|
const materialName = materialNode.getNamePath();
|
|
179
|
-
if (debug) console.log('
|
|
178
|
+
if (debug) console.log('Scan material: ', i, materialName);
|
|
180
179
|
|
|
181
180
|
// Find the matching material
|
|
182
181
|
if (materialName == materialXData.name) {
|
|
183
182
|
renderableElement = materialNode;
|
|
184
183
|
foundRenderable = true;
|
|
185
|
-
if (debug) console.log('
|
|
184
|
+
if (debug) console.log('-- add material: ', materialName);
|
|
186
185
|
break;
|
|
187
186
|
}
|
|
188
187
|
}
|
|
@@ -236,35 +235,35 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
236
235
|
*/
|
|
237
236
|
|
|
238
237
|
if (!renderableElement) {
|
|
239
|
-
console.warn("
|
|
238
|
+
console.warn("No renderable element found in MaterialX document");
|
|
240
239
|
const fallbackMaterial = new MeshStandardMaterial();
|
|
241
240
|
fallbackMaterial.userData.materialX = materialXData;
|
|
242
241
|
fallbackMaterial.name = `MaterialX_NoRenderable_${materialXData.name}`;
|
|
243
242
|
return fallbackMaterial;
|
|
244
243
|
}
|
|
245
244
|
|
|
246
|
-
if (debug) console.log("
|
|
245
|
+
if (debug) console.log("Using renderable element for shader generation");
|
|
247
246
|
|
|
248
247
|
// Check transparency and set context options like the reference
|
|
249
248
|
let isTransparent = state.materialXModule.isTransparentSurface(renderableElement, state.materialXGenerator.getTarget());
|
|
250
249
|
state.materialXGenContext.getOptions().hwTransparency = isTransparent;
|
|
250
|
+
state.materialXGenContext.getOptions().shaderInterfaceType = state.materialXModule.ShaderInterfaceType.SHADER_INTERFACE_COMPLETE;
|
|
251
|
+
state.materialXGenContext.getOptions().hwSrgbEncodeOutput = true; // Like the reference
|
|
251
252
|
|
|
252
253
|
// Generate shaders using the element's name path
|
|
253
|
-
if (debug) console.log("
|
|
254
|
+
if (debug) console.log("Generating MaterialX shaders...");
|
|
254
255
|
const elementName = (renderableElement as any).getNamePath ? (renderableElement as any).getNamePath() : (renderableElement as any).getName();
|
|
255
256
|
|
|
256
257
|
const shader = state.materialXGenerator.generate(elementName, renderableElement, state.materialXGenContext);
|
|
257
258
|
|
|
258
|
-
// Get vertex and fragment shader source
|
|
259
|
-
// It's added by
|
|
259
|
+
// Get vertex and fragment shader source
|
|
260
|
+
// Remove #version directive for newer js. It's added by RawShaderMaterial glslVersion.
|
|
260
261
|
let vertexShader = shader.getSourceCode("vertex").replace(/^#version.*$/gm, '').trim();
|
|
261
262
|
let fragmentShader = shader.getSourceCode("pixel").replace(/^#version.*$/gm, '').trim();
|
|
262
263
|
|
|
263
264
|
// MaterialX uses different attribute names than js defaults,
|
|
264
265
|
// so we patch the MaterialX shaders to match the js standard names.
|
|
265
|
-
// Otherwise, we'd have to modify the mesh attributes (see
|
|
266
|
-
|
|
267
|
-
// Patch vertexShader
|
|
266
|
+
// Otherwise, we'd have to modify the mesh attributes (see below).
|
|
268
267
|
vertexShader = vertexShader.replace(/\bi_position\b/g, 'position');
|
|
269
268
|
vertexShader = vertexShader.replace(/\bi_normal\b/g, 'normal');
|
|
270
269
|
vertexShader = vertexShader.replace(/\bi_texcoord_0\b/g, 'uv');
|
|
@@ -272,7 +271,6 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
272
271
|
vertexShader = vertexShader.replace(/\bi_tangent\b/g, 'tangent');
|
|
273
272
|
vertexShader = vertexShader.replace(/\bi_color_0\b/g, 'color');
|
|
274
273
|
|
|
275
|
-
// Patch fragmentShader
|
|
276
274
|
fragmentShader = fragmentShader.replace(/\bi_position\b/g, 'position');
|
|
277
275
|
fragmentShader = fragmentShader.replace(/\bi_normal\b/g, 'normal');
|
|
278
276
|
fragmentShader = fragmentShader.replace(/\bi_texcoord_0\b/g, 'uv');
|
|
@@ -280,30 +278,19 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
280
278
|
fragmentShader = fragmentShader.replace(/\bi_tangent\b/g, 'tangent');
|
|
281
279
|
fragmentShader = fragmentShader.replace(/\bi_color_0\b/g, 'color');
|
|
282
280
|
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
vertexShader = vertexShader.replace(/texcoord_0 = uv;/g, 'texcoord_0 = vec3(uv, 0.0);');
|
|
294
|
-
|
|
295
|
-
// Add tonemapping and colorspace handling
|
|
296
|
-
// Replace `out vec4 out1;` with `out vec4 gl_FragColor;`
|
|
297
|
-
fragmentShader = fragmentShader.replace(/out\s+vec4\s+out1;/, 'layout(location = 0) out vec4 pc_fragColor;\n#define gl_FragColor pc_fragColor');
|
|
298
|
-
// Replace `out1 = vec4(<CAPTURE>)` with `gl_FragColor = vec4(<CAPTURE>)` and tonemapping/colorspace handling
|
|
299
|
-
fragmentShader = fragmentShader.replace(/^\s*out1\s*=\s*vec4\((.*)\);/gm,
|
|
300
|
-
`
|
|
301
|
-
gl_FragColor = vec4($1);
|
|
302
|
-
#include <tonemapping_fragment>
|
|
303
|
-
#include <colorspace_fragment>`);
|
|
281
|
+
// From the original code:
|
|
282
|
+
|
|
283
|
+
/* PATCHING THE SHADER IS BETTER – THIS IS JUST FOR REFERENCE
|
|
284
|
+
// Use default MaterialX naming convention.
|
|
285
|
+
var startStreamTime = performance.now();
|
|
286
|
+
child.geometry.attributes.i_position = child.geometry.attributes.position;
|
|
287
|
+
child.geometry.attributes.i_normal = child.geometry.attributes.normal;
|
|
288
|
+
child.geometry.attributes.i_tangent = child.geometry.attributes.tangent;
|
|
289
|
+
child.geometry.attributes.i_texcoord_0 = child.geometry.attributes.uv;
|
|
290
|
+
*/
|
|
304
291
|
|
|
305
292
|
if (debug) {
|
|
306
|
-
console.group("
|
|
293
|
+
console.group("Material: ", materialXData.name);
|
|
307
294
|
console.log("Vertex shader length:", vertexShader.length, vertexShader);
|
|
308
295
|
console.log("Fragment shader length:", fragmentShader.length, fragmentShader);
|
|
309
296
|
console.groupEnd();
|
|
@@ -342,17 +329,17 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
342
329
|
const textures = ext?.textures || [];
|
|
343
330
|
|
|
344
331
|
const index = textures.findIndex(tex => {
|
|
345
|
-
if (debug) console.log("
|
|
332
|
+
if (debug) console.log("Checking texture:", tex.name, "against URL:", filenameWithoutExt);
|
|
346
333
|
return tex.name === filenameWithoutExt;
|
|
347
334
|
});
|
|
348
335
|
|
|
349
336
|
if (index < 0) {
|
|
350
|
-
console.warn("
|
|
337
|
+
console.warn("Texture not found in parser:", filenameWithoutExt, this.parser.json);
|
|
351
338
|
onError?.(new Error(`Texture not found: ${filenameWithoutExt}`));
|
|
352
339
|
return;
|
|
353
340
|
}
|
|
354
341
|
this.parser.getDependency("texture", index).then(tex => {
|
|
355
|
-
if (debug) console.log("
|
|
342
|
+
if (debug) console.log("Texture loaded:", tex);
|
|
356
343
|
// update the checkerboard texture with the loaded texture
|
|
357
344
|
checkerboardTexture.image = tex.image;
|
|
358
345
|
checkerboardTexture.needsUpdate = true;
|
|
@@ -397,7 +384,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
397
384
|
}
|
|
398
385
|
|
|
399
386
|
const mips = Math.trunc(Math.log2(Math.max(radianceTexture?.width ?? 0, radianceTexture?.height ?? 0))) + 1;
|
|
400
|
-
if (debug) console.log("
|
|
387
|
+
if (debug) console.log("Radiance texture mips:", mips, "for texture size:", radianceTexture?.width, "x", radianceTexture?.height);
|
|
401
388
|
Object.assign(uniforms, {
|
|
402
389
|
u_envMatrix: { value: getLightRotation() },
|
|
403
390
|
u_envRadiance: { value: radianceTexture, type: 't' },
|
|
@@ -415,7 +402,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
415
402
|
// console.log("Generated fragment shader:", fragmentShader.substring(0, 500) + "...");
|
|
416
403
|
|
|
417
404
|
// Create js RawShaderMaterial (with GLSL3 for MaterialX compatibility)
|
|
418
|
-
const shaderMaterial = new
|
|
405
|
+
const shaderMaterial = new RawShaderMaterial({
|
|
419
406
|
uniforms: uniforms,
|
|
420
407
|
vertexShader: vertexShader,
|
|
421
408
|
fragmentShader: fragmentShader,
|
|
@@ -486,7 +473,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
486
473
|
shaderMaterial.name = `MaterialX_Generated_${materialXData.name}`;
|
|
487
474
|
|
|
488
475
|
// Add debugging to see if the material compiles correctly
|
|
489
|
-
if (debug) console.log("
|
|
476
|
+
if (debug) console.log("MaterialX material created successfully:", shaderMaterial.name);
|
|
490
477
|
// if (debug) console.log("Material uniforms keys:", Object.keys(shaderMaterial.uniforms || {}));
|
|
491
478
|
// if (debug) console.log("Material transparent:", shaderMaterial.transparent);
|
|
492
479
|
// if (debug) console.log("Material side:", shaderMaterial.side);
|
|
@@ -498,7 +485,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
498
485
|
|
|
499
486
|
} catch (error) {
|
|
500
487
|
// This is a wasm error (an int) that we need to resolve
|
|
501
|
-
console.error("
|
|
488
|
+
console.error("Error creating MaterialX material:", error);
|
|
502
489
|
// Return a fallback material with stored MaterialX data
|
|
503
490
|
const fallbackMaterial = new MeshStandardMaterial();
|
|
504
491
|
fallbackMaterial.userData.materialX = materialXData;
|
|
@@ -512,12 +499,12 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
512
499
|
updateLightingFromEnvironment(environment: MaterialXEnvironment): void {
|
|
513
500
|
|
|
514
501
|
// Get lighting data from environment
|
|
502
|
+
// const lights = environment.getLights() || [];
|
|
515
503
|
const lightData = environment.getLightData() || null;
|
|
516
|
-
const lightCount = environment.getLightCount() || 0;
|
|
517
504
|
const radianceTexture = environment.getRadianceTexture() || null;
|
|
518
505
|
const irradianceTexture = environment.getIrradianceTexture() || null;
|
|
519
506
|
|
|
520
|
-
if (debug) console.log(`
|
|
507
|
+
if (debug) console.log(`Updating lighting for ${this.generatedMaterials.length} MaterialX materials`, {
|
|
521
508
|
lightData, radianceTexture, irradianceTexture,
|
|
522
509
|
});
|
|
523
510
|
|
|
@@ -526,8 +513,8 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
526
513
|
if (!material.uniforms) return;
|
|
527
514
|
|
|
528
515
|
// Update light count
|
|
529
|
-
if (material.uniforms.u_numActiveLightSources &&
|
|
530
|
-
material.uniforms.u_numActiveLightSources.value =
|
|
516
|
+
if (material.uniforms.u_numActiveLightSources && lightData) {
|
|
517
|
+
material.uniforms.u_numActiveLightSources.value = lightData.length;
|
|
531
518
|
}
|
|
532
519
|
|
|
533
520
|
// Update light data if we have lights
|
|
@@ -536,9 +523,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
536
523
|
material.uniforms.u_lightData = { value: null };
|
|
537
524
|
}
|
|
538
525
|
material.uniforms.u_lightData.value = lightData;
|
|
539
|
-
if (debug) console.log("[MaterialX] Updated light data for material", material.name, lightData, material.uniforms,);
|
|
540
526
|
}
|
|
541
|
-
else if(debug) console.warn("[MaterialX] No light data available to update uniforms for material", material.name);
|
|
542
527
|
|
|
543
528
|
// Update environment uniforms
|
|
544
529
|
if (material.uniforms.u_envMatrix) {
|
package/src/materialx.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { Context, delay, isDevEnvironment, ObjectUtils
|
|
1
|
+
import { Context, delay, isDevEnvironment, ObjectUtils } from "@needle-tools/engine";
|
|
2
2
|
import MaterialX from "../bin/JsMaterialXGenShader.js";
|
|
3
3
|
import { debug } from "./utils.js";
|
|
4
4
|
import { renderPMREMToEquirect } from "./textureHelper.js";
|
|
5
|
-
import { Light, MeshBasicMaterial, Object3D, PMREMGenerator
|
|
5
|
+
import { Light, MeshBasicMaterial, Object3D, PMREMGenerator } from "three";
|
|
6
6
|
import { registerLights } from "./helper.js";
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
// Global MaterialX module instance - initialized lazily
|
|
9
10
|
export const state = new class {
|
|
10
|
-
materialXModule:
|
|
11
|
+
materialXModule: any = null;
|
|
11
12
|
materialXGenerator: any = null;
|
|
12
13
|
materialXGenContext: any = null;
|
|
13
14
|
materialXStdLib: any = null;
|
|
@@ -21,14 +22,14 @@ export const state = new class {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
export async function
|
|
25
|
+
// Initialize MaterialX WASM module lazily
|
|
26
|
+
export async function initializeMaterialX(): Promise<void> {
|
|
26
27
|
if (state.materialXInitPromise) {
|
|
27
28
|
return state.materialXInitPromise;
|
|
28
29
|
}
|
|
29
30
|
return state.materialXInitPromise = (async () => {
|
|
30
31
|
if (state.materialXModule) return; // Already initialized
|
|
31
|
-
if (debug) console.log("
|
|
32
|
+
if (debug) console.log("Initializing MaterialX WASM module...");
|
|
32
33
|
try {
|
|
33
34
|
|
|
34
35
|
const urls: Array<string> = await Promise.all([
|
|
@@ -43,7 +44,7 @@ export async function ready(): Promise<void> {
|
|
|
43
44
|
|
|
44
45
|
const module = await MaterialX({
|
|
45
46
|
locateFile: (path: string, scriptDirectory: string) => {
|
|
46
|
-
if (debug) console.debug("
|
|
47
|
+
if (debug) console.debug("MaterialX locateFile called:", { path, scriptDirectory });
|
|
47
48
|
|
|
48
49
|
if (path.includes("JsMaterialXCore.wasm")) {
|
|
49
50
|
return JsMaterialXCore; // Use the URL for the core WASM file
|
|
@@ -58,7 +59,7 @@ export async function ready(): Promise<void> {
|
|
|
58
59
|
return scriptDirectory + path;
|
|
59
60
|
},
|
|
60
61
|
});
|
|
61
|
-
if (debug) console.log("
|
|
62
|
+
if (debug) console.log("MaterialXLoader module loaded", module);
|
|
62
63
|
state.materialXModule = module;
|
|
63
64
|
|
|
64
65
|
// Initialize shader generator and context
|
|
@@ -70,36 +71,23 @@ export async function ready(): Promise<void> {
|
|
|
70
71
|
state.materialXStdLib = module.loadStandardLibraries(state.materialXGenContext);
|
|
71
72
|
tempDoc.setDataLibrary(state.materialXStdLib);
|
|
72
73
|
|
|
73
|
-
//
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
// TRANSMISSION_OPACITY: Use opacity for transmission rendering.
|
|
84
|
-
// state.materialXGenContext.getOptions().hwTransmissionRenderMethod = state.materialXModule.HwTransmissionRenderMethod.TRANSMISSION_REFRACTION;
|
|
85
|
-
|
|
86
|
-
// Turned off because we're doing color space conversion the three.js way
|
|
87
|
-
state.materialXGenContext.getOptions().hwSrgbEncodeOutput = false;
|
|
88
|
-
|
|
89
|
-
// Enables the generation of a prefiltered environment map.
|
|
90
|
-
// TODO Would be great to use but requires setting more uniforms (like u_envPrefilterMip).
|
|
91
|
-
// When set to true, the u_envRadiance map is expected to be a prefiltered environment map.
|
|
92
|
-
// state.materialXGenContext.getOptions().hwWriteEnvPrefilter = true;
|
|
93
|
-
|
|
94
|
-
// Set a reasonable default for max active lights
|
|
95
|
-
state.materialXGenContext.getOptions().hwMaxActiveLightSources = 4;
|
|
74
|
+
// Initialize basic lighting with default light rig
|
|
75
|
+
// const defaultLightRigXml = `<?xml version="1.0"?>
|
|
76
|
+
// <materialx version="1.39">
|
|
77
|
+
// <!-- Default directional light -->
|
|
78
|
+
// <directional_light name="default_light" type="lightshader">
|
|
79
|
+
// <input name="direction" type="vector3" value="0.0, -1.0, -0.5" />
|
|
80
|
+
// <input name="color" type="color3" value="1.0, 1.0, 1.0" />
|
|
81
|
+
// <input name="intensity" type="float" value="1.0" />
|
|
82
|
+
// </directional_light>
|
|
83
|
+
// </materialx>`;
|
|
96
84
|
|
|
97
85
|
// This prewarms the shader generation context to have all light types
|
|
98
86
|
await registerLights(state.materialXModule, [], state.materialXGenContext);
|
|
99
87
|
|
|
100
|
-
if (debug) console.log("
|
|
88
|
+
if (debug) console.log("MaterialX generator initialized successfully");
|
|
101
89
|
} catch (error) {
|
|
102
|
-
console.error("
|
|
90
|
+
console.error("Failed to load MaterialX module:", error);
|
|
103
91
|
throw error;
|
|
104
92
|
}
|
|
105
93
|
})();
|
|
@@ -107,79 +95,67 @@ export async function ready(): Promise<void> {
|
|
|
107
95
|
|
|
108
96
|
// MaterialX Environment Manager - handles lighting and environment setup
|
|
109
97
|
export class MaterialXEnvironment {
|
|
110
|
-
private
|
|
111
|
-
private
|
|
112
|
-
private
|
|
113
|
-
private
|
|
114
|
-
private
|
|
115
|
-
private
|
|
98
|
+
private lights: any[] = [];
|
|
99
|
+
private lightData: any = null;
|
|
100
|
+
private radianceTexture: any = null;
|
|
101
|
+
private irradianceTexture: any = null;
|
|
102
|
+
private context: Context | null = null;
|
|
103
|
+
private initialized: boolean = false;
|
|
116
104
|
|
|
117
105
|
constructor() {
|
|
118
|
-
if (debug) console.log("
|
|
106
|
+
if (debug) console.log("MaterialX Environment created");
|
|
119
107
|
}
|
|
120
108
|
|
|
121
|
-
|
|
122
|
-
|
|
109
|
+
setContext(context: Context) {
|
|
110
|
+
this.context = context;
|
|
111
|
+
}
|
|
123
112
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
/*
|
|
114
|
+
// Initialize MaterialX lighting system based on the reference implementation
|
|
115
|
+
async initializeLighting(lightRigXml: string, renderer?: any, radianceTexture?: any, irradianceTexture?: any): Promise<void> {
|
|
116
|
+
if (!materialXModule || !materialXGenContext) {
|
|
117
|
+
console.warn("MaterialX module not initialized, skipping lighting setup");
|
|
118
|
+
return;
|
|
128
119
|
}
|
|
129
120
|
|
|
130
|
-
|
|
121
|
+
registerLights(materialXModule, this.lights, materialXGenContext);
|
|
131
122
|
}
|
|
123
|
+
*/
|
|
132
124
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
getIrradianceTexture() { return this._irradianceTexture; }
|
|
140
|
-
setIrradianceTexture(texture: Texture) { this._irradianceTexture = texture; }
|
|
141
|
-
|
|
142
|
-
// Reset the environment to allow re-initialization
|
|
143
|
-
reset() {
|
|
144
|
-
if (debug) console.log("[MaterialX] Resetting environment");
|
|
145
|
-
if (this._radianceTexture) {
|
|
146
|
-
this._radianceTexture.dispose();
|
|
147
|
-
this._radianceTexture = null;
|
|
148
|
-
}
|
|
149
|
-
if (this._irradianceTexture) {
|
|
150
|
-
this._irradianceTexture.dispose();
|
|
151
|
-
this._irradianceTexture = null;
|
|
125
|
+
// Initialize with Needle Engine context
|
|
126
|
+
async initializeFromContext(): Promise<void> {
|
|
127
|
+
if (!this.context) {
|
|
128
|
+
console.warn("No Needle context available for MaterialX environment initialization");
|
|
129
|
+
return;
|
|
152
130
|
}
|
|
153
|
-
this._initializePromise = null;
|
|
154
|
-
// this.lights = [];
|
|
155
|
-
this._lightData = null;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
private _initialize: (context: Context) => Promise<boolean> = async (context: Context) => {
|
|
159
131
|
|
|
160
|
-
|
|
132
|
+
// Prevent multiple initializations
|
|
133
|
+
if (this.initialized) {
|
|
134
|
+
if (debug) console.log("MaterialX environment already initialized, skipping");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
161
137
|
|
|
162
138
|
// Clean up previous textures if they exist
|
|
163
|
-
if (this.
|
|
164
|
-
if (debug) console.log("
|
|
165
|
-
this.
|
|
166
|
-
this.
|
|
139
|
+
if (this.radianceTexture) {
|
|
140
|
+
if (debug) console.log("Disposing previous radiance texture");
|
|
141
|
+
this.radianceTexture.dispose();
|
|
142
|
+
this.radianceTexture = null;
|
|
167
143
|
}
|
|
168
|
-
if (this.
|
|
169
|
-
if (debug) console.log("
|
|
170
|
-
this.
|
|
171
|
-
this.
|
|
144
|
+
if (this.irradianceTexture) {
|
|
145
|
+
if (debug) console.log("Disposing previous irradiance texture");
|
|
146
|
+
this.irradianceTexture.dispose();
|
|
147
|
+
this.irradianceTexture = null;
|
|
172
148
|
}
|
|
173
149
|
|
|
174
150
|
// Get renderer from context
|
|
175
|
-
const renderer = this.
|
|
151
|
+
const renderer = this.context.renderer;
|
|
176
152
|
|
|
177
153
|
// TODO remove this delay; we should wait for the scene lighting to be ready
|
|
178
154
|
// and then update the uniforms
|
|
179
|
-
let envMap = this.
|
|
155
|
+
let envMap = this.context.scene.environment;
|
|
180
156
|
while (!envMap) {
|
|
181
157
|
await delay(200);
|
|
182
|
-
envMap = this.
|
|
158
|
+
envMap = this.context.scene.environment;
|
|
183
159
|
}
|
|
184
160
|
var pmrem = new PMREMGenerator(renderer);
|
|
185
161
|
const target = pmrem.fromEquirectangular(envMap);
|
|
@@ -187,42 +163,66 @@ export class MaterialXEnvironment {
|
|
|
187
163
|
const radianceRenderTarget = renderPMREMToEquirect(renderer, target.texture, 0.0, 1024, 512, target.height);
|
|
188
164
|
const irradianceRenderTarget = renderPMREMToEquirect(renderer, target.texture, 1.0, 32, 16, target.height);
|
|
189
165
|
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
166
|
+
this.radianceTexture = radianceRenderTarget.texture;
|
|
167
|
+
this.irradianceTexture = irradianceRenderTarget.texture;
|
|
192
168
|
|
|
193
169
|
// Clean up PMREM generator and its render target
|
|
194
170
|
target.dispose();
|
|
195
171
|
pmrem.dispose();
|
|
196
172
|
|
|
197
173
|
if (debug) {
|
|
198
|
-
console.log({ radiance: this.
|
|
174
|
+
console.log({ radiance: this.radianceTexture, irradiance: this.irradianceTexture });
|
|
199
175
|
// Show both of them on cubes in the scene
|
|
200
176
|
const unlitMat = new MeshBasicMaterial();
|
|
201
|
-
unlitMat.side = 2;
|
|
202
177
|
const radianceMat = unlitMat.clone();
|
|
203
|
-
radianceMat.map = this.
|
|
204
|
-
const radianceCube = ObjectUtils.createPrimitive("
|
|
178
|
+
radianceMat.map = this.radianceTexture;
|
|
179
|
+
const radianceCube = ObjectUtils.createPrimitive("Cube", { material: radianceMat });
|
|
205
180
|
const irradianceMat = unlitMat.clone();
|
|
206
|
-
irradianceMat.map = this.
|
|
207
|
-
const irradianceCube = ObjectUtils.createPrimitive("
|
|
208
|
-
this.
|
|
209
|
-
this.
|
|
181
|
+
irradianceMat.map = this.irradianceTexture;
|
|
182
|
+
const irradianceCube = ObjectUtils.createPrimitive("Cube", { material: irradianceMat });
|
|
183
|
+
this.context.scene.add(radianceCube);
|
|
184
|
+
this.context.scene.add(irradianceCube);
|
|
210
185
|
radianceCube.position.set(2, 0, 0);
|
|
186
|
+
radianceCube.scale.y = 0.00001;
|
|
211
187
|
irradianceCube.position.set(-2, 0, 0);
|
|
188
|
+
irradianceCube.scale.y = 0.00001;
|
|
212
189
|
// await this.initializeLighting(defaultLightRigXml, renderer);
|
|
213
|
-
console.log("
|
|
190
|
+
console.log("MaterialX environment initialized from Needle context", this, this.context.scene);
|
|
214
191
|
}
|
|
215
192
|
|
|
216
193
|
// Find lights in scene
|
|
217
194
|
let lights = new Array<Light>();
|
|
218
|
-
this.
|
|
219
|
-
if ((object as Light).isLight
|
|
220
|
-
lights.push(object as Light);
|
|
195
|
+
this.context.scene.traverse((object: Object3D) => {
|
|
196
|
+
if ((object as Light).isLight) lights.push(object as Light);
|
|
221
197
|
});
|
|
222
198
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
199
|
+
this.lightData = await registerLights(state.materialXModule, lights, state.materialXGenContext);
|
|
200
|
+
|
|
201
|
+
// Mark as initialized
|
|
202
|
+
this.initialized = true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// getLights() { return this.lights; }
|
|
206
|
+
getLightData() { return this.lightData; }
|
|
207
|
+
getRadianceTexture() { return this.radianceTexture; }
|
|
208
|
+
getIrradianceTexture() { return this.irradianceTexture; }
|
|
209
|
+
|
|
210
|
+
setRadianceTexture(texture: any) { this.radianceTexture = texture; }
|
|
211
|
+
setIrradianceTexture(texture: any) { this.irradianceTexture = texture; }
|
|
212
|
+
|
|
213
|
+
// Reset the environment to allow re-initialization
|
|
214
|
+
reset() {
|
|
215
|
+
if (debug) console.log("Resetting MaterialX environment");
|
|
216
|
+
if (this.radianceTexture) {
|
|
217
|
+
this.radianceTexture.dispose();
|
|
218
|
+
this.radianceTexture = null;
|
|
219
|
+
}
|
|
220
|
+
if (this.irradianceTexture) {
|
|
221
|
+
this.irradianceTexture.dispose();
|
|
222
|
+
this.irradianceTexture = null;
|
|
223
|
+
}
|
|
224
|
+
this.initialized = false;
|
|
225
|
+
// this.lights = [];
|
|
226
|
+
this.lightData = null;
|
|
227
227
|
}
|
|
228
228
|
}
|