@needle-tools/materialx 1.7.0-next.0d06218 → 1.7.0-next.57183d6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@needle-tools/materialx",
3
3
  "description": "MaterialX material support for three.js and Needle Engine – render physically based MaterialX shaders in the browser via WebAssembly",
4
- "version": "1.7.0-next.0d06218",
4
+ "version": "1.7.0-next.57183d6",
5
5
  "type": "module",
6
+ "license": "PolyForm-Noncommercial-1.0.0",
6
7
  "main": "index.js",
7
8
  "types": "index.d.ts",
8
9
  "exports": {
@@ -26,7 +27,10 @@
26
27
  "three": ">=0.160.0"
27
28
  },
28
29
  "scripts": {
29
- "test": "node --import=./tests/unit/register-json-loader.js --test tests/unit/**/*.test.js"
30
+ "test": "node --import=./tests/unit/register-json-loader.js --test tests/unit/**/*.test.js",
31
+ "test:runtime:node": "node tests/runtime/materialx-runtime-smoke.mjs",
32
+ "test:runtime:deno": "deno run --allow-read --no-lock --node-modules-dir=auto tests/runtime/materialx-runtime-smoke.mjs",
33
+ "test:runtime:bun": "bun tests/runtime/materialx-runtime-smoke.mjs"
30
34
  },
31
35
  "devDependencies": {
32
36
  "@needle-tools/engine": "4.x",
@@ -35,6 +39,9 @@
35
39
  "jsdom": "^29.0.1",
36
40
  "three": "npm:@needle-tools/three@^0.169.5"
37
41
  },
