@needle-tools/materialx 1.1.1 → 1.2.0
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 +6 -0
- package/bin/.gitattributes +4 -0
- package/bin/README.md +6 -0
- package/{index.ts → index.d.ts} +1 -1
- package/index.js +2 -0
- package/{needle.ts → needle.d.ts} +1 -1
- package/needle.js +2 -0
- package/package.json +24 -10
- package/src/index.d.ts +11 -0
- package/src/index.js +11 -0
- package/src/loader/loader.needle.d.ts +15 -0
- package/src/loader/loader.needle.js +62 -0
- package/src/loader/loader.three.d.ts +71 -0
- package/src/loader/loader.three.js +334 -0
- package/src/materialx.d.ts +60 -0
- package/src/materialx.helper.d.ts +31 -0
- package/src/{materialx.helper.ts → materialx.helper.js} +149 -101
- package/src/{materialx.ts → materialx.js} +115 -64
- package/src/materialx.material.d.ts +37 -0
- package/src/{materialx.material.ts → materialx.material.js} +110 -40
- package/src/utils.d.ts +17 -0
- package/src/{utils.ts → utils.js} +21 -4
- package/src/utils.texture.d.ts +13 -0
- package/src/{textureHelper.ts → utils.texture.js} +18 -17
- package/src/index.ts +0 -3
- package/src/loader/loader.needle.ts +0 -43
- package/src/loader/loader.three.ts +0 -322
- package/tsconfig.json +0 -20
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
export interface Callbacks {
|
|
4
|
+
readonly cacheKey?: string;
|
|
5
|
+
readonly getTexture: (path: string) => Promise<THREE.Texture | null | void>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface LightData {
|
|
9
|
+
type: number;
|
|
10
|
+
position: THREE.Vector3;
|
|
11
|
+
direction: THREE.Vector3;
|
|
12
|
+
color: THREE.Color;
|
|
13
|
+
intensity: number;
|
|
14
|
+
decay_rate: number;
|
|
15
|
+
inner_angle: number;
|
|
16
|
+
outer_angle: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function prepareEnvTexture(texture: THREE.Texture, capabilities: any): THREE.Texture;
|
|
20
|
+
|
|
21
|
+
export function getLightRotation(): THREE.Matrix4;
|
|
22
|
+
|
|
23
|
+
export function findLights(doc: any): Array<any>;
|
|
24
|
+
|
|
25
|
+
export function registerLights(mx: any, genContext: any): Promise<void>;
|
|
26
|
+
|
|
27
|
+
export function getLightData(lights: Array<THREE.Light>, genContext: any): { lightData: LightData[], lightCount: number };
|
|
28
|
+
|
|
29
|
+
export function getUniformValues(shaderStage: any, loaders: Callbacks, searchPath: string): Record<string, THREE.Uniform>;
|
|
30
|
+
|
|
31
|
+
export function generateMaterialPropertiesForUniforms(material: THREE.ShaderMaterial, shaderStage: any): void;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
//
|
|
5
5
|
import * as THREE from 'three';
|
|
6
6
|
import { debug, debugUpdate } from './utils.js';
|
|
7
|
-
import { MaterialX } from './materialx.types.js';
|
|
8
7
|
|
|
9
8
|
const IMAGE_PROPERTY_SEPARATOR = "_";
|
|
10
9
|
const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
|
|
@@ -13,20 +12,19 @@ const FILTER_TYPE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "filtertype";
|
|
|
13
12
|
const IMAGE_PATH_SEPARATOR = "/";
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
15
|
+
* Initializes the environment texture as MaterialX expects it
|
|
17
16
|
* @param {THREE.Texture} texture
|
|
18
17
|
* @param {Object} capabilities
|
|
19
18
|
* @returns {THREE.Texture}
|
|
20
19
|
*/
|
|
21
20
|
export function prepareEnvTexture(texture, capabilities) {
|
|
22
|
-
|
|
21
|
+
const newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, /** @type {any} */(texture.format), texture.type);
|
|
23
22
|
newTexture.wrapS = THREE.RepeatWrapping;
|
|
24
23
|
newTexture.anisotropy = capabilities.getMaxAnisotropy();
|
|
25
24
|
newTexture.minFilter = THREE.LinearMipmapLinearFilter;
|
|
26
25
|
newTexture.magFilter = THREE.LinearFilter;
|
|
27
26
|
newTexture.generateMipmaps = true;
|
|
28
27
|
newTexture.needsUpdate = true;
|
|
29
|
-
|
|
30
28
|
return newTexture;
|
|
31
29
|
}
|
|
32
30
|
|
|
@@ -34,7 +32,7 @@ export function prepareEnvTexture(texture, capabilities) {
|
|
|
34
32
|
* Get Three uniform from MaterialX vector
|
|
35
33
|
* @param {any} value
|
|
36
34
|
* @param {any} dimension
|
|
37
|
-
* @returns {
|
|
35
|
+
* @returns {Array<number>}
|
|
38
36
|
*/
|
|
39
37
|
function fromVector(value, dimension) {
|
|
40
38
|
let outValue;
|
|
@@ -52,8 +50,11 @@ function fromVector(value, dimension) {
|
|
|
52
50
|
|
|
53
51
|
/**
|
|
54
52
|
* Get Three uniform from MaterialX matrix
|
|
53
|
+
* @param {any} matrix
|
|
54
|
+
* @param {number} dimension
|
|
55
|
+
* @returns {Array<number>}
|
|
55
56
|
*/
|
|
56
|
-
function fromMatrix(matrix
|
|
57
|
+
function fromMatrix(matrix, dimension) {
|
|
57
58
|
const vec = new Array(dimension);
|
|
58
59
|
if (matrix) {
|
|
59
60
|
for (let i = 0; i < matrix.numRows(); ++i) {
|
|
@@ -69,19 +70,11 @@ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"
|
|
|
69
70
|
return vec;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
readonly cacheKey: string;
|
|
78
|
-
/**
|
|
79
|
-
* Get a texture by path
|
|
80
|
-
* @param {string} path - The path to the texture
|
|
81
|
-
* @return {Promise<THREE.Texture>} - A promise that resolves to the texture
|
|
82
|
-
*/
|
|
83
|
-
readonly getTexture: (path: string) => Promise<THREE.Texture>;
|
|
84
|
-
}
|
|
73
|
+
/**
|
|
74
|
+
* @typedef {Object} Callbacks
|
|
75
|
+
* @property {string} [cacheKey] - Cache key for the loaders, used to identify and reuse textures
|
|
76
|
+
* @property {(path: string) => Promise<THREE.Texture | null | void>} getTexture - Get a texture by path
|
|
77
|
+
*/
|
|
85
78
|
|
|
86
79
|
const defaultTexture = new THREE.Texture();
|
|
87
80
|
defaultTexture.needsUpdate = true;
|
|
@@ -94,21 +87,28 @@ defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAA
|
|
|
94
87
|
// defaultTexture.magFilter = THREE.NearestFilter;
|
|
95
88
|
// defaultTexture.repeat = new THREE.Vector2(100, 100);
|
|
96
89
|
|
|
97
|
-
|
|
98
90
|
const defaultNormalTexture = new THREE.Texture();
|
|
99
91
|
defaultNormalTexture.needsUpdate = true;
|
|
100
92
|
defaultNormalTexture.image = new Image();
|
|
101
93
|
defaultNormalTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=";
|
|
102
94
|
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
/**
|
|
96
|
+
* @param {string} key
|
|
97
|
+
* @returns {any}
|
|
98
|
+
*/
|
|
99
|
+
function tryGetFromCache(key) {
|
|
105
100
|
const wasEnabled = THREE.Cache.enabled;
|
|
106
101
|
THREE.Cache.enabled = true;
|
|
107
102
|
const value = THREE.Cache.get(key);
|
|
108
103
|
THREE.Cache.enabled = wasEnabled;
|
|
109
104
|
return value;
|
|
110
105
|
}
|
|
111
|
-
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {string} key
|
|
109
|
+
* @param {any} value
|
|
110
|
+
*/
|
|
111
|
+
function addToCache(key, value) {
|
|
112
112
|
const wasEnabled = THREE.Cache.enabled;
|
|
113
113
|
THREE.Cache.enabled = true;
|
|
114
114
|
THREE.Cache.add(key, value);
|
|
@@ -118,10 +118,17 @@ function addToCache(key: string, value: any): void {
|
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Get Three uniform from MaterialX value
|
|
121
|
+
* @param {any} uniforms
|
|
122
|
+
* @param {string} type
|
|
123
|
+
* @param {any} value
|
|
124
|
+
* @param {string} name
|
|
125
|
+
* @param {Callbacks} loaders
|
|
126
|
+
* @param {string} searchPath
|
|
127
|
+
* @returns {THREE.Uniform}
|
|
121
128
|
*/
|
|
122
|
-
function toThreeUniform(uniforms
|
|
129
|
+
function toThreeUniform(uniforms, type, value, name, loaders, searchPath) {
|
|
123
130
|
|
|
124
|
-
const uniform = new THREE.Uniform
|
|
131
|
+
const uniform = new THREE.Uniform(/** @type {any} */(null));
|
|
125
132
|
|
|
126
133
|
switch (type) {
|
|
127
134
|
case 'float':
|
|
@@ -130,21 +137,21 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
|
|
|
130
137
|
uniform.value = value;
|
|
131
138
|
break;
|
|
132
139
|
case 'vector2':
|
|
133
|
-
uniform.value = fromVector(value, 2);
|
|
140
|
+
uniform.value = /** @type {any} */ (fromVector(value, 2));
|
|
134
141
|
break;
|
|
135
142
|
case 'vector3':
|
|
136
143
|
case 'color3':
|
|
137
|
-
uniform.value = fromVector(value, 3);
|
|
144
|
+
uniform.value = /** @type {any} */ (fromVector(value, 3));
|
|
138
145
|
break;
|
|
139
146
|
case 'vector4':
|
|
140
147
|
case 'color4':
|
|
141
|
-
uniform.value = fromVector(value, 4);
|
|
148
|
+
uniform.value = /** @type {any} */ (fromVector(value, 4));
|
|
142
149
|
break;
|
|
143
150
|
case 'matrix33':
|
|
144
|
-
uniform.value = fromMatrix(value, 9);
|
|
151
|
+
uniform.value = /** @type {any} */ (fromMatrix(value, 9));
|
|
145
152
|
break;
|
|
146
153
|
case 'matrix44':
|
|
147
|
-
uniform.value = fromMatrix(value, 16);
|
|
154
|
+
uniform.value = /** @type {any} */ (fromMatrix(value, 16));
|
|
148
155
|
break;
|
|
149
156
|
case 'filename':
|
|
150
157
|
if (value) {
|
|
@@ -165,7 +172,7 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
|
|
|
165
172
|
checkCache = true;
|
|
166
173
|
}
|
|
167
174
|
|
|
168
|
-
const cacheKey = `${loaders.cacheKey}-${texturePath}
|
|
175
|
+
const cacheKey = loaders.cacheKey?.length ? `${loaders.cacheKey}-${texturePath}` : texturePath;
|
|
169
176
|
const cacheValue = checkCache ? tryGetFromCache(cacheKey) : null;
|
|
170
177
|
if (cacheValue) {
|
|
171
178
|
if (debug) console.log('[MaterialX] Use cached texture: ', cacheKey, cacheValue);
|
|
@@ -180,28 +187,30 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
|
|
|
180
187
|
}
|
|
181
188
|
}
|
|
182
189
|
else {
|
|
183
|
-
if (name.toLowerCase().includes("normal")) {
|
|
184
|
-
uniform.value = defaultNormalTexture;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
uniform.value = defaultTexture;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
190
|
if (debug) console.log('[MaterialX] Load texture:', texturePath);
|
|
191
|
+
|
|
192
|
+
if (name.toLowerCase().includes("normal")) uniform.value = /** @type {any} */ (defaultNormalTexture);
|
|
193
|
+
else uniform.value = /** @type {any} */ (defaultTexture);
|
|
194
|
+
const defaultValue = uniform.value;
|
|
191
195
|
// Save the loading promise in the cache
|
|
192
|
-
const promise = loaders.getTexture(texturePath)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
const promise = loaders.getTexture(texturePath)
|
|
197
|
+
?.then(res => {
|
|
198
|
+
if (res) {
|
|
199
|
+
res = res.clone(); // we need to clone the texture once to avoid colorSpace issues with other materials
|
|
200
|
+
res.colorSpace = THREE.LinearSRGBColorSpace;
|
|
201
|
+
setTextureParameters(res, name, uniforms);
|
|
202
|
+
}
|
|
203
|
+
return res;
|
|
204
|
+
})
|
|
205
|
+
.catch(err => {
|
|
206
|
+
console.error(`[MaterialX] Failed to load texture ${name} '${texturePath}'`, err);
|
|
207
|
+
return defaultValue;
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (checkCache) addToCache(cacheKey, promise);
|
|
211
|
+
|
|
212
|
+
promise?.then(res => {
|
|
213
|
+
if (res) uniform.value = /** @type {any} */ (res);
|
|
205
214
|
else console.warn(`[MaterialX] Failed to load texture ${name} '${texturePath}'`);
|
|
206
215
|
});
|
|
207
216
|
}
|
|
@@ -222,12 +231,15 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
|
|
|
222
231
|
return uniform;
|
|
223
232
|
}
|
|
224
233
|
|
|
225
|
-
|
|
234
|
+
/** @type {Map<string, boolean>} */
|
|
235
|
+
const valueTypeWarningMap = new Map();
|
|
226
236
|
|
|
227
237
|
/**
|
|
228
238
|
* Get Three wrapping mode
|
|
239
|
+
* @param {number} mode
|
|
240
|
+
* @returns {THREE.Wrapping}
|
|
229
241
|
*/
|
|
230
|
-
function getWrapping(mode
|
|
242
|
+
function getWrapping(mode) {
|
|
231
243
|
let wrap;
|
|
232
244
|
switch (mode) {
|
|
233
245
|
case 1:
|
|
@@ -246,11 +258,14 @@ function getWrapping(mode: number): THREE.Wrapping {
|
|
|
246
258
|
return wrap;
|
|
247
259
|
}
|
|
248
260
|
|
|
249
|
-
|
|
250
261
|
/**
|
|
251
262
|
* Set Three texture parameters
|
|
263
|
+
* @param {THREE.Texture} texture
|
|
264
|
+
* @param {string} name
|
|
265
|
+
* @param {any} uniforms
|
|
266
|
+
* @param {boolean} [generateMipmaps=true]
|
|
252
267
|
*/
|
|
253
|
-
function setTextureParameters(texture
|
|
268
|
+
function setTextureParameters(texture, name, uniforms, generateMipmaps = true) {
|
|
254
269
|
const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
|
|
255
270
|
const base = name.substring(0, idx) || name;
|
|
256
271
|
|
|
@@ -265,15 +280,16 @@ function setTextureParameters(texture: THREE.Texture, name: string, uniforms: an
|
|
|
265
280
|
}
|
|
266
281
|
|
|
267
282
|
const mxFilterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
|
|
268
|
-
let minFilter
|
|
283
|
+
let minFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
|
|
269
284
|
if (mxFilterType === 0) {
|
|
270
|
-
minFilter = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
|
|
285
|
+
minFilter = /** @type {any} */ (generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter);
|
|
271
286
|
}
|
|
272
287
|
texture.minFilter = minFilter;
|
|
273
288
|
}
|
|
274
289
|
|
|
275
290
|
/**
|
|
276
291
|
* Return the global light rotation matrix
|
|
292
|
+
* @returns {THREE.Matrix4}
|
|
277
293
|
*/
|
|
278
294
|
export function getLightRotation() {
|
|
279
295
|
return new THREE.Matrix4().makeRotationY(Math.PI / 2);
|
|
@@ -281,11 +297,11 @@ export function getLightRotation() {
|
|
|
281
297
|
|
|
282
298
|
/**
|
|
283
299
|
* Returns all lights nodes in a MaterialX document
|
|
284
|
-
* @param {
|
|
285
|
-
* @returns {Array
|
|
300
|
+
* @param {any} doc
|
|
301
|
+
* @returns {Array<any>}
|
|
286
302
|
*/
|
|
287
|
-
export function findLights(doc
|
|
288
|
-
let lights = new Array
|
|
303
|
+
export function findLights(doc) {
|
|
304
|
+
let lights = new Array();
|
|
289
305
|
for (let node of doc.getNodes()) {
|
|
290
306
|
if (node.getType() === "lightshader")
|
|
291
307
|
lights.push(node);
|
|
@@ -293,14 +309,16 @@ export function findLights(doc: MaterialX.Document) {
|
|
|
293
309
|
return lights;
|
|
294
310
|
}
|
|
295
311
|
|
|
312
|
+
/** @type {Object<string, number>} */
|
|
296
313
|
let lightTypesBound = {};
|
|
297
314
|
|
|
298
315
|
/**
|
|
299
316
|
* Register lights in shader generation context
|
|
300
|
-
* @param {
|
|
301
|
-
* @param {
|
|
317
|
+
* @param {any} mx - MaterialX Module
|
|
318
|
+
* @param {any} genContext - Shader generation context
|
|
319
|
+
* @returns {Promise<void>}
|
|
302
320
|
*/
|
|
303
|
-
export async function registerLights(mx
|
|
321
|
+
export async function registerLights(mx, genContext) {
|
|
304
322
|
lightTypesBound = {};
|
|
305
323
|
const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
|
|
306
324
|
mx.HwShaderGenerator.unbindLightShaders(genContext);
|
|
@@ -353,7 +371,12 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
|
|
|
353
371
|
if (debug) console.log("Light types bound in MaterialX context", lightTypesBound);
|
|
354
372
|
}
|
|
355
373
|
|
|
356
|
-
|
|
374
|
+
const _lightTypeWarnings = {}
|
|
375
|
+
/**
|
|
376
|
+
* Converts Three.js light type to MaterialX node name
|
|
377
|
+
* @param {string} threeLightType
|
|
378
|
+
* @returns {string|null}
|
|
379
|
+
*/
|
|
357
380
|
function threeLightTypeToMaterialXNodeName(threeLightType) {
|
|
358
381
|
switch (threeLightType) {
|
|
359
382
|
case 'PointLight':
|
|
@@ -363,26 +386,33 @@ function threeLightTypeToMaterialXNodeName(threeLightType) {
|
|
|
363
386
|
case 'SpotLight':
|
|
364
387
|
return 'ND_spot_light';
|
|
365
388
|
default:
|
|
366
|
-
|
|
367
|
-
|
|
389
|
+
if (!_lightTypeWarnings[threeLightType]) {
|
|
390
|
+
_lightTypeWarnings[threeLightType] = true;
|
|
391
|
+
console.warn('MaterialX: Unsupported light type: ' + threeLightType);
|
|
392
|
+
}
|
|
393
|
+
return null; // Unsupported light type
|
|
368
394
|
}
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
export type LightData = {
|
|
372
|
-
type: number, // Light type ID
|
|
373
|
-
position: THREE.Vector3, // Position in world space
|
|
374
|
-
direction: THREE.Vector3, // Direction in world space
|
|
375
|
-
color: THREE.Color, // Color of the light
|
|
376
|
-
intensity: number, // Intensity of the light
|
|
377
|
-
decay_rate: number, // Decay rate for point and spot lights
|
|
378
|
-
inner_angle: number, // Inner angle for spot lights
|
|
379
|
-
outer_angle: number, // Outer angle for spot lights
|
|
380
395
|
}
|
|
381
396
|
|
|
397
|
+
/**
|
|
398
|
+
* @typedef {Object} LightData
|
|
399
|
+
* @property {number} type - Light type ID
|
|
400
|
+
* @property {THREE.Vector3} position - Position in world space
|
|
401
|
+
* @property {THREE.Vector3} direction - Direction in world space
|
|
402
|
+
* @property {THREE.Color} color - Color of the light
|
|
403
|
+
* @property {number} intensity - Intensity of the light
|
|
404
|
+
* @property {number} decay_rate - Decay rate for point and spot lights
|
|
405
|
+
* @property {number} inner_angle - Inner angle for spot lights
|
|
406
|
+
* @property {number} outer_angle - Outer angle for spot lights
|
|
407
|
+
*/
|
|
408
|
+
|
|
382
409
|
/**
|
|
383
410
|
* Update light data for shader uniforms
|
|
411
|
+
* @param {Array<THREE.Light>} lights
|
|
412
|
+
* @param {any} genContext
|
|
413
|
+
* @returns {{ lightData: LightData[], lightCount: number }}
|
|
384
414
|
*/
|
|
385
|
-
export function getLightData(lights
|
|
415
|
+
export function getLightData(lights, genContext) {
|
|
386
416
|
const lightData = new Array();
|
|
387
417
|
const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
|
|
388
418
|
|
|
@@ -395,8 +425,12 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
|
|
|
395
425
|
|
|
396
426
|
const lightDefinitionName = threeLightTypeToMaterialXNodeName(light.type);
|
|
397
427
|
|
|
398
|
-
if
|
|
399
|
-
|
|
428
|
+
if(!lightDefinitionName){
|
|
429
|
+
continue; // Unsupported light type
|
|
430
|
+
}
|
|
431
|
+
if (!lightTypesBound[lightDefinitionName]) {
|
|
432
|
+
if(debug) console.error("MaterialX: Light type not registered in context. Make sure to register light types before using them.", lightDefinitionName);
|
|
433
|
+
}
|
|
400
434
|
|
|
401
435
|
const wp = light.getWorldPosition(new THREE.Vector3());
|
|
402
436
|
const wq = light.getWorldQuaternion(new THREE.Quaternion());
|
|
@@ -408,8 +442,8 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
|
|
|
408
442
|
// float cosDir = dot(result.direction, -light.direction);
|
|
409
443
|
// float spotAttenuation = smoothstep(low, high, cosDir);
|
|
410
444
|
|
|
411
|
-
const outerAngleRad =
|
|
412
|
-
const innerAngleRad = outerAngleRad * (1 -
|
|
445
|
+
const outerAngleRad = /** @type {THREE.SpotLight} */ (light).angle;
|
|
446
|
+
const innerAngleRad = outerAngleRad * (1 - /** @type {THREE.SpotLight} */ (light).penumbra);
|
|
413
447
|
const inner_angle = Math.cos(innerAngleRad);
|
|
414
448
|
const outer_angle = Math.cos(outerAngleRad);
|
|
415
449
|
|
|
@@ -420,7 +454,7 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
|
|
|
420
454
|
color: new THREE.Color().fromArray(light.color.toArray()),
|
|
421
455
|
// Luminous efficacy for converting radiant power in watts (W) to luminous flux in lumens (lm) at a wavelength of 555 nm.
|
|
422
456
|
// Also, three.js lights don't have PI scale baked in, but MaterialX does, so we need to divide by PI for point and spot lights.
|
|
423
|
-
intensity: light.intensity * (
|
|
457
|
+
intensity: light.intensity * (/** @type {THREE.PointLight} */ (light).isPointLight ? 683.0 / 3.1415 : /** @type {THREE.SpotLight} */ (light).isSpotLight ? 683.0 / 3.1415 : 1.0),
|
|
424
458
|
decay_rate: 2.0,
|
|
425
459
|
// Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
|
|
426
460
|
inner_angle: inner_angle,
|
|
@@ -453,8 +487,13 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
|
|
|
453
487
|
|
|
454
488
|
/**
|
|
455
489
|
* Get uniform values for a shader
|
|
490
|
+
* @param {any} shaderStage
|
|
491
|
+
* @param {Callbacks} loaders
|
|
492
|
+
* @param {string} searchPath
|
|
493
|
+
* @returns {Object<string, THREE.Uniform>}
|
|
456
494
|
*/
|
|
457
|
-
export function getUniformValues(shaderStage
|
|
495
|
+
export function getUniformValues(shaderStage, loaders, searchPath) {
|
|
496
|
+
/** @type {Object<string, THREE.Uniform>} */
|
|
458
497
|
const threeUniforms = {};
|
|
459
498
|
|
|
460
499
|
const uniformBlocks = shaderStage.getUniformBlocks()
|
|
@@ -468,8 +507,8 @@ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Lo
|
|
|
468
507
|
const value = variable.getValue()?.getData();
|
|
469
508
|
const uniformName = variable.getVariable();
|
|
470
509
|
const type = variable.getType().getName();
|
|
471
|
-
if (debug) console.log("Adding uniform", { path: variable.getPath(), name: uniformName, value: value, type: type });
|
|
472
510
|
threeUniforms[uniformName] = toThreeUniform(uniforms, type, value, uniformName, loaders, searchPath);
|
|
511
|
+
if (debug) console.log("Adding uniform", { path: variable.getPath(), type: type, name: uniformName, value: threeUniforms[uniformName], },);
|
|
473
512
|
}
|
|
474
513
|
}
|
|
475
514
|
}
|
|
@@ -477,7 +516,11 @@ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Lo
|
|
|
477
516
|
return threeUniforms;
|
|
478
517
|
}
|
|
479
518
|
|
|
480
|
-
|
|
519
|
+
/**
|
|
520
|
+
* @param {THREE.ShaderMaterial} material
|
|
521
|
+
* @param {any} shaderStage
|
|
522
|
+
*/
|
|
523
|
+
export function generateMaterialPropertiesForUniforms(material, shaderStage) {
|
|
481
524
|
|
|
482
525
|
const uniformBlocks = shaderStage.getUniformBlocks()
|
|
483
526
|
for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
|
|
@@ -501,22 +544,27 @@ export function generateMaterialPropertiesForUniforms(material: THREE.ShaderMate
|
|
|
501
544
|
break;
|
|
502
545
|
}
|
|
503
546
|
if (key) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
547
|
+
if (material.hasOwnProperty(key)) {
|
|
548
|
+
if (debug) console.warn(`[MaterialX] Uniform ${uniformName} already exists in material as property ${key}, skipping.`);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
Object.defineProperty(material, key, {
|
|
552
|
+
get: function () {
|
|
553
|
+
return this.uniforms?.[uniformName].value
|
|
554
|
+
},
|
|
555
|
+
set: function (v) {
|
|
556
|
+
const uniforms = this.uniforms;
|
|
557
|
+
if (!uniforms || !uniforms[uniformName]) {
|
|
558
|
+
console.warn(`[MaterialX] Uniform ${uniformName} not found in ${this.name} uniforms`);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
this.uniforms[uniformName].value = v;
|
|
562
|
+
this.uniformsNeedUpdate = true;
|
|
513
563
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
517
|
-
});
|
|
564
|
+
});
|
|
565
|
+
}
|
|
518
566
|
}
|
|
519
567
|
}
|
|
520
568
|
}
|
|
521
569
|
}
|
|
522
|
-
}
|
|
570
|
+
}
|