@needle-tools/materialx 1.0.1-next.19d0723 → 1.0.1-next.31390e3
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 +1 -3
- package/codegen/register_types.ts +0 -2
- package/package.json +1 -1
- package/src/{materialx.helper.ts → helper.js} +205 -144
- package/src/loader/loader.needle.ts +38 -25
- package/src/loader/loader.three.ts +394 -138
- package/src/materialx.ts +100 -133
- package/src/textureHelper.ts +6 -6
- package/src/utils.ts +4 -39
- package/src/materialx.material.ts +0 -220
- package/src/materialx.types.d.ts +0 -50
package/README.md
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
import { TypeStore } from "@needle-tools/engine"
|
|
3
3
|
|
|
4
4
|
// Import types
|
|
5
|
-
import { MaterialXMaterial } from "../src/materialx.material.js";
|
|
6
5
|
import { MaterialXUniformUpdate } from "../src/loader/loader.needle.js";
|
|
7
6
|
|
|
8
7
|
// Register types
|
|
9
|
-
TypeStore.add("MaterialXMaterial", MaterialXMaterial);
|
|
10
8
|
TypeStore.add("MaterialXUniformUpdate", MaterialXUniformUpdate);
|
package/package.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { getParam, getWorldDirection } from '@needle-tools/engine';
|
|
7
7
|
import * as THREE from 'three';
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
const debug = getParam("debugmaterialx");
|
|
10
10
|
|
|
11
11
|
const IMAGE_PROPERTY_SEPARATOR = "_";
|
|
12
12
|
const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
|
|
@@ -20,7 +20,8 @@ const IMAGE_PATH_SEPARATOR = "/";
|
|
|
20
20
|
* @param {Object} capabilities
|
|
21
21
|
* @returns {THREE.Texture}
|
|
22
22
|
*/
|
|
23
|
-
export function prepareEnvTexture(texture, capabilities)
|
|
23
|
+
export function prepareEnvTexture(texture, capabilities)
|
|
24
|
+
{
|
|
24
25
|
let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type);
|
|
25
26
|
newTexture.wrapS = THREE.RepeatWrapping;
|
|
26
27
|
newTexture.anisotropy = capabilities.getMaxAnisotropy();
|
|
@@ -38,12 +39,15 @@ export function prepareEnvTexture(texture, capabilities) {
|
|
|
38
39
|
* @param {any} dimension
|
|
39
40
|
* @returns {THREE.Uniform}
|
|
40
41
|
*/
|
|
41
|
-
function fromVector(value, dimension)
|
|
42
|
+
function fromVector(value, dimension)
|
|
43
|
+
{
|
|
42
44
|
let outValue;
|
|
43
|
-
if (value)
|
|
45
|
+
if (value)
|
|
46
|
+
{
|
|
44
47
|
outValue = [...value.data()];
|
|
45
48
|
}
|
|
46
|
-
else
|
|
49
|
+
else
|
|
50
|
+
{
|
|
47
51
|
outValue = [];
|
|
48
52
|
for (let i = 0; i < dimension; ++i)
|
|
49
53
|
outValue.push(0.0);
|
|
@@ -54,16 +58,23 @@ function fromVector(value, dimension) {
|
|
|
54
58
|
|
|
55
59
|
/**
|
|
56
60
|
* Get Three uniform from MaterialX matrix
|
|
61
|
+
* @param {mx.matrix} matrix
|
|
62
|
+
* @param {mx.matrix.size} dimension
|
|
57
63
|
*/
|
|
58
|
-
function fromMatrix(matrix
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
function fromMatrix(matrix, dimension)
|
|
65
|
+
{
|
|
66
|
+
let vec = [];
|
|
67
|
+
if (matrix)
|
|
68
|
+
{
|
|
69
|
+
for (let i = 0; i < matrix.numRows(); ++i)
|
|
70
|
+
{
|
|
71
|
+
for (let k = 0; k < matrix.numColumns(); ++k)
|
|
72
|
+
{
|
|
63
73
|
vec.push(matrix.getItem(i, k));
|
|
64
74
|
}
|
|
65
75
|
}
|
|
66
|
-
} else
|
|
76
|
+
} else
|
|
77
|
+
{
|
|
67
78
|
for (let i = 0; i < dimension; ++i)
|
|
68
79
|
vec.push(0.0);
|
|
69
80
|
}
|
|
@@ -71,99 +82,125 @@ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"
|
|
|
71
82
|
return vec;
|
|
72
83
|
}
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
export type Loaders = {
|
|
76
|
-
getTexture: (path: string) => THREE.Texture;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
85
|
/**
|
|
80
86
|
* Get Three uniform from MaterialX value
|
|
81
87
|
* @param {mx.Uniform.type} type
|
|
82
88
|
* @param {mx.Uniform.value} value
|
|
83
89
|
* @param {mx.Uniform.name} name
|
|
84
90
|
* @param {mx.Uniforms} uniforms
|
|
85
|
-
* @param {
|
|
91
|
+
* @param {THREE.textureLoader} textureLoader
|
|
86
92
|
* @param {string} searchPath
|
|
87
93
|
* @param {boolean} flipY
|
|
88
94
|
*/
|
|
89
|
-
function toThreeUniform(type
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, flipY)
|
|
96
|
+
{
|
|
97
|
+
let outValue = null;
|
|
98
|
+
switch (type)
|
|
99
|
+
{
|
|
92
100
|
case 'float':
|
|
93
101
|
case 'integer':
|
|
94
102
|
case 'boolean':
|
|
95
|
-
|
|
103
|
+
outValue = value;
|
|
96
104
|
break;
|
|
97
105
|
case 'vector2':
|
|
98
|
-
|
|
106
|
+
outValue = fromVector(value, 2);
|
|
99
107
|
break;
|
|
100
108
|
case 'vector3':
|
|
101
109
|
case 'color3':
|
|
102
|
-
|
|
110
|
+
outValue = fromVector(value, 3);
|
|
111
|
+
break;
|
|
103
112
|
case 'vector4':
|
|
104
113
|
case 'color4':
|
|
105
|
-
|
|
114
|
+
outValue = fromVector(value, 4);
|
|
115
|
+
break;
|
|
106
116
|
case 'matrix33':
|
|
107
|
-
|
|
117
|
+
outValue = fromMatrix(value, 9);
|
|
118
|
+
break;
|
|
108
119
|
case 'matrix44':
|
|
109
|
-
|
|
120
|
+
outValue = fromMatrix(value, 16);
|
|
121
|
+
break;
|
|
110
122
|
case 'filename':
|
|
111
|
-
if (value)
|
|
123
|
+
if (value)
|
|
124
|
+
{
|
|
112
125
|
// Cache / reuse texture to avoid reload overhead.
|
|
113
126
|
// Note: that data blobs and embedded data textures are not cached as they are transient data.
|
|
114
127
|
let checkCache = false;
|
|
115
128
|
let texturePath = searchPath + IMAGE_PATH_SEPARATOR + value;
|
|
116
|
-
if (value.startsWith('blob:'))
|
|
129
|
+
if (value.startsWith('blob:'))
|
|
130
|
+
{
|
|
117
131
|
texturePath = value;
|
|
118
132
|
if (debug) console.log('Load blob URL:', texturePath);
|
|
119
133
|
checkCache = false;
|
|
120
134
|
}
|
|
121
|
-
else if (value.startsWith('http'))
|
|
135
|
+
else if (value.startsWith('http'))
|
|
136
|
+
{
|
|
122
137
|
texturePath = value;
|
|
123
138
|
if (debug) console.log('Load HTTP URL:', texturePath);
|
|
124
139
|
}
|
|
125
|
-
else if (value.startsWith('data:'))
|
|
140
|
+
else if (value.startsWith('data:'))
|
|
141
|
+
{
|
|
126
142
|
texturePath = value;
|
|
127
143
|
checkCache = false;
|
|
128
144
|
if (debug) console.log('Load data URL:', texturePath);
|
|
129
145
|
}
|
|
130
146
|
const cachedTexture = checkCache && THREE.Cache.get(texturePath);
|
|
131
|
-
if (cachedTexture)
|
|
132
|
-
|
|
133
|
-
|
|
147
|
+
if (cachedTexture)
|
|
148
|
+
{
|
|
149
|
+
// Get texture from cache
|
|
150
|
+
outValue = cachedTexture;
|
|
151
|
+
if (debug) console.log('Use cached texture: ', texturePath, outValue);
|
|
134
152
|
}
|
|
135
|
-
else
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
else
|
|
154
|
+
{
|
|
155
|
+
outValue = textureLoader.load(
|
|
156
|
+
texturePath,
|
|
157
|
+
function (texture) {
|
|
158
|
+
if (debug) console.log('Load new texture: ' + texturePath, texture);
|
|
159
|
+
outValue = texture;
|
|
160
|
+
|
|
161
|
+
// Add texture to ThreeJS cache
|
|
162
|
+
if (checkCache)
|
|
163
|
+
THREE.Cache.add(texturePath, texture);
|
|
164
|
+
},
|
|
165
|
+
undefined,
|
|
166
|
+
function (error) {
|
|
167
|
+
console.error('Error loading texture: ', error);
|
|
168
|
+
});
|
|
169
|
+
|
|
138
170
|
// Set address & filtering mode
|
|
139
|
-
if (
|
|
140
|
-
|
|
171
|
+
if (outValue)
|
|
172
|
+
setTextureParameters(outValue, name, uniforms, flipY);
|
|
141
173
|
}
|
|
142
174
|
}
|
|
143
175
|
break;
|
|
144
176
|
case 'samplerCube':
|
|
145
177
|
case 'string':
|
|
146
|
-
|
|
178
|
+
break;
|
|
147
179
|
default:
|
|
148
180
|
const key = type + ':' + name;
|
|
149
|
-
if (!valueTypeWarningMap.has(key))
|
|
181
|
+
if (!valueTypeWarningMap.has(key))
|
|
182
|
+
{
|
|
150
183
|
valueTypeWarningMap.set(key, true);
|
|
151
184
|
console.warn('MaterialX: Unsupported uniform type: ' + type + ' for uniform: ' + name, value);
|
|
152
185
|
}
|
|
153
|
-
|
|
186
|
+
outValue = null;
|
|
154
187
|
}
|
|
188
|
+
|
|
189
|
+
return outValue;
|
|
155
190
|
}
|
|
156
191
|
|
|
157
|
-
const valueTypeWarningMap = new Map
|
|
192
|
+
const valueTypeWarningMap = new Map();
|
|
158
193
|
|
|
159
194
|
/**
|
|
160
195
|
* Get Three wrapping mode
|
|
161
196
|
* @param {mx.TextureFilter.wrap} mode
|
|
162
197
|
* @returns {THREE.Wrapping}
|
|
163
198
|
*/
|
|
164
|
-
function getWrapping(mode)
|
|
199
|
+
function getWrapping(mode)
|
|
200
|
+
{
|
|
165
201
|
let wrap;
|
|
166
|
-
switch (mode)
|
|
202
|
+
switch (mode)
|
|
203
|
+
{
|
|
167
204
|
case 1:
|
|
168
205
|
wrap = THREE.ClampToEdgeWrapping;
|
|
169
206
|
break;
|
|
@@ -185,9 +222,12 @@ function getWrapping(mode) {
|
|
|
185
222
|
* @param {mx.TextureFilter.minFilter} type
|
|
186
223
|
* @param {mx.TextureFilter.generateMipmaps} generateMipmaps
|
|
187
224
|
*/
|
|
188
|
-
function getMinFilter(type, generateMipmaps)
|
|
189
|
-
|
|
190
|
-
|
|
225
|
+
function getMinFilter(type, generateMipmaps)
|
|
226
|
+
{
|
|
227
|
+
/** @type {THREE.TextureFilter} */
|
|
228
|
+
let filterType = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
|
|
229
|
+
if (type === 0)
|
|
230
|
+
{
|
|
191
231
|
filterType = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
|
|
192
232
|
}
|
|
193
233
|
return filterType;
|
|
@@ -200,22 +240,25 @@ function getMinFilter(type, generateMipmaps) {
|
|
|
200
240
|
* @param {mx.Uniforms} uniforms
|
|
201
241
|
* @param {mx.TextureFilter.generateMipmaps} generateMipmaps
|
|
202
242
|
*/
|
|
203
|
-
function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
|
|
243
|
+
function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
|
|
244
|
+
{
|
|
204
245
|
const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
|
|
205
246
|
const base = name.substring(0, idx) || name;
|
|
206
247
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
248
|
+
texture.generateMipmaps = generateMipmaps;
|
|
249
|
+
texture.wrapS = THREE.RepeatWrapping;
|
|
250
|
+
texture.wrapT = THREE.RepeatWrapping;
|
|
251
|
+
texture.magFilter = THREE.LinearFilter;
|
|
252
|
+
texture.flipY = flipY;
|
|
212
253
|
|
|
213
|
-
if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
|
|
254
|
+
if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
|
|
255
|
+
{
|
|
214
256
|
const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData();
|
|
215
257
|
texture.wrapS = getWrapping(uaddressmode);
|
|
216
258
|
}
|
|
217
259
|
|
|
218
|
-
if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
|
|
260
|
+
if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
|
|
261
|
+
{
|
|
219
262
|
const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData();
|
|
220
263
|
texture.wrapT = getWrapping(vaddressmode);
|
|
221
264
|
}
|
|
@@ -227,7 +270,8 @@ function setTextureParameters(texture, name, uniforms, flipY = true, generateMip
|
|
|
227
270
|
/**
|
|
228
271
|
* Return the global light rotation matrix
|
|
229
272
|
*/
|
|
230
|
-
export function getLightRotation()
|
|
273
|
+
export function getLightRotation()
|
|
274
|
+
{
|
|
231
275
|
return new THREE.Matrix4().makeRotationY(Math.PI / 2);
|
|
232
276
|
}
|
|
233
277
|
|
|
@@ -236,27 +280,36 @@ export function getLightRotation() {
|
|
|
236
280
|
* @param {mx.Document} doc
|
|
237
281
|
* @returns {Array.<mx.Node>}
|
|
238
282
|
*/
|
|
239
|
-
export function findLights(doc
|
|
240
|
-
|
|
241
|
-
|
|
283
|
+
export function findLights(doc)
|
|
284
|
+
{
|
|
285
|
+
let lights = [];
|
|
286
|
+
for (let node of doc.getNodes())
|
|
287
|
+
{
|
|
242
288
|
if (node.getType() === "lightshader")
|
|
243
289
|
lights.push(node);
|
|
244
290
|
}
|
|
245
291
|
return lights;
|
|
246
292
|
}
|
|
247
293
|
|
|
248
|
-
let lightTypesBound = {};
|
|
249
|
-
|
|
250
294
|
/**
|
|
251
295
|
* Register lights in shader generation context
|
|
252
|
-
* @param {
|
|
296
|
+
* @param {Object} mx MaterialX Module
|
|
297
|
+
* @param {Array.<mx.Node>} lights Light nodes
|
|
253
298
|
* @param {mx.GenContext} genContext Shader generation context
|
|
299
|
+
* @returns {Array.<mx.Node>}
|
|
254
300
|
*/
|
|
255
|
-
export async function registerLights(mx
|
|
256
|
-
|
|
257
|
-
const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
|
|
301
|
+
export async function registerLights(mx, lights, genContext)
|
|
302
|
+
{
|
|
258
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
|
+
|
|
307
|
+
const lightTypesBound = {};
|
|
308
|
+
const lightData = [];
|
|
259
309
|
let lightId = 1;
|
|
310
|
+
let lightCount = 0;
|
|
311
|
+
const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
|
|
312
|
+
|
|
260
313
|
// All light types so that we have NodeDefs for them
|
|
261
314
|
const defaultLightRigXml = `<?xml version="1.0"?>
|
|
262
315
|
<materialx version="1.39">
|
|
@@ -274,7 +327,7 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
|
|
|
274
327
|
|
|
275
328
|
// Load default light rig XML to ensure we have all light types available
|
|
276
329
|
const lightRigDoc = mx.createDocument();
|
|
277
|
-
await mx.readFromXmlString(lightRigDoc, defaultLightRigXml
|
|
330
|
+
await mx.readFromXmlString(lightRigDoc, defaultLightRigXml);
|
|
278
331
|
const document = mx.createDocument();
|
|
279
332
|
const stdlib = mx.loadStandardLibraries(genContext);
|
|
280
333
|
document.setDataLibrary(stdlib);
|
|
@@ -287,14 +340,16 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
|
|
|
287
340
|
|
|
288
341
|
// Register types only – we get these from the default light rig XML above
|
|
289
342
|
// This is needed to ensure that the light shaders are bound for each light type
|
|
290
|
-
for (let light of defaultLights)
|
|
343
|
+
for (let light of defaultLights)
|
|
344
|
+
{
|
|
291
345
|
const lightDef = light.getNodeDef();
|
|
292
346
|
if (debug) console.log("Default light node definition", lightDef);
|
|
293
347
|
if (!lightDef) continue;
|
|
294
348
|
|
|
295
349
|
const lightName = lightDef.getName();
|
|
296
350
|
if (debug) console.log("Registering default light", { lightName, lightDef });
|
|
297
|
-
if (!lightTypesBound[lightName])
|
|
351
|
+
if (!lightTypesBound[lightName])
|
|
352
|
+
{
|
|
298
353
|
// TODO check if we need to bind light shader for each three.js light instead of once per type
|
|
299
354
|
if (debug) console.log("Bind light shader for node", { lightName, lightId, lightDef });
|
|
300
355
|
lightTypesBound[lightName] = lightId;
|
|
@@ -303,40 +358,52 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
|
|
|
303
358
|
}
|
|
304
359
|
|
|
305
360
|
if (debug) console.log("Light types bound in MaterialX context", lightTypesBound);
|
|
306
|
-
}
|
|
307
361
|
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.
|
|
319
|
-
|
|
362
|
+
// MaterialX light nodes
|
|
363
|
+
for (let light of lights)
|
|
364
|
+
{
|
|
365
|
+
// Skip if light does not have a node definition
|
|
366
|
+
if (!("getNodeDef" in light)) continue;
|
|
367
|
+
|
|
368
|
+
let nodeDef = light.getNodeDef();
|
|
369
|
+
let nodeName = nodeDef.getName();
|
|
370
|
+
if (!lightTypesBound[nodeName])
|
|
371
|
+
{
|
|
372
|
+
if (debug) console.log("bind light shader for node", { nodeName, lightId, nodeDef });
|
|
373
|
+
lightTypesBound[nodeName] = lightId;
|
|
374
|
+
mx.HwShaderGenerator.bindLightShader(nodeDef, lightId++, genContext);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const lightDirection = light.getValueElement("direction").getValue().getData().data();
|
|
378
|
+
const lightColor = light.getValueElement("color").getValue().getData().data();
|
|
379
|
+
const lightIntensity = light.getValueElement("intensity").getValue().getData();
|
|
380
|
+
|
|
381
|
+
let rotatedLightDirection = new THREE.Vector3(...lightDirection)
|
|
382
|
+
rotatedLightDirection.transformDirection(getLightRotation())
|
|
383
|
+
|
|
384
|
+
lightData.push({
|
|
385
|
+
type: lightTypesBound[nodeName],
|
|
386
|
+
direction: rotatedLightDirection,
|
|
387
|
+
color: new THREE.Vector3(...lightColor),
|
|
388
|
+
intensity: lightIntensity,
|
|
389
|
+
});
|
|
320
390
|
}
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
type LightData = {
|
|
324
|
-
type: number, // Light type ID
|
|
325
|
-
position: THREE.Vector3, // Position in world space
|
|
326
|
-
direction: THREE.Vector3, // Direction in world space
|
|
327
|
-
color: THREE.Color, // Color of the light
|
|
328
|
-
intensity: number, // Intensity of the light
|
|
329
|
-
decay_rate: number, // Decay rate for point and spot lights
|
|
330
|
-
inner_angle: number, // Inner angle for spot lights
|
|
331
|
-
outer_angle: number, // Outer angle for spot lights
|
|
332
|
-
}
|
|
333
391
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
392
|
+
const threeLightTypeToMaterialXNodeName = (threeLightType) => {
|
|
393
|
+
switch (threeLightType) {
|
|
394
|
+
case 'PointLight':
|
|
395
|
+
return 'ND_point_light';
|
|
396
|
+
case 'DirectionalLight':
|
|
397
|
+
return 'ND_directional_light';
|
|
398
|
+
case 'SpotLight':
|
|
399
|
+
return 'ND_spot_light';
|
|
400
|
+
default:
|
|
401
|
+
console.warn('MaterialX: Unsupported light type: ' + threeLightType);
|
|
402
|
+
return 'ND_point_light'; // Default to point light
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
if (debug) console.log("Registering lights in MaterialX context", lights, lightData);
|
|
340
407
|
|
|
341
408
|
// Three.js lights
|
|
342
409
|
for (let light of lights) {
|
|
@@ -348,82 +415,76 @@ export function getLightData(lights: any, genContext: any): { lightData: LightDa
|
|
|
348
415
|
const lightDefinitionName = threeLightTypeToMaterialXNodeName(light.type);
|
|
349
416
|
|
|
350
417
|
if (!lightTypesBound[lightDefinitionName])
|
|
351
|
-
|
|
418
|
+
{
|
|
419
|
+
lightTypesBound[lightDefinitionName] = lightId;
|
|
420
|
+
const nodeDef = null;
|
|
421
|
+
mx.HwShaderGenerator.bindLightShader(nodeDef, lightId++, genContext);
|
|
422
|
+
}
|
|
352
423
|
|
|
353
424
|
const wp = light.getWorldPosition(new THREE.Vector3());
|
|
354
|
-
const wd = getWorldDirection(light, new THREE.Vector3(0,
|
|
355
|
-
|
|
356
|
-
// Shader math from the generated MaterialX shader:
|
|
357
|
-
// float low = min(light.inner_angle, light.outer_angle);
|
|
358
|
-
// float high = light.inner_angle;
|
|
359
|
-
// float cosDir = dot(result.direction, -light.direction);
|
|
360
|
-
// float spotAttenuation = smoothstep(low, high, cosDir);
|
|
361
|
-
|
|
362
|
-
const outerAngleRad = light.angle;
|
|
363
|
-
const innerAngleRad = outerAngleRad * (1 - light.penumbra);
|
|
364
|
-
const inner_angle = Math.cos(innerAngleRad);
|
|
365
|
-
const outer_angle = Math.cos(outerAngleRad);
|
|
366
|
-
|
|
425
|
+
const wd = getWorldDirection(light, new THREE.Vector3(0,0,-1));
|
|
367
426
|
lightData.push({
|
|
368
427
|
type: lightTypesBound[lightDefinitionName],
|
|
369
428
|
position: wp.clone(),
|
|
370
429
|
direction: wd.clone(),
|
|
371
|
-
color: new THREE.
|
|
372
|
-
//
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
// Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
|
|
377
|
-
inner_angle: inner_angle,
|
|
378
|
-
outer_angle: outer_angle,
|
|
430
|
+
color: new THREE.Vector3().fromArray(light.color.toArray()),
|
|
431
|
+
intensity: light.intensity, // Scale intensity for spot lights
|
|
432
|
+
decay_rate: 2.0, // physically-based default decay rate
|
|
433
|
+
inner_angle: 1.0,
|
|
434
|
+
outer_angle: 2.0,
|
|
379
435
|
});
|
|
380
436
|
}
|
|
381
437
|
|
|
382
438
|
// Count the number of lights that are not empty
|
|
383
|
-
|
|
439
|
+
lightCount = lightData.length;
|
|
384
440
|
|
|
385
441
|
// If we don't have enough entries in lightData, fill with empty lights
|
|
386
|
-
|
|
442
|
+
if (lightData.length < maxLightCount)
|
|
443
|
+
{
|
|
387
444
|
const emptyLight = {
|
|
388
445
|
type: 0, // Default light type
|
|
389
446
|
position: new THREE.Vector3(0, 0, 0),
|
|
390
447
|
direction: new THREE.Vector3(0, 0, -1),
|
|
391
|
-
color: new THREE.
|
|
392
|
-
intensity: 0
|
|
393
|
-
decay_rate: 2
|
|
394
|
-
inner_angle: 0
|
|
395
|
-
outer_angle: 0
|
|
448
|
+
color: new THREE.Vector3(0, 0, 0),
|
|
449
|
+
intensity: 0,
|
|
450
|
+
decay_rate: 2,
|
|
451
|
+
inner_angle: 0,
|
|
452
|
+
outer_angle: 0,
|
|
396
453
|
};
|
|
397
|
-
lightData.
|
|
454
|
+
while (lightData.length < maxLightCount) {
|
|
455
|
+
lightData.push(emptyLight);
|
|
456
|
+
}
|
|
398
457
|
}
|
|
399
458
|
|
|
400
|
-
if (
|
|
459
|
+
if (debug) console.log("Registered lights in MaterialX context", lightTypesBound, lightData);
|
|
401
460
|
|
|
402
461
|
return { lightData, lightCount };
|
|
403
462
|
}
|
|
404
463
|
|
|
405
464
|
/**
|
|
406
465
|
* Get uniform values for a shader
|
|
466
|
+
* @param {mx.shaderStage} shaderStage
|
|
467
|
+
* @param {THREE.TextureLoader} textureLoader
|
|
407
468
|
*/
|
|
408
|
-
export function getUniformValues(shaderStage
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
for (let i = 0; i < uniforms.size(); ++i)
|
|
469
|
+
export function getUniformValues(shaderStage, textureLoader, searchPath, flipY)
|
|
470
|
+
{
|
|
471
|
+
let threeUniforms = {};
|
|
472
|
+
|
|
473
|
+
const uniformBlocks = Object.values(shaderStage.getUniformBlocks());
|
|
474
|
+
uniformBlocks.forEach(uniforms =>
|
|
475
|
+
{
|
|
476
|
+
if (!uniforms.empty())
|
|
477
|
+
{
|
|
478
|
+
for (let i = 0; i < uniforms.size(); ++i)
|
|
479
|
+
{
|
|
418
480
|
const variable = uniforms.get(i);
|
|
419
481
|
const value = variable.getValue()?.getData();
|
|
420
482
|
const name = variable.getVariable();
|
|
421
|
-
if (debug) console.log("Adding uniform", { path: variable.getPath(), name, value, type: variable.getType().getName() });
|
|
422
483
|
threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms,
|
|
423
|
-
|
|
484
|
+
textureLoader, searchPath, flipY));
|
|
424
485
|
}
|
|
425
486
|
}
|
|
426
|
-
}
|
|
487
|
+
});
|
|
427
488
|
|
|
428
489
|
return threeUniforms;
|
|
429
490
|
}
|