42
+ "overrides": {
43
+ "@needle-tools/gltf-progressive": "3.6.0-beta.2"
44
+ },
38
45
  "files": [
39
46
  "index.js",
40
47
  "index.d.ts",
package/src/constants.js CHANGED
@@ -1,6 +1,5 @@
1
- // Bare JSON import works in all bundlers (Vite, Webpack, Rollup).
2
- // Node.js 22+ requires --experimental-json-modules or import attributes,
3
- // but this file is only loaded in bundler context at runtime.
4
- // Unit tests that run under Node.js use the --import flag in package.json.
5
- import pkg from '../package.json';
1
+ // Keep the runtime version tied to package.json. The import attribute is
2
+ // required by browsers and Node.js for JSON modules; bundlers also understand
3
+ // this shape.
4
+ import pkg from '../package.json' with { type: 'json' };
6
5
  export const VERSION = pkg.version;
@@ -16,7 +16,7 @@ export interface LightData {
16
16
  outer_angle: number;
17
17
  }
18
18
 
19
- export function prepareEnvTexture(texture: THREE.Texture, capabilities: any): THREE.Texture;
19
+ export function prepareEnvTexture(texture: THREE.Texture, capabilities?: any): THREE.Texture;
20
20
 
21
21
  export function getLightRotation(): THREE.Matrix4;
22
22
 
@@ -21,7 +21,7 @@ const IMAGE_PATH_SEPARATOR = "/";
21
21
  export function prepareEnvTexture(texture, capabilities) {
22
22
  const newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, /** @type {any} */(texture.format), texture.type);
23
23
  newTexture.wrapS = THREE.RepeatWrapping;
24
- newTexture.anisotropy = capabilities.getMaxAnisotropy();
24
+ newTexture.anisotropy = capabilities?.getMaxAnisotropy?.() ?? 1;
25
25
  newTexture.minFilter = THREE.LinearMipmapLinearFilter;
26
26
  newTexture.magFilter = THREE.LinearFilter;
27
27
  newTexture.generateMipmaps = true;
@@ -71,10 +71,22 @@ function fromMatrix(matrix, dimension) {
71
71
  * @property {(path: string) => Promise<THREE.Texture | null | void>} getTexture - Get a texture by path
72
72
  */
73
73
 
74
+ /**
75
+ * @param {string} src
76
+ * @returns {HTMLImageElement | { src: string }}
77
+ */
78
+ function createPortableImage(src) {
79
+ if (typeof Image !== 'undefined') {
80
+ const image = new Image();
81
+ image.src = src;
82
+ return image;
83
+ }
84
+ return { src };
85
+ }
86
+
74
87
  const defaultTexture = new THREE.Texture();
75
88
  defaultTexture.needsUpdate = true;
76
- defaultTexture.image = new Image();
77
- defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFr6+vGqg52AAAAAxJREFUeJxjZGBEgQAAWAAJLpjsTQAAAABJRU5ErkJggg=="
89
+ defaultTexture.image = createPortableImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFr6+vGqg52AAAAAxJREFUeJxjZGBEgQAAWAAJLpjsTQAAAABJRU5ErkJggg==");
78
90
  // defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAB5QTFRFAAAABAQEw8PD////v7+/vb29Xl5eQEBA+/v7PDw8GPBYkgAAAB1JREFUeJxjZGBgYFQSABIUMlxgDGMGBtaIAnIZAKwQCSDYUEZEAAAAAElFTkSuQmCC";
79
91
  // defaultTexture.wrapS = THREE.RepeatWrapping;
80
92
  // defaultTexture.wrapT = THREE.RepeatWrapping;
@@ -84,8 +96,7 @@ defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAA
84
96
 
85
97
  const defaultNormalTexture = new THREE.Texture();
86
98
  defaultNormalTexture.needsUpdate = true;
87
- defaultNormalTexture.image = new Image();
88
- defaultNormalTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=";
99
+ defaultNormalTexture.image = createPortableImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=");
89
100
 
90
101
  /**
91
102
  * @param {string} key
package/src/materialx.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import MaterialX from "../bin/JsMaterialXGenShader.js";
2
2
  import { debug, waitForNetworkIdle } from "./utils.js";
3
3
  import { renderPMREMToEquirect, renderPMREMToPrefilteredEquirect } from "./utils.texture.js";
4
- import { CubeUVReflectionMapping, Light, Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, PMREMGenerator, Scene, Texture, WebGLRenderer } from "three";
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";
@@ -17,6 +17,19 @@ function isTextureLike(value) {
17
17
  return !!value && typeof value === "object" && /** @type {{ isTexture?: unknown }} */(value).isTexture === true;
18
18
  }
19
19
 
20
+ function isNodeRuntime() {
21
+ return !!globalThis.process?.versions?.node && globalThis.process?.type !== "renderer";
22
+ }
23
+
24
+ async function getNodePackageAssetPaths() {
25
+ const { fileURLToPath } = await import(/* @vite-ignore */ "node:url");
26
+ return [
27
+ fileURLToPath(new URL("../bin/JsMaterialXCore.wasm", import.meta.url)),
28
+ fileURLToPath(new URL("../bin/JsMaterialXGenShader.wasm", import.meta.url)),
29
+ fileURLToPath(new URL("../bin/JsMaterialXGenShader.data.txt", import.meta.url)),
30
+ ];
31
+ }
32
+
20
33
 
21
34
  /**
22
35
  * Preloads the MaterialX WebAssembly module.
@@ -69,7 +82,10 @@ export async function ready() {
69
82
 
70
83
  const location = globalThis.NEEDLE_MATERIALX_LOCATION;
71
84
 
72
- if (location === "package" || location === "bin/" || location === "./bin/" || location === "../bin/") {
85
+ if (isNodeRuntime()) {
86
+ urls = await getNodePackageAssetPaths();
87
+ }
88
+ else if (location === "package" || location === "bin/" || location === "./bin/" || location === "../bin/") {
73
89
  // Use local files from the @needle-tools/materialx npm package.
74
90
  // Vite's ?url suffix copies these files to the output directory
75
91
  // and returns their URL automatically — no CDN download needed.
@@ -229,7 +245,7 @@ export class MaterialXEnvironment {
229
245
 
230
246
  /**
231
247
  * Initialize with Needle Engine context
232
- * @param {WebGLRenderer} renderer
248
+ * @param {import("three").WebGLRenderer} renderer
233
249
  * @returns {Promise<boolean>}
234
250
  */
235
251
  async initialize(renderer) {
@@ -243,7 +259,7 @@ export class MaterialXEnvironment {
243
259
  /**
244
260
  * @param {number} frame
245
261
  * @param {Scene} scene
246
- * @param {WebGLRenderer} renderer
262
+ * @param {import("three").WebGLRenderer} renderer
247
263
  */
248
264
  update(frame, scene, renderer) {
249
265
  if (!this._initializePromise) {
@@ -334,13 +350,13 @@ export class MaterialXEnvironment {
334
350
 
335
351
  /** @type {PMREMGenerator | null} */
336
352
  _pmremGenerator = null;
337
- /** @type {WebGLRenderer | null} */
353
+ /** @type {import("three").WebGLRenderer | null} */
338
354
  _renderer = null;
339
355
  /** @type {Map<Texture | null, Map<string, EnvironmentTextureSet>>} */
340
356
  _texturesCache = new Map();
341
357
 
342
358
  /**
343
- * @param {WebGLRenderer} renderer
359
+ * @param {import("three").WebGLRenderer} renderer
344
360
  * @returns {Promise<boolean>}
345
361
  */
346
362
  async _initialize(renderer) {
@@ -1,8 +1,7 @@
1
- import { BufferGeometry, Camera, Euler, FrontSide, GLSL3, Group, Matrix4, Object3D, Scene, ShaderMaterial, Texture, UniformsLib, Vector3, WebGLRenderer } from "three";
1
+ import { BufferGeometry, Camera, Euler, FrontSide, GLSL3, Group, Matrix4, Object3D, Scene, ShaderMaterial, Texture, Vector3 } from "three";
2
2
  import { debug, getFrame, getTime } from "./utils.js";
3
3
  import { MaterialXEnvironment } from "./materialx.js";
4
4
  import { generateMaterialPropertiesForUniforms, getUniformValues, getLightTypeIds } from "./materialx.helper.js";
5
- import { cloneUniforms, cloneUniformsGroups, mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js";
6
5
 
7
6
  export const DEFAULT_ENVIRONMENT_RADIANCE_MODE = "three-pmrem";
8
7
 
@@ -15,6 +14,83 @@ const worldViewProjectionMat = new Matrix4();
15
14
  const envMat = new Matrix4();
16
15
  const envRotation = new Euler();
17
16
 
17
+ // Local copy of Three.js UniformsUtils.cloneUniforms from
18
+ // three/src/renderers/shaders/UniformsUtils.js. Keep this in sync with the
19
+ // minimum supported Three.js version when Three changes uniform cloning.
20
+ function cloneUniforms(src) {
21
+ const dst = {};
22
+ for (const uniformName in src) {
23
+ dst[uniformName] = {};
24
+ for (const propertyName in src[uniformName]) {
25
+ const property = src[uniformName][propertyName];
26
+ if (property && (
27
+ property.isColor ||
28
+ property.isMatrix3 || property.isMatrix4 ||
29
+ property.isVector2 || property.isVector3 || property.isVector4 ||
30
+ property.isTexture || property.isQuaternion
31
+ )) {
32
+ dst[uniformName][propertyName] = property.isRenderTargetTexture ? null : property.clone();
33
+ }
34
+ else if (Array.isArray(property)) {
35
+ dst[uniformName][propertyName] = property.slice();
36
+ }
37
+ else {
38
+ dst[uniformName][propertyName] = property;
39
+ }
40
+ }
41
+ }
42
+ return dst;
43
+ }
44
+
45
+ // Local copy of Three.js UniformsUtils.mergeUniforms from
46
+ // three/src/renderers/shaders/UniformsUtils.js. Copied to avoid importing from
47
+ // three/src, which breaks package consumers using Three's public ESM surface.
48
+ function mergeUniforms(uniforms) {
49
+ const merged = {};
50
+ for (const uniformSet of uniforms) {
51
+ const tmp = cloneUniforms(uniformSet);
52
+ for (const propertyName in tmp) {
53
+ merged[propertyName] = tmp[propertyName];
54
+ }
55
+ }
56
+ return merged;
57
+ }
58
+
59
+ // Local copy of Three.js UniformsUtils.cloneUniformsGroups from
60
+ // three/src/renderers/shaders/UniformsUtils.js. Keep alongside cloneUniforms
61
+ // and mergeUniforms so ShaderMaterial.clone() stays behavior-compatible.
62
+ function cloneUniformsGroups(src) {
63
+ return src.map(group => group.clone());
64
+ }
65
+
66
+ function createThreeLightUniforms() {
67
+ return {
68
+ ambientLightColor: { value: [] },
69
+ lightProbe: { value: [] },
70
+ directionalLights: { value: [], properties: { direction: {}, color: {} } },
71
+ directionalLightShadows: { value: [], properties: { shadowIntensity: 1, shadowBias: {}, shadowNormalBias: {}, shadowRadius: {}, shadowMapSize: {} } },
72
+ directionalShadowMap: { value: [] },
73
+ directionalShadowMatrix: { value: [] },
74
+ spotLights: { value: [], properties: { color: {}, position: {}, direction: {}, distance: {}, coneCos: {}, penumbraCos: {}, decay: {} } },
75
+ spotLightShadows: { value: [], properties: { shadowIntensity: 1, shadowBias: {}, shadowNormalBias: {}, shadowRadius: {}, shadowMapSize: {} } },
76
+ spotLightMap: { value: [] },
77
+ spotShadowMap: { value: [] },
78
+ spotLightMatrix: { value: [] },
79
+ pointLights: { value: [], properties: { color: {}, position: {}, decay: {}, distance: {} } },
80
+ pointLightShadows: { value: [], properties: { shadowIntensity: 1, shadowBias: {}, shadowNormalBias: {}, shadowRadius: {}, shadowMapSize: {}, shadowCameraNear: {}, shadowCameraFar: {} } },
81
+ pointShadowMap: { value: [] },
82
+ pointShadowMatrix: { value: [] },
83
+ hemisphereLights: { value: [], properties: { direction: {}, skyColor: {}, groundColor: {} } },
84
+ rectAreaLights: { value: [], properties: { color: {}, position: {}, width: {}, height: {} } },
85
+ ltc_1: { value: null },
86
+ ltc_2: { value: null },
87
+ probesSH: { value: null },
88
+ probesMin: { value: new Vector3() },
89
+ probesMax: { value: new Vector3() },
90
+ probesResolution: { value: new Vector3() },
91
+ };
92
+ }
93
+
18
94
  const CUBE_UV_REFLECTION_FUNCTIONS = `
19
95
  float mx_cubeuv_getFace(vec3 direction) {
20
96
  vec3 absDirection = abs(direction);
@@ -623,37 +699,39 @@ $2`
623
699
  this.environmentRadianceMode = environmentRadianceMode;
624
700
  this.specularAntialiasing = specularAntialiasing;
625
701
 
626
- Object.assign(this.uniforms, {
627
- // Three.js light uniforms (required when lights: true)
628
- ...UniformsLib.lights,
629
-
630
- ...getUniformValues(init.shader.getStage('vertex'), init.loaders, searchPath, pendingTextureLoads),
631
- ...getUniformValues(init.shader.getStage('pixel'), init.loaders, searchPath, pendingTextureLoads),
632
-
633
- u_worldMatrix: { value: new Matrix4() },
634
- u_worldInverseMatrix: { value: new Matrix4() },
635
- u_worldTransposeMatrix: { value: new Matrix4() },
636
- u_worldInverseTransposeMatrix: { value: new Matrix4() },
637
- u_worldViewMatrix: { value: new Matrix4() },
638
- u_viewProjectionMatrix: { value: new Matrix4() },
639
- u_worldViewProjectionMatrix: { value: new Matrix4() },
640
- u_viewPosition: { value: new Vector3() },
641
-
642
- u_envMatrix: { value: new Matrix4() },
643
- u_envRadiance: { value: null, type: 't' },
644
- u_envRadianceMips: { value: 8, type: 'i' },
645
- u_envRadianceCubeUVTexelWidth: { value: 1 / 768 },
646
- u_envRadianceCubeUVTexelHeight: { value: 1 / 1024 },
647
- u_envRadianceCubeUVMaxMip: { value: 8 },
648
- // TODO we need to figure out how we can set a PMREM here... doing many texture samples is prohibitively expensive
649
- u_envRadianceSamples: { value: 8, type: 'i' },
650
- u_envIrradiance: { value: null, type: 't' },
651
- envMapIntensity: { value: 1.0 },
652
- u_refractionEnv: { value: true },
653
- u_refractionTwoSided: { value: false },
654
- u_numActiveLightSources: { value: 0 },
655
- u_lightData: { value: [], needsUpdate: false }, // Array of light data. We need to set needsUpdate to false until we actually update it
656
- });
702
+ Object.assign(this.uniforms,
703
+ // Three.js light uniforms (required when lights: true). These use
704
+ // Three's merge/clone semantics; generated MaterialX texture
705
+ // uniforms below must keep their original object identity so async
706
+ // texture resolution updates the same uniform object.
707
+ mergeUniforms([createThreeLightUniforms()]),
708
+ getUniformValues(init.shader.getStage('vertex'), init.loaders, searchPath, pendingTextureLoads),
709
+ getUniformValues(init.shader.getStage('pixel'), init.loaders, searchPath, pendingTextureLoads),
710
+ {
711
+ u_worldMatrix: { value: new Matrix4() },
712
+ u_worldInverseMatrix: { value: new Matrix4() },
713
+ u_worldTransposeMatrix: { value: new Matrix4() },
714
+ u_worldInverseTransposeMatrix: { value: new Matrix4() },
715
+ u_worldViewMatrix: { value: new Matrix4() },
716
+ u_viewProjectionMatrix: { value: new Matrix4() },
717
+ u_worldViewProjectionMatrix: { value: new Matrix4() },
718
+ u_viewPosition: { value: new Vector3() },
719
+
720
+ u_envMatrix: { value: new Matrix4() },
721
+ u_envRadiance: { value: null, type: 't' },
722
+ u_envRadianceMips: { value: 8, type: 'i' },
723
+ u_envRadianceCubeUVTexelWidth: { value: 1 / 768 },
724
+ u_envRadianceCubeUVTexelHeight: { value: 1 / 1024 },
725
+ u_envRadianceCubeUVMaxMip: { value: 8 },
726
+ // TODO we need to figure out how we can set a PMREM here... doing many texture samples is prohibitively expensive
727
+ u_envRadianceSamples: { value: 8, type: 'i' },
728
+ u_envIrradiance: { value: null, type: 't' },
729
+ envMapIntensity: { value: 1.0 },
730
+ u_refractionEnv: { value: true },
731
+ u_refractionTwoSided: { value: false },
732
+ u_numActiveLightSources: { value: 0 },
733
+ u_lightData: { value: [], needsUpdate: false }, // Array of light data. We need to set needsUpdate to false until we actually update it
734
+ });
657
735
  this.ready = Promise.all(pendingTextureLoads).then(() => undefined);
658
736
 
659
737
  generateMaterialPropertiesForUniforms(this, init.shader.getStage('pixel'));
@@ -673,7 +751,7 @@ $2`
673
751
  _missingTangentsWarned = false;
674
752
 
675
753
  /**
676
- * @param {WebGLRenderer} renderer
754
+ * @param {import("three").WebGLRenderer} renderer
677
755
  * @param {Scene} _scene
678
756
  * @param {Camera} camera
679
757
  * @param {BufferGeometry} geometry
@@ -710,7 +788,7 @@ $2`
710
788
  specularAntialiasing = true;
711
789
 
712
790
  /**
713
- * @param {WebGLRenderer} _renderer
791
+ * @param {import("three").WebGLRenderer} _renderer
714
792
  * @param {Object3D} object
715
793
  * @param {Camera} camera
716
794
  * @param {number} [time]
package/src/utils.js CHANGED
@@ -7,7 +7,9 @@
7
7
  * @returns {boolean|string} Parameter value or false if not found
8
8
  */
9
9
  export function getParam(name) {
10
- const urlParams = new URLSearchParams(window.location.search);
10
+ const search = globalThis.location?.search ?? globalThis.window?.location?.search;
11
+ if (!search) return false;
12
+ const urlParams = new URLSearchParams(search);
11
13
  const param = urlParams.get(name);
12
14
  if (param == null || param === "0" || param === "false") return false;
13
15
  if (param === "") return true;
@@ -35,22 +37,26 @@ export function getFrame() {
35
37
  return frame;
36
38
  }
37
39
 
38
- const performance = window.performance || /** @type {any} */ (window).webkitPerformance || /** @type {any} */ (window).mozPerformance;
40
+ const performanceApi = globalThis.performance
41
+ || globalThis.window?.performance
42
+ || /** @type {any} */ (globalThis.window)?.webkitPerformance
43
+ || /** @type {any} */ (globalThis.window)?.mozPerformance
44
+ || { now: () => Date.now() };
39
45
 
40
46
  function updateTime() {
41
- time = performance.now() / 1000; // Convert to seconds
47
+ time = performanceApi.now() / 1000; // Convert to seconds
42
48
  frame++;
43
- window.requestAnimationFrame(updateTime);
49
+ globalThis.requestAnimationFrame?.(updateTime);
44
50
  }
45
51
 
46
- window.requestAnimationFrame(updateTime);
52
+ globalThis.requestAnimationFrame?.(updateTime);
47
53
 
48
54
 
49
55
 
50
56
 
51
57
  export async function waitForNetworkIdle() {
52
- if (typeof requestIdleCallback !== "undefined") {
53
- return new Promise(res => requestIdleCallback(res));
58
+ if (typeof globalThis.requestIdleCallback !== "undefined") {
59
+ return new Promise(res => globalThis.requestIdleCallback(res));
54
60
  }
55
61
  else {
56
62
  console.debug("[MaterialX] Can not wait for network idle, using fallback");
@@ -61,5 +67,6 @@ export async function waitForNetworkIdle() {
61
67
 
62
68
  export function isDevEnvironment() {
63
69
  // check if we're in localhost or using an ip address
64
- return window.location.hostname === "localhost" || /^\d{1,3}(\.\d{1,3}){3}$/.test(window.location.hostname);
65
- }
70
+ const hostname = globalThis.location?.hostname ?? globalThis.window?.location?.hostname;
71
+ return hostname === "localhost" || !!hostname && /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname);
72
+ }
@@ -1,4 +1,4 @@
1
- import { WebGLRenderer, Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter, DataTexture, UnsignedByteType, Vector4 } from 'three';
1
+ import { Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter, DataTexture, UnsignedByteType, Vector4 } from 'three';
2
2
  import { getParam } from './utils.js';
3
3
 
4
4
  const debug = getParam("debugmaterialx");
@@ -96,7 +96,7 @@ function createPrefilteredEquirectMaterial(pmremTexture, cubeUVSize) {
96
96
 
97
97
  /**
98
98
  * Renders a PMREM environment map to an equirectangular texture with specified roughness
99
- * @param {WebGLRenderer} renderer - Three.js WebGL renderer
99
+ * @param {import("three").WebGLRenderer} renderer - Three.js WebGL renderer
100
100
  * @param {Texture} pmremTexture - PMREM texture (2D CubeUV layout) to convert
101
101
  * @param {number} [roughness=0.0] - Roughness value (0.0 to 1.0)
102
102
  * @param {number} [width=1024] - Output texture width
@@ -249,7 +249,7 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
249
249
  /**
250
250
  * Renders a Three.js PMREM CubeUV texture to an equirectangular texture whose mip
251
251
  * levels encode increasing roughness for MaterialX SPECULAR_ENVIRONMENT_PREFILTER.
252
- * @param {WebGLRenderer} renderer
252
+ * @param {import("three").WebGLRenderer} renderer
253
253
  * @param {Texture} pmremTexture
254
254
  * @param {number} [width=2048]
255
255
  * @param {number} [height=1024]