@needle-tools/materialx 1.0.4-next.8713311 → 1.0.4-next.a95b900
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/index.ts +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -5
- package/src/loader/loader.needle.ts +10 -52
- package/src/loader/loader.three.ts +5 -11
- package/src/materialx.helper.ts +1 -1
- package/src/materialx.material.ts +30 -19
- package/src/materialx.ts +81 -83
package/index.ts
CHANGED
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export { ready, getMaterialXEnvironment };
|
|
1
|
+
export { ready, type MaterialXContext } from "./materialx.js";
|
|
2
|
+
export { MaterialXMaterial } from "./materialx.material.js";
|
|
3
|
+
export { MaterialXLoader } from "./loader/loader.three.js";
|
|
4
|
+
export { registerNeedleLoader } from "./loader/loader.needle.js";
|
|
@@ -1,46 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { Context, GLTF, addCustomExtensionPlugin, Component, INeedleGLTFExtensionPlugin } from "@needle-tools/engine";
|
|
3
|
+
import { Context, GLTF, addCustomExtensionPlugin, INeedleGLTFExtensionPlugin } from "@needle-tools/engine";
|
|
5
4
|
import type { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
6
5
|
import type { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
7
6
|
import { MaterialXLoader } from "./loader.three.js";
|
|
8
7
|
import { debug } from "../utils.js";
|
|
9
|
-
import { MaterialXEnvironment, state } from "../materialx.js";
|
|
10
|
-
import { MaterialXMaterial } from "../materialx.material.js";
|
|
11
|
-
|
|
12
|
-
//@dont-generate-component
|
|
13
|
-
export class MaterialXUniformUpdate extends Component {
|
|
14
|
-
|
|
15
|
-
onEnable(): void {
|
|
16
|
-
this.context.addBeforeRenderListener(this.gameObject, this.onBeforeRenderThree);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
onDisable(): void {
|
|
20
|
-
this.context.removeBeforeRenderListener(this.gameObject, this.onBeforeRenderThree);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
onBeforeRenderThree = () => {
|
|
24
|
-
// Update uniforms or perform any pre-render logic here
|
|
25
|
-
const gameObject = this.gameObject as any as Mesh;
|
|
26
|
-
const material = gameObject?.material;
|
|
27
|
-
|
|
28
|
-
const camera = this.context.mainCamera;
|
|
29
|
-
if (!camera) return;
|
|
30
|
-
|
|
31
|
-
const env = state.materialXEnvironment;
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(material)) {
|
|
34
|
-
for (const entry of material) {
|
|
35
|
-
if (entry && entry instanceof MaterialXMaterial) {
|
|
36
|
-
entry.updateUniforms(this.context, env, this.gameObject, camera);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
} else if (material instanceof MaterialXMaterial) {
|
|
40
|
-
material.updateUniforms(this.context, env, this.gameObject, camera);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
8
|
|
|
45
9
|
export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
46
10
|
readonly name = "MaterialXLoaderPlugin";
|
|
@@ -53,7 +17,12 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
53
17
|
// Register the MaterialX loader extension
|
|
54
18
|
// Environment initialization is now handled in the MaterialXLoader constructor
|
|
55
19
|
loader.register(p => {
|
|
56
|
-
this.loader = new MaterialXLoader(p, url,
|
|
20
|
+
this.loader = new MaterialXLoader(p, url, {
|
|
21
|
+
getTime: () => context.time.time,
|
|
22
|
+
getFrame: ()=> context.time.frame,
|
|
23
|
+
getScene: () => context.scene,
|
|
24
|
+
getRenderer: () => context.renderer,
|
|
25
|
+
});
|
|
57
26
|
return this.loader;
|
|
58
27
|
});
|
|
59
28
|
};
|
|
@@ -65,25 +34,14 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
65
34
|
if (!this.loader?.materialX_root_data) {
|
|
66
35
|
return;
|
|
67
36
|
}
|
|
68
|
-
// Set up onBeforeRender callbacks for objects with MaterialX materials
|
|
69
|
-
// This ensures uniforms are updated properly during rendering
|
|
70
|
-
gltf.scene.traverse((child) => {
|
|
71
|
-
if ((child as any).isMesh) {
|
|
72
|
-
const mesh = child as Mesh;
|
|
73
|
-
const material = mesh.material as Material;
|
|
74
|
-
|
|
75
|
-
if (material instanceof MaterialXMaterial) {
|
|
76
|
-
if (debug) console.log("[MaterialX] Adding MaterialX uniform update component to:", child.name);
|
|
77
|
-
child.addComponent(MaterialXUniformUpdate);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
37
|
|
|
82
38
|
if (debug) console.log("[MaterialX] Loaded: ", this.loader);
|
|
39
|
+
|
|
40
|
+
|
|
83
41
|
};
|
|
84
42
|
|
|
85
43
|
onExport = (_exporter: GLTFExporter, _context: Context) => {
|
|
86
|
-
console.
|
|
44
|
+
console.warn("[MaterialX] Export is not supported");
|
|
87
45
|
// TODO: Add MaterialX export functionality if needed
|
|
88
46
|
};
|
|
89
47
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { ready, MaterialXEnvironment, state } from "../materialx.js";
|
|
1
|
+
import { Material, MeshStandardMaterial, DoubleSide, FrontSide } from "three";
|
|
2
|
+
import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
3
|
+
import { ready, state, MaterialXContext } from "../materialx.js";
|
|
5
4
|
import { debug } from "../utils.js";
|
|
6
5
|
import { MaterialXMaterial } from "../materialx.material.js";
|
|
7
6
|
|
|
@@ -52,7 +51,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
52
51
|
* @param url The URL of the GLTF file
|
|
53
52
|
* @param context The context for the GLTF loading process
|
|
54
53
|
*/
|
|
55
|
-
constructor(private parser: GLTFParser, private url: string, private context:
|
|
54
|
+
constructor(private parser: GLTFParser, private url: string, private context: MaterialXContext) {
|
|
56
55
|
if (debug) console.log("MaterialXLoader created for parser");
|
|
57
56
|
// Start loading of MaterialX environment if the root extension exists
|
|
58
57
|
if (this.materialX_root_data) {
|
|
@@ -69,12 +68,6 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
69
68
|
return this._loadMaterialAsync(materialIndex);
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
afterRoot = async (_gltf: GLTF) => {
|
|
73
|
-
// Initialize MaterialX lighting system with scene data
|
|
74
|
-
const environment = state.materialXEnvironment;
|
|
75
|
-
environment.initialize(this.context);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
71
|
// Parse the MaterialX document once and cache it
|
|
79
72
|
private async _materialXDocumentReady(): Promise<any> {
|
|
80
73
|
if (this._documentReadyPromise) {
|
|
@@ -238,6 +231,7 @@ export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
|
238
231
|
shader,
|
|
239
232
|
transparent: isTransparent,
|
|
240
233
|
side: material_def.doubleSided ? DoubleSide : FrontSide,
|
|
234
|
+
context: this.context,
|
|
241
235
|
loaders: {
|
|
242
236
|
cacheKey: this.url,
|
|
243
237
|
getTexture: async url => {
|
package/src/materialx.helper.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
//
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { getWorldDirection } from '@needle-tools/engine';
|
|
7
7
|
import * as THREE from 'three';
|
|
8
8
|
import { debug, debugUpdate } from './utils';
|
|
9
9
|
import { MaterialX } from './materialx.types';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BufferGeometry, Camera, FrontSide, GLSL3, Group, IUniform, MaterialParameters, Matrix3, Matrix4, Object3D, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
|
|
2
2
|
import { debug } from "./utils.js";
|
|
3
|
-
import { MaterialXEnvironment } from "./materialx.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Context } from "@needle-tools/engine";
|
|
3
|
+
import { MaterialXContext, MaterialXEnvironment } from "./materialx.js";
|
|
4
|
+
import { getUniformValues, Loaders } from "./materialx.helper.js";
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
// Add helper matrices for uniform updates (similar to MaterialX example)
|
|
@@ -17,21 +16,20 @@ declare type MaterialXMaterialInitParameters = {
|
|
|
17
16
|
loaders: Loaders,
|
|
18
17
|
transparent?: boolean,
|
|
19
18
|
side?: MaterialParameters['side'],
|
|
19
|
+
context: MaterialXContext,
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
type Uniforms = Record<string, IUniform & { needsUpdate?: boolean }>;
|
|
23
23
|
|
|
24
24
|
export class MaterialXMaterial extends ShaderMaterial {
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// return this;
|
|
34
|
-
// }
|
|
26
|
+
copy(source: MaterialXMaterial): this {
|
|
27
|
+
super.copy(source);
|
|
28
|
+
this._context = source._context;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private _context: MaterialXContext | null = null;
|
|
35
33
|
|
|
36
34
|
constructor(init?: MaterialXMaterialInitParameters) {
|
|
37
35
|
|
|
@@ -133,6 +131,8 @@ export class MaterialXMaterial extends ShaderMaterial {
|
|
|
133
131
|
u_lightData: { value: [], needsUpdate: false }, // Array of light data. We need to set needsUpdate to false until we actually update it
|
|
134
132
|
});
|
|
135
133
|
|
|
134
|
+
this._context = init.context;
|
|
135
|
+
|
|
136
136
|
if (debug) {
|
|
137
137
|
// Get lighting and environment data from MaterialX environment
|
|
138
138
|
console.group("[MaterialX]: ", name);
|
|
@@ -140,13 +140,22 @@ export class MaterialXMaterial extends ShaderMaterial {
|
|
|
140
140
|
console.log("Fragment shader length:", fragmentShader.length, fragmentShader);
|
|
141
141
|
console.groupEnd();
|
|
142
142
|
}
|
|
143
|
+
}
|
|
143
144
|
|
|
145
|
+
onBeforeRender(_renderer: WebGLRenderer, _scene: Scene, camera: Camera, _geometry: BufferGeometry, object: Object3D, _group: Group): void {
|
|
146
|
+
if (this._context) {
|
|
147
|
+
const env = MaterialXEnvironment.get(this._context);
|
|
148
|
+
if (env) {
|
|
149
|
+
env.update(this._context.getFrame(), this._context.getScene());
|
|
150
|
+
this.updateUniforms(env, object, camera);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
144
153
|
}
|
|
145
154
|
|
|
146
155
|
|
|
147
156
|
envMapIntensity: number = 1.0; // Default intensity for environment map
|
|
148
157
|
envMap: Texture | null = null; // Environment map texture, can be set externally
|
|
149
|
-
updateUniforms = (
|
|
158
|
+
updateUniforms = (environment: MaterialXEnvironment, object: Object3D, camera: Camera) => {
|
|
150
159
|
|
|
151
160
|
const uniforms = this.uniforms as Uniforms;
|
|
152
161
|
|
|
@@ -176,11 +185,13 @@ export class MaterialXMaterial extends ShaderMaterial {
|
|
|
176
185
|
}
|
|
177
186
|
|
|
178
187
|
// Update time uniforms
|
|
179
|
-
if (
|
|
180
|
-
uniforms.u_time
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
uniforms.u_frame
|
|
188
|
+
if (this._context) {
|
|
189
|
+
if (uniforms.u_time) {
|
|
190
|
+
uniforms.u_time.value = this._context.getTime();
|
|
191
|
+
}
|
|
192
|
+
if (uniforms.u_frame) {
|
|
193
|
+
uniforms.u_frame.value = this._context.getFrame();
|
|
194
|
+
}
|
|
184
195
|
}
|
|
185
196
|
|
|
186
197
|
// Update light uniforms
|
package/src/materialx.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { Context, delay, isDevEnvironment, ObjectUtils, GameObject, onBeforeRender } from "@needle-tools/engine";
|
|
2
1
|
import type { MaterialX as MX } from "./materialx.types.js";
|
|
3
2
|
import MaterialX from "../bin/JsMaterialXGenShader.js";
|
|
4
3
|
import { debug } from "./utils.js";
|
|
5
4
|
import { renderPMREMToEquirect } from "./textureHelper.js";
|
|
6
|
-
import { Light,
|
|
5
|
+
import { Light, Object3D, PMREMGenerator, Scene, Texture, WebGLRenderer } from "three";
|
|
7
6
|
import { registerLights, getLightData, LightData } from "./materialx.helper.js";
|
|
8
7
|
import type { MaterialXMaterial } from "./materialx.material.js";
|
|
9
8
|
|
|
9
|
+
export type MaterialXContext = {
|
|
10
|
+
getTime(): number,
|
|
11
|
+
getFrame(): number,
|
|
12
|
+
getScene(): Scene,
|
|
13
|
+
getRenderer(): WebGLRenderer,
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
|
|
11
17
|
export const state = new class {
|
|
12
18
|
materialXModule: MX.MODULE | null = null;
|
|
@@ -14,16 +20,12 @@ export const state = new class {
|
|
|
14
20
|
materialXGenContext: any = null;
|
|
15
21
|
materialXStdLib: any = null;
|
|
16
22
|
materialXInitPromise: Promise<void> | null = null;
|
|
17
|
-
|
|
18
|
-
// Global MaterialX environment instance
|
|
19
|
-
private _materialXEnvironment: MaterialXEnvironment | null = null;
|
|
20
|
-
get materialXEnvironment() {
|
|
21
|
-
this._materialXEnvironment ??= new MaterialXEnvironment();
|
|
22
|
-
return this._materialXEnvironment;
|
|
23
|
-
}
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Wait for the MaterialX WASM module to be ready.
|
|
28
|
+
*/
|
|
27
29
|
export async function ready(): Promise<void> {
|
|
28
30
|
if (state.materialXInitPromise) {
|
|
29
31
|
return state.materialXInitPromise;
|
|
@@ -111,93 +113,72 @@ type EnvironmentTextureSet = {
|
|
|
111
113
|
irradianceTexture: Texture | null;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
type EnvironmentContext = Pick<MaterialXContext, "getRenderer" | "getScene">;
|
|
119
|
+
/**
|
|
120
|
+
* MaterialXEnvironment manages the environment settings for MaterialX materials.
|
|
121
|
+
*/
|
|
115
122
|
export class MaterialXEnvironment {
|
|
116
|
-
|
|
123
|
+
|
|
124
|
+
static get(context: EnvironmentContext): MaterialXEnvironment | null {
|
|
125
|
+
return this.getEnvironment(context);
|
|
126
|
+
}
|
|
127
|
+
private static _environments: WeakMap<EnvironmentContext, MaterialXEnvironment> = new Map();
|
|
128
|
+
private static getEnvironment(context: EnvironmentContext): MaterialXEnvironment {
|
|
129
|
+
if (this._environments.has(context)) {
|
|
130
|
+
return this._environments.get(context)!;
|
|
131
|
+
}
|
|
132
|
+
const env = new MaterialXEnvironment(context);
|
|
133
|
+
this._environments.set(context, env);
|
|
134
|
+
return env;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
117
138
|
private _lights: Array<Light> = [];
|
|
118
139
|
private _lightData: null | LightData[] = null;
|
|
119
140
|
private _lightCount: number = 0;
|
|
120
|
-
private _initializePromise: Promise<boolean> | null = null;
|
|
121
141
|
|
|
122
|
-
private
|
|
142
|
+
private _initializePromise: Promise<boolean> | null = null;
|
|
143
|
+
private _isInitialized: boolean = false;
|
|
144
|
+
private _lastUpdateFrame: number = -1;
|
|
123
145
|
|
|
124
|
-
constructor() {
|
|
146
|
+
constructor(private _context: EnvironmentContext) {
|
|
125
147
|
if (debug) console.log("[MaterialX] Environment created");
|
|
126
148
|
}
|
|
127
149
|
|
|
128
150
|
// Initialize with Needle Engine context
|
|
129
|
-
async initialize(
|
|
151
|
+
async initialize(): Promise<boolean> {
|
|
130
152
|
if (this._initializePromise) {
|
|
131
153
|
return this._initializePromise;
|
|
132
154
|
}
|
|
133
|
-
|
|
155
|
+
this._initializePromise = this._initialize();
|
|
156
|
+
return this._initializePromise;
|
|
134
157
|
}
|
|
135
158
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// }
|
|
141
|
-
return this._lightData;
|
|
142
|
-
}
|
|
143
|
-
get lightCount() { return this._lightCount || 0; }
|
|
144
|
-
getTextures(material: MaterialXMaterial) {
|
|
145
|
-
if (material.envMap) {
|
|
146
|
-
// If the material has its own envMap, we don't use the irradiance texture
|
|
147
|
-
return this._getTextures(material.envMap);
|
|
159
|
+
update(frame: number, scene: Scene) {
|
|
160
|
+
if (!this._initializePromise) {
|
|
161
|
+
this.initialize();
|
|
162
|
+
return;
|
|
148
163
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
private _pmremGenerator: PMREMGenerator | null = null;
|
|
153
|
-
private readonly _texturesCache: Map<Texture | null, EnvironmentTextureSet> = new Map();
|
|
154
|
-
|
|
155
|
-
private _initialize: (context: Context) => Promise<boolean> = async (context: Context) => {
|
|
156
|
-
|
|
157
|
-
this._context = context;
|
|
158
|
-
this._pmremGenerator = new PMREMGenerator(context.renderer);
|
|
159
|
-
|
|
160
|
-
this._unsubscribehook?.();
|
|
161
|
-
this._unsubscribehook = onBeforeRender(() => {
|
|
162
|
-
this.updateLighting(false);
|
|
163
|
-
this._getTextures(context.scene.environment);
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
// TODO remove this delay; we should wait for the scene lighting to be ready
|
|
167
|
-
// and then update the uniforms
|
|
168
|
-
while (!context.scene.environment) {
|
|
169
|
-
await delay(5);
|
|
164
|
+
if (!this._isInitialized) {
|
|
165
|
+
return;
|
|
170
166
|
}
|
|
171
|
-
this.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// const radianceMat = unlitMat.clone();
|
|
179
|
-
// radianceMat.map = this._radianceTexture;
|
|
180
|
-
// const radianceCube = ObjectUtils.createPrimitive("Quad", { material: radianceMat });
|
|
181
|
-
// const irradianceMat = unlitMat.clone();
|
|
182
|
-
// irradianceMat.map = this._irradianceTexture;
|
|
183
|
-
// const irradianceCube = ObjectUtils.createPrimitive("Quad", { material: irradianceMat });
|
|
184
|
-
// context.scene.add(radianceCube);
|
|
185
|
-
// context.scene.add(irradianceCube);
|
|
186
|
-
// radianceCube.position.set(2, 0, 0);
|
|
187
|
-
// irradianceCube.position.set(-2, 0, 0);
|
|
188
|
-
// console.log("[MaterialX] environment initialized from Needle context", this, this._context.scene);
|
|
189
|
-
// }
|
|
190
|
-
|
|
191
|
-
this.updateLighting(true);
|
|
192
|
-
|
|
193
|
-
// Mark as initialized
|
|
194
|
-
return true;
|
|
167
|
+
if (this._lastUpdateFrame === frame) {
|
|
168
|
+
// Already updated this frame
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this._lastUpdateFrame = frame;
|
|
172
|
+
this.updateLighting(false);
|
|
173
|
+
this._getTextures(scene.environment);
|
|
195
174
|
}
|
|
196
175
|
|
|
197
176
|
// Reset the environment to allow re-initialization
|
|
198
177
|
reset() {
|
|
199
178
|
if (debug) console.log("[MaterialX] Resetting environment");
|
|
200
179
|
this._initializePromise = null;
|
|
180
|
+
this._isInitialized = false;
|
|
181
|
+
this._lastUpdateFrame = -1;
|
|
201
182
|
this._lights = [];
|
|
202
183
|
this._lightData = null;
|
|
203
184
|
this._lightCount = 0;
|
|
@@ -208,16 +189,35 @@ export class MaterialXEnvironment {
|
|
|
208
189
|
textureSet.irradianceTexture?.dispose();
|
|
209
190
|
}
|
|
210
191
|
this._texturesCache.clear();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
get lightData() {
|
|
195
|
+
return this._lightData;
|
|
196
|
+
}
|
|
197
|
+
get lightCount() { return this._lightCount || 0; }
|
|
198
|
+
getTextures(material: MaterialXMaterial) {
|
|
199
|
+
if (material.envMap) {
|
|
200
|
+
// If the material has its own envMap, we don't use the irradiance texture
|
|
201
|
+
return this._getTextures(material.envMap);
|
|
202
|
+
}
|
|
203
|
+
return this._getTextures(this._context?.getScene().environment);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private _pmremGenerator: PMREMGenerator | null = null;
|
|
207
|
+
private readonly _texturesCache: Map<Texture | null, EnvironmentTextureSet> = new Map();
|
|
211
208
|
|
|
212
|
-
|
|
213
|
-
this.
|
|
209
|
+
private async _initialize(): Promise<boolean> {
|
|
210
|
+
this._isInitialized = false;
|
|
211
|
+
this._pmremGenerator = new PMREMGenerator(this._context.getRenderer());
|
|
212
|
+
this.updateLighting(true);
|
|
213
|
+
this._isInitialized = true;
|
|
214
|
+
return true;
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
private _getTextures(texture: Texture | null | undefined): {
|
|
217
218
|
radianceTexture: Texture | null,
|
|
218
219
|
irradianceTexture: Texture | null
|
|
219
220
|
} {
|
|
220
|
-
|
|
221
221
|
let res: EnvironmentTextureSet | undefined = this._texturesCache.get(texture || null);
|
|
222
222
|
if (res) {
|
|
223
223
|
return res;
|
|
@@ -225,10 +225,9 @@ export class MaterialXEnvironment {
|
|
|
225
225
|
|
|
226
226
|
if (this._context && this._pmremGenerator && texture) {
|
|
227
227
|
if (debug) console.log("[MaterialX] Generating environment textures", texture.name);
|
|
228
|
-
|
|
229
228
|
const target = this._pmremGenerator.fromEquirectangular(texture);
|
|
230
|
-
const radianceRenderTarget = renderPMREMToEquirect(this._context.
|
|
231
|
-
const irradianceRenderTarget = renderPMREMToEquirect(this._context.
|
|
229
|
+
const radianceRenderTarget = renderPMREMToEquirect(this._context.getRenderer(), target.texture, 0.0, 1024, 512, target.height);
|
|
230
|
+
const irradianceRenderTarget = renderPMREMToEquirect(this._context.getRenderer(), target.texture, 1.0, 32, 16, target.height);
|
|
232
231
|
target.dispose();
|
|
233
232
|
res = {
|
|
234
233
|
radianceTexture: radianceRenderTarget.texture,
|
|
@@ -247,12 +246,11 @@ export class MaterialXEnvironment {
|
|
|
247
246
|
|
|
248
247
|
private updateLighting = (collectLights: boolean = false) => {
|
|
249
248
|
if (!this._context) return;
|
|
250
|
-
|
|
251
249
|
// Find lights in scene
|
|
252
250
|
if (collectLights) {
|
|
253
251
|
const lights = new Array<Light>();
|
|
254
|
-
this._context.
|
|
255
|
-
if ((object as Light).isLight &&
|
|
252
|
+
this._context.getScene().traverse((object: Object3D) => {
|
|
253
|
+
if ((object as Light).isLight && object.visible)
|
|
256
254
|
lights.push(object as Light);
|
|
257
255
|
});
|
|
258
256
|
this._lights = lights;
|