@needle-tools/materialx 1.6.0 → 1.7.0-next.043f0c6
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/CHANGELOG.md +19 -1
- package/LICENSE.txt +131 -0
- package/README.md +33 -1
- package/bin/JsMaterialXCore.js +5 -13
- package/bin/JsMaterialXCore.wasm +0 -0
- package/bin/JsMaterialXGenShader.data.txt +2127 -2453
- package/bin/JsMaterialXGenShader.js +5 -13
- package/bin/JsMaterialXGenShader.wasm +0 -0
- package/bin/revision.json +3 -3
- package/package.json +14 -3
- package/src/constants.js +4 -5
- package/src/index.d.ts +1 -2
- package/src/loader/loader.three.d.ts +10 -1
- package/src/loader/loader.three.js +26 -19
- package/src/materialx.d.ts +9 -5
- package/src/materialx.helper.d.ts +2 -2
- package/src/materialx.helper.js +113 -47
- package/src/materialx.js +106 -29
- package/src/materialx.material.d.ts +11 -2
- package/src/materialx.material.js +614 -34
- package/src/materialx.types.d.ts +65 -10
- package/src/utils.js +16 -9
- package/src/utils.texture.d.ts +11 -0
- package/src/utils.texture.js +195 -38
- /package/bin/{SHA_0e7685f37737511f2816949b9486d511a5fa71bd → SHA_ab218c56f016a9a2d398e8d306f3aeb439ae9e9e} +0 -0
package/src/materialx.js
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import MaterialX from "../bin/JsMaterialXGenShader.js";
|
|
2
2
|
import { debug, waitForNetworkIdle } from "./utils.js";
|
|
3
|
-
import { renderPMREMToEquirect } from "./utils.texture.js";
|
|
4
|
-
import { Light, Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, PMREMGenerator, Scene, Texture
|
|
3
|
+
import { renderPMREMToEquirect, renderPMREMToPrefilteredEquirect } from "./utils.texture.js";
|
|
4
|
+
import { CubeUVReflectionMapping, Light, Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, PMREMGenerator, Scene, Texture } from "three";
|
|
5
5
|
import { registerLights, getLightData } from "./materialx.helper.js";
|
|
6
6
|
import { whiteTexture } from "./utils.texture.js";
|
|
7
7
|
import { VERSION } from "./constants.js";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Accept Texture instances from any Three.js copy. Tooling like the fidelity
|
|
11
|
+
* renderer can host scenes with a different Three.js module instance than this
|
|
12
|
+
* package, so `instanceof Texture` is too strict here.
|
|
13
|
+
* @param {unknown} value
|
|
14
|
+
* @returns {value is Texture}
|
|
15
|
+
*/
|
|
16
|
+
function isTextureLike(value) {
|
|
17
|
+
return !!value && typeof value === "object" && /** @type {{ isTexture?: unknown }} */(value).isTexture === true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isNodeRuntime() {
|
|
21
|
+
return !!globalThis.process?.versions?.node && globalThis.process?.type !== "renderer";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function getNodePackageAssetPaths() {
|
|
25
|
+
const nodeUrlModule = "node:url";
|
|
26
|
+
const { fileURLToPath } = await import(/* @vite-ignore */ nodeUrlModule);
|
|
27
|
+
const binDirectory = ["..", "bin"].join("/") + "/";
|
|
28
|
+
return [
|
|
29
|
+
"JsMaterialXCore.wasm",
|
|
30
|
+
"JsMaterialXGenShader.wasm",
|
|
31
|
+
"JsMaterialXGenShader.data.txt",
|
|
32
|
+
].map(fileName => fileURLToPath(new URL(binDirectory + fileName, import.meta.url)));
|
|
33
|
+
}
|
|
34
|
+
|
|
9
35
|
|
|
10
36
|
/**
|
|
11
37
|
* Preloads the MaterialX WebAssembly module.
|
|
@@ -51,14 +77,17 @@ export async function ready() {
|
|
|
51
77
|
|
|
52
78
|
// NOTE: This must be a plain string literal (not a template) so that the
|
|
53
79
|
// makeFilesLocal Vite plugin can statically detect and localize this URL.
|
|
54
|
-
const defaultBaseUrl = "https://cdn.needle.tools/static/materialx/1.
|
|
80
|
+
const defaultBaseUrl = "https://cdn.needle.tools/static/materialx/1.7.0/";
|
|
55
81
|
|
|
56
82
|
/** @type {Array<string>} */
|
|
57
83
|
let urls;
|
|
58
84
|
|
|
59
85
|
const location = globalThis.NEEDLE_MATERIALX_LOCATION;
|
|
60
86
|
|
|
61
|
-
if (
|
|
87
|
+
if (isNodeRuntime()) {
|
|
88
|
+
urls = await getNodePackageAssetPaths();
|
|
89
|
+
}
|
|
90
|
+
else if (location === "package" || location === "bin/" || location === "./bin/" || location === "../bin/") {
|
|
62
91
|
// Use local files from the @needle-tools/materialx npm package.
|
|
63
92
|
// Vite's ?url suffix copies these files to the output directory
|
|
64
93
|
// and returns their URL automatically — no CDN download needed.
|
|
@@ -121,7 +150,7 @@ export async function ready() {
|
|
|
121
150
|
// SPECULAR_ENVIRONMENT_NONE: Do not use specular environment maps.
|
|
122
151
|
// SPECULAR_ENVIRONMENT_FIS: Use Filtered Importance Sampling for specular environment/indirect lighting.
|
|
123
152
|
// SPECULAR_ENVIRONMENT_PREFILTER: Use pre-filtered environment maps for specular environment/indirect lighting.
|
|
124
|
-
state.materialXGenContext.getOptions().hwSpecularEnvironmentMethod = state.materialXModule.HwSpecularEnvironmentMethod.
|
|
153
|
+
state.materialXGenContext.getOptions().hwSpecularEnvironmentMethod = state.materialXModule.HwSpecularEnvironmentMethod.SPECULAR_ENVIRONMENT_PREFILTER;
|
|
125
154
|
|
|
126
155
|
// TRANSMISSION_REFRACTION: Use a refraction approximation for transmission rendering.
|
|
127
156
|
// TRANSMISSION_OPACITY: Use opacity for transmission rendering.
|
|
@@ -161,6 +190,7 @@ export async function ready() {
|
|
|
161
190
|
* @typedef {Object} EnvironmentTextureSet
|
|
162
191
|
* @property {Texture | null} radianceTexture
|
|
163
192
|
* @property {Texture | null} irradianceTexture
|
|
193
|
+
* @property {() => void} [dispose]
|
|
164
194
|
*/
|
|
165
195
|
|
|
166
196
|
/**
|
|
@@ -217,7 +247,7 @@ export class MaterialXEnvironment {
|
|
|
217
247
|
|
|
218
248
|
/**
|
|
219
249
|
* Initialize with Needle Engine context
|
|
220
|
-
* @param {WebGLRenderer} renderer
|
|
250
|
+
* @param {import("three").WebGLRenderer} renderer
|
|
221
251
|
* @returns {Promise<boolean>}
|
|
222
252
|
*/
|
|
223
253
|
async initialize(renderer) {
|
|
@@ -231,7 +261,7 @@ export class MaterialXEnvironment {
|
|
|
231
261
|
/**
|
|
232
262
|
* @param {number} frame
|
|
233
263
|
* @param {Scene} scene
|
|
234
|
-
* @param {WebGLRenderer} renderer
|
|
264
|
+
* @param {import("three").WebGLRenderer} renderer
|
|
235
265
|
*/
|
|
236
266
|
update(frame, scene, renderer) {
|
|
237
267
|
if (!this._initializePromise) {
|
|
@@ -285,9 +315,10 @@ export class MaterialXEnvironment {
|
|
|
285
315
|
this._pmremGenerator?.dispose();
|
|
286
316
|
this._pmremGenerator = null;
|
|
287
317
|
this._renderer = null;
|
|
288
|
-
for (const
|
|
289
|
-
textureSet.
|
|
290
|
-
|
|
318
|
+
for (const textureModeMap of this._texturesCache.values()) {
|
|
319
|
+
for (const textureSet of textureModeMap.values()) {
|
|
320
|
+
textureSet.dispose?.();
|
|
321
|
+
}
|
|
291
322
|
}
|
|
292
323
|
this._texturesCache.clear();
|
|
293
324
|
}
|
|
@@ -304,34 +335,34 @@ export class MaterialXEnvironment {
|
|
|
304
335
|
* @param {import("./materialx.material.js").MaterialXMaterial} material
|
|
305
336
|
*/
|
|
306
337
|
getTextures(material) {
|
|
338
|
+
const radianceMode = material.environmentRadianceMode ?? "three-pmrem";
|
|
307
339
|
if (material.envMap) {
|
|
308
340
|
// If the material has its own envMap, we don't use the irradiance texture
|
|
309
|
-
return this._getTextures(material.envMap);
|
|
341
|
+
return this._getTextures(material.envMap, radianceMode);
|
|
310
342
|
}
|
|
311
343
|
|
|
312
344
|
// Use the scene background for lighting if no environment is available
|
|
313
345
|
// If we don't do this we don't see the correct lighting for scenes exported with 'Environment Lighting: Color' and 'Environment Reflections: Skybox'
|
|
314
346
|
const skybox = this._scene.environment || this._scene.background;
|
|
315
|
-
if (skybox
|
|
316
|
-
return this._getTextures(skybox);
|
|
347
|
+
if (isTextureLike(skybox)) {
|
|
348
|
+
return this._getTextures(skybox, radianceMode);
|
|
317
349
|
}
|
|
318
|
-
return this._getTextures(null);
|
|
350
|
+
return this._getTextures(null, radianceMode);
|
|
319
351
|
}
|
|
320
352
|
|
|
321
353
|
/** @type {PMREMGenerator | null} */
|
|
322
354
|
_pmremGenerator = null;
|
|
323
|
-
/** @type {WebGLRenderer | null} */
|
|
355
|
+
/** @type {import("three").WebGLRenderer | null} */
|
|
324
356
|
_renderer = null;
|
|
325
|
-
/** @type {Map<Texture | null, EnvironmentTextureSet
|
|
357
|
+
/** @type {Map<Texture | null, Map<string, EnvironmentTextureSet>>} */
|
|
326
358
|
_texturesCache = new Map();
|
|
327
359
|
|
|
328
360
|
/**
|
|
329
|
-
* @param {WebGLRenderer} renderer
|
|
361
|
+
* @param {import("three").WebGLRenderer} renderer
|
|
330
362
|
* @returns {Promise<boolean>}
|
|
331
363
|
*/
|
|
332
364
|
async _initialize(renderer) {
|
|
333
365
|
this._isInitialized = false;
|
|
334
|
-
this._pmremGenerator = new PMREMGenerator(renderer);
|
|
335
366
|
this._renderer = renderer;
|
|
336
367
|
this.updateLighting(true);
|
|
337
368
|
this._isInitialized = true;
|
|
@@ -340,30 +371,65 @@ export class MaterialXEnvironment {
|
|
|
340
371
|
|
|
341
372
|
/**
|
|
342
373
|
* @param {Texture | null | undefined} texture
|
|
343
|
-
* @
|
|
374
|
+
* @param {"three-pmrem" | "materialx-prefiltered" | "materialx-fis"} [radianceMode]
|
|
375
|
+
* @returns {EnvironmentTextureSet}
|
|
344
376
|
*/
|
|
345
|
-
_getTextures(texture) {
|
|
377
|
+
_getTextures(texture, radianceMode = "three-pmrem") {
|
|
346
378
|
|
|
347
379
|
// Fallback to white texture if no texture is provided
|
|
348
380
|
if (!texture) {
|
|
349
381
|
texture = whiteTexture;
|
|
350
382
|
}
|
|
351
383
|
|
|
384
|
+
const cacheKey = texture || null;
|
|
385
|
+
let textureModeMap = this._texturesCache.get(cacheKey);
|
|
386
|
+
if (!textureModeMap) {
|
|
387
|
+
textureModeMap = new Map();
|
|
388
|
+
this._texturesCache.set(cacheKey, textureModeMap);
|
|
389
|
+
}
|
|
390
|
+
|
|
352
391
|
/** @type {EnvironmentTextureSet | undefined} */
|
|
353
|
-
let res =
|
|
392
|
+
let res = textureModeMap.get(radianceMode);
|
|
354
393
|
if (res) {
|
|
355
394
|
return res;
|
|
356
395
|
}
|
|
357
396
|
|
|
358
|
-
|
|
397
|
+
const isPmremTexture = texture.mapping === CubeUVReflectionMapping || texture.isRenderTargetTexture === true;
|
|
398
|
+
|
|
399
|
+
if (this._scene && this._renderer && texture) {
|
|
359
400
|
if (debug) console.log("[MaterialX] Generating environment textures", texture.name);
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
401
|
+
let radianceRenderTarget;
|
|
402
|
+
let irradianceRenderTarget;
|
|
403
|
+
|
|
404
|
+
if (isPmremTexture) {
|
|
405
|
+
// Scene.environment is often already PMREM-processed (CubeUV layout).
|
|
406
|
+
// Running PMREMGenerator on it again corrupts the sampling layout.
|
|
407
|
+
radianceRenderTarget = radianceMode === "materialx-prefiltered"
|
|
408
|
+
? renderPMREMToPrefilteredEquirect(this._renderer, texture)
|
|
409
|
+
: radianceMode === "materialx-fis"
|
|
410
|
+
? renderPMREMToEquirect(this._renderer, texture, 0.0, 1024, 512)
|
|
411
|
+
: null;
|
|
412
|
+
irradianceRenderTarget = renderPMREMToEquirect(this._renderer, texture, 1.0, 32, 16);
|
|
413
|
+
} else {
|
|
414
|
+
const target = this._getPMREMGenerator().fromEquirectangular(texture);
|
|
415
|
+
radianceRenderTarget = radianceMode === "materialx-prefiltered"
|
|
416
|
+
? renderPMREMToPrefilteredEquirect(this._renderer, target.texture, undefined, undefined, target.height)
|
|
417
|
+
: radianceMode === "three-pmrem"
|
|
418
|
+
? target
|
|
419
|
+
: null;
|
|
420
|
+
irradianceRenderTarget = renderPMREMToEquirect(this._renderer, target.texture, 1.0, 32, 16, target.height);
|
|
421
|
+
if (radianceMode !== "three-pmrem") {
|
|
422
|
+
target.dispose();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
364
426
|
res = {
|
|
365
|
-
radianceTexture: radianceRenderTarget
|
|
366
|
-
irradianceTexture: irradianceRenderTarget.texture
|
|
427
|
+
radianceTexture: radianceRenderTarget?.texture ?? texture,
|
|
428
|
+
irradianceTexture: irradianceRenderTarget.texture,
|
|
429
|
+
dispose: () => {
|
|
430
|
+
radianceRenderTarget?.dispose();
|
|
431
|
+
irradianceRenderTarget?.dispose();
|
|
432
|
+
},
|
|
367
433
|
}
|
|
368
434
|
}
|
|
369
435
|
else {
|
|
@@ -372,10 +438,21 @@ export class MaterialXEnvironment {
|
|
|
372
438
|
irradianceTexture: null
|
|
373
439
|
}
|
|
374
440
|
}
|
|
375
|
-
|
|
441
|
+
textureModeMap.set(radianceMode, res);
|
|
376
442
|
return res;
|
|
377
443
|
}
|
|
378
444
|
|
|
445
|
+
/**
|
|
446
|
+
* @returns {PMREMGenerator}
|
|
447
|
+
*/
|
|
448
|
+
_getPMREMGenerator() {
|
|
449
|
+
if (!this._renderer) {
|
|
450
|
+
throw new Error("[MaterialX] Cannot create PMREMGenerator before renderer initialization.");
|
|
451
|
+
}
|
|
452
|
+
this._pmremGenerator ??= new PMREMGenerator(this._renderer);
|
|
453
|
+
return this._pmremGenerator;
|
|
454
|
+
}
|
|
455
|
+
|
|
379
456
|
/**
|
|
380
457
|
* @param {boolean} collectLights
|
|
381
458
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { BufferGeometry, Camera, Group, IUniform, MaterialParameters, Object3D, Scene, ShaderMaterial, Texture, WebGLRenderer } from "three";
|
|
1
|
+
import { BufferGeometry, Camera, Euler, Group, IUniform, MaterialParameters, Object3D, Scene, ShaderMaterial, Texture, WebGLRenderer } from "three";
|
|
2
2
|
import { MaterialXContext, MaterialXEnvironment } from "./materialx.js";
|
|
3
|
+
import type { MaterialXEnvironmentRadianceMode } from "./materialx.js";
|
|
3
4
|
import { Callbacks } from "./materialx.helper.js";
|
|
4
5
|
|
|
5
6
|
declare type MaterialXMaterialInitParameters = {
|
|
@@ -9,6 +10,8 @@ declare type MaterialXMaterialInitParameters = {
|
|
|
9
10
|
loaders: Callbacks;
|
|
10
11
|
context: MaterialXContext;
|
|
11
12
|
parameters?: MaterialParameters;
|
|
13
|
+
environmentRadianceMode?: MaterialXEnvironmentRadianceMode;
|
|
14
|
+
specularAntialiasing?: boolean;
|
|
12
15
|
debug?: boolean;
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -17,6 +20,7 @@ type Precision = "highp" | "mediump" | "lowp";
|
|
|
17
20
|
|
|
18
21
|
export declare class MaterialXMaterial extends ShaderMaterial {
|
|
19
22
|
readonly shaderName: string | null;
|
|
23
|
+
readonly ready: Promise<void>;
|
|
20
24
|
|
|
21
25
|
copy(source: MaterialXMaterial): this;
|
|
22
26
|
|
|
@@ -31,7 +35,12 @@ export declare class MaterialXMaterial extends ShaderMaterial {
|
|
|
31
35
|
|
|
32
36
|
envMapIntensity: number;
|
|
33
37
|
envMap: Texture | null;
|
|
38
|
+
envMapRotation: Euler;
|
|
39
|
+
environmentRadianceMode: MaterialXEnvironmentRadianceMode;
|
|
40
|
+
specularAntialiasing: boolean;
|
|
34
41
|
updateUniforms(environment: MaterialXEnvironment, _renderer: WebGLRenderer, object: Object3D, camera: Camera, time?: number, frame?: number): void;
|
|
35
42
|
|
|
36
|
-
private updateEnvironmentUniforms(environment: MaterialXEnvironment): void;
|
|
43
|
+
private updateEnvironmentUniforms(environment: MaterialXEnvironment, scene: Scene): void;
|
|
37
44
|
}
|
|
45
|
+
|
|
46
|
+
export declare const DEFAULT_ENVIRONMENT_RADIANCE_MODE: MaterialXEnvironmentRadianceMode;
|