@needle-tools/engine 4.6.2 → 4.7.0-next.22483b4

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.
Files changed (36) hide show
  1. package/dist/needle-engine.bundle-BnGp0ASs.min.js +1604 -0
  2. package/dist/{needle-engine.bundle-DmYMLdWP.umd.cjs → needle-engine.bundle-CP5AJL1A.umd.cjs} +213 -184
  3. package/dist/{needle-engine.bundle-DGcStTA7.js → needle-engine.bundle-RgZNbAgp.js} +8716 -8444
  4. package/dist/needle-engine.js +2 -2
  5. package/dist/needle-engine.min.js +1 -1
  6. package/dist/needle-engine.umd.cjs +1 -1
  7. package/lib/engine/engine_context.js +3 -2
  8. package/lib/engine/engine_context.js.map +1 -1
  9. package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +5 -3
  10. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +124 -117
  11. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
  12. package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.d.ts +10 -0
  13. package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.js +452 -0
  14. package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.js.map +1 -0
  15. package/lib/engine-components/postprocessing/Effects/Antialiasing.js +8 -1
  16. package/lib/engine-components/postprocessing/Effects/Antialiasing.js.map +1 -1
  17. package/lib/engine-components/postprocessing/Effects/BloomEffect.js +0 -3
  18. package/lib/engine-components/postprocessing/Effects/BloomEffect.js.map +1 -1
  19. package/lib/engine-components/postprocessing/PostProcessingHandler.js +43 -11
  20. package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
  21. package/lib/engine-components/postprocessing/utils.d.ts +1 -0
  22. package/lib/engine-components/postprocessing/utils.js.map +1 -1
  23. package/package.json +2 -2
  24. package/plugins/types/userconfig.d.ts +2 -0
  25. package/plugins/vite/alias.js +48 -38
  26. package/plugins/vite/index.js +2 -0
  27. package/plugins/vite/materialx.js +30 -0
  28. package/plugins/vite/transform.js +1 -0
  29. package/src/engine/engine_context.ts +3 -2
  30. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +155 -142
  31. package/src/engine-components/export/usdz/extensions/NodeMaterialConverter.ts +532 -0
  32. package/src/engine-components/postprocessing/Effects/Antialiasing.ts +8 -1
  33. package/src/engine-components/postprocessing/Effects/BloomEffect.ts +0 -2
  34. package/src/engine-components/postprocessing/PostProcessingHandler.ts +50 -12
  35. package/src/engine-components/postprocessing/utils.ts +1 -0
  36. package/dist/needle-engine.bundle-D0XWaCQs.min.js +0 -1575
@@ -0,0 +1,532 @@
1
+ import {Color, Texture, Vector2, Vector3, Vector4} from "three";
2
+
3
+ import {
4
+ formatsWithAlphaChannel,
5
+ makeNameSafeForUSD
6
+ } from "../ThreeUSDZExporter.js";
7
+
8
+ const materialRoot = '</StageRoot/Materials';
9
+ declare type TextureMap = {[name: string]: {texture: Texture, scale?: Vector4}};
10
+
11
+ type MeshPhysicalNodeMaterial = import("three/src/materials/nodes/MeshPhysicalNodeMaterial.js").default;
12
+
13
+ function buildNodeMaterial( nodeMaterial: MeshPhysicalNodeMaterial, materialName: string, textures: TextureMap ) {
14
+
15
+ const collectedNodeTypes = new Map();
16
+ const getUniqueNodeName = (node) => {
17
+ const type = node["type___needle"];
18
+ const typeMap = collectedNodeTypes.get(type) || new Map();
19
+ collectedNodeTypes.set(type, typeMap);
20
+
21
+ if (!typeMap.has(node)) {
22
+ const name = `${type}${typeMap.size ? `_${typeMap.size}` : ""}`;
23
+ typeMap.set(node, name);
24
+ }
25
+
26
+ return typeMap.get(node);
27
+ };
28
+
29
+ const colorNodesToBeExported = nodeMaterial.colorNode ? getNodesToExport(nodeMaterial.colorNode) : [];
30
+ const colorOutputString = nodeMaterial.colorNode
31
+ ? `color3f inputs:diffuseColor.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(colorNodesToBeExported.values().next().value)}.outputs:out>`
32
+ : "";
33
+
34
+ const roughnessNodesToBeExported = nodeMaterial.roughnessNode ? getNodesToExport(nodeMaterial.roughnessNode) : [];
35
+ const roughnessOutputString = nodeMaterial.roughnessNode
36
+ ? `float inputs:roughness.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(roughnessNodesToBeExported.values().next().value)}.outputs:out>`
37
+ : "";
38
+
39
+ const normalNodesToBeExported = nodeMaterial.normalNode ? getNodesToExport(nodeMaterial.normalNode) : [];
40
+ const normalOutputString = nodeMaterial.normalNode
41
+ ? `float3 inputs:normal.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(normalNodesToBeExported.values().next().value)}.outputs:out>`
42
+ : "";
43
+
44
+ const metallicNodesToBeExported = nodeMaterial.metalnessNode ? getNodesToExport(nodeMaterial.metalnessNode) : [];
45
+ const metallicOutputString = nodeMaterial.metalnessNode
46
+ ? `float inputs:metallic.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(metallicNodesToBeExported.values().next().value)}.outputs:out>`
47
+ : "";
48
+
49
+ const combinedSetOfAllNodesToExport = new Set([...colorNodesToBeExported, ...roughnessNodesToBeExported, ...normalNodesToBeExported, ...metallicNodesToBeExported])
50
+
51
+ const shaderOutput = getShadersFromNodes(combinedSetOfAllNodesToExport, materialName, textures, getUniqueNodeName);
52
+
53
+ console.debug(shaderOutput);
54
+
55
+ return `
56
+
57
+ def Material "${materialName}" ${nodeMaterial.name ? `(
58
+ displayName = "${nodeMaterial.name}"
59
+ )` : ''}
60
+ {
61
+ token outputs:mtlx:surface.connect = ${materialRoot}/${materialName}/N_mtlxsurface.outputs:surface>
62
+
63
+ def Shader "N_mtlxsurface"
64
+ {
65
+ uniform token info:id = "ND_UsdPreviewSurface_surfaceshader"
66
+ ${colorOutputString}
67
+ ${roughnessOutputString}
68
+ ${normalOutputString}
69
+ ${metallicOutputString}
70
+ token outputs:surface
71
+ }
72
+
73
+ ${shaderOutput}
74
+
75
+ }`;
76
+ }
77
+
78
+ function getNodesToExport( rootNode: any ): Set<any> {
79
+
80
+ const getNodeType = (node) => {
81
+ if (node.nodeType) return node.nodeType;
82
+ switch (node.type) {
83
+ case "TimerNode": return "float";
84
+ case "TextureNode": return undefined;
85
+ case "ConvertNode": return node.convertTo;
86
+ default: return undefined;
87
+ }
88
+ };
89
+
90
+ const getSetOfAllNodes = (rootNode: any): Set<any> => {
91
+ const setOfAllNodes:Set<any> = new Set();
92
+
93
+ const collectNode = (node) => {
94
+ if (!node.isNode || setOfAllNodes.has(node)) return;
95
+ if (!node["nodeType___needle"]){
96
+ node["nodeType___needle"] = getNodeType(node);
97
+ }
98
+
99
+ if (node.shaderNode){
100
+ node["type___needle"] = "ShaderCallNodeInternal";
101
+ node["shaderNodeLayoutName___needle"] = node.shaderNode.layout.name.slice(3);
102
+ }
103
+ else {
104
+ node["type___needle"] = node.type;
105
+ }
106
+ setOfAllNodes.add(node);
107
+
108
+ for (const key in node) {
109
+ if (node[key]?.isNode) {
110
+
111
+ collectNode(node[key]);
112
+ node["nodeType___needle"] ||= node[key]["nodeType___needle"];
113
+ }
114
+ if (Array.isArray(node[key])) {
115
+ node[key].forEach(child => {
116
+ if (child.isNode) {
117
+ collectNode(child)
118
+
119
+ node["nodeType___needle"] ||= child["nodeType___needle"];
120
+ }
121
+ });
122
+ }
123
+ }
124
+ };
125
+
126
+ collectNode(rootNode);
127
+
128
+ return setOfAllNodes;
129
+ }
130
+
131
+ const isSelfConversionNode = (node) => {
132
+
133
+
134
+ if (node.type === "ConvertNode"){
135
+ if (node.convertTo === node.node["nodeType___needle"])
136
+ {
137
+ return true;
138
+ }
139
+ else if (node.node.type === "ConstNode")
140
+ {
141
+ if (node.convertTo === "vec4" && node.node.value.isVector4){
142
+ return true;
143
+ }
144
+ else if (node.convertTo === "vec3" && node.node.value.isVector3){
145
+ return true;
146
+ }
147
+ else if (node.convertTo === "vec2" && node.node.value.isVector2){
148
+ return true;
149
+ }
150
+ else if (node.convertTo === "color" && node.node.value.isColor){
151
+ return true;
152
+ }
153
+ else if (node.convertTo === "float" && typeof node.node.value === 'number'){
154
+ return true;
155
+ }
156
+ }
157
+ else if (node.node.type == "SplitNode"){
158
+ if (node.convertTo == "float" && node.node.components.length === 1){
159
+ return true;
160
+ }
161
+ }
162
+ }
163
+
164
+ return false;
165
+ }
166
+
167
+ const getNextValidNode = (node) => {
168
+ while (nodeShouldNotBeExported(node)) {
169
+ if (!node.node && node.shaderNode){
170
+ node = node.inputNodes[0];
171
+ }
172
+ else{
173
+ node = node.node ?? node.aNode ?? node.bNode ?? node.cNode;
174
+ }
175
+ }
176
+ return node;
177
+ };
178
+
179
+ const nodeShouldNotBeExported = (node: any | undefined): boolean => {
180
+ const ignorableNodeTypes = ["UniformNode", "UniformGroupNode", "ShaderNodeInternal"]
181
+ return !node || isSelfConversionNode(node) || ignorableNodeTypes.includes(node["type___needle"]) || node["type___needle"] === undefined;
182
+ }
183
+
184
+ const getParent = (currNode, nodeSet) => {
185
+ for (const node of nodeSet) {
186
+ for (const key in node) {
187
+ if (node[key]?.isNode && node[key] === currNode) {
188
+ return { parent: node, label: key };
189
+ }
190
+ if (Array.isArray(node[key])) {
191
+ const child = node[key].find(childNode => childNode.isNode && childNode === currNode);
192
+ if (child) return { parent: node, label: key };
193
+ }
194
+ }
195
+ }
196
+ return null;
197
+ };
198
+
199
+ const updateNodeReferences = (node, refKeys) => {
200
+ if (node.shaderNode){
201
+ node.inputNodes[0] = getNextValidNode(node.inputNodes[0]);
202
+ }
203
+ else if (Array.isArray(node.nodes)) {
204
+ for(let i = 0; i < node.nodes.length; i++){
205
+ if (node.nodes[i] && nodeShouldNotBeExported(node.nodes[i])) {
206
+ node.nodes[i] = getNextValidNode(node.nodes[i]);
207
+ }
208
+ }
209
+ }
210
+ else{
211
+ refKeys.forEach(key => {
212
+ if (node[key] && nodeShouldNotBeExported(node[key])) {
213
+ node[key] = getNextValidNode(node[key]);
214
+ }
215
+ });
216
+ }
217
+ };
218
+
219
+ const setMixNodeMixToFloat = (node) => {
220
+ if (node.type === "MathNode" && node.method === "mix"){
221
+ node.cNode["nodeType___needle"] = "float";
222
+ if (node.cNode.type === "ConvertNode"){
223
+ node.cNode.convertTo = "float";
224
+ }
225
+ }
226
+ }
227
+
228
+ const setConstNodeTypeToParentType = (node, parentResponse) => {
229
+ if (!(parentResponse.label === 'cNode' && parentResponse.parent.type === "MathNode" && parentResponse.parent.method === "mix")){
230
+ if (parentResponse.parent.type === "JoinNode"){
231
+ node["nodeType___needle"] = "float";
232
+ }
233
+ else {
234
+ node["nodeType___needle"] = parentResponse.parent["nodeType___needle"];
235
+ }
236
+ }
237
+ }
238
+
239
+ const isConvertVector4ToColorNode = (node) => (
240
+ node?.type === "ConvertNode" && node["nodeType___needle"] === "color" && node.node["nodeType___needle"] === "vec4"
241
+ );
242
+
243
+ const createVec3ToColorConversionNode = (node, allNodes) => {
244
+ node.convertTo = "vec3";
245
+ node["nodeType___needle"] = "vec3";
246
+
247
+ const newNode = {
248
+ type: "ConvertNode",
249
+ convertTo: "color",
250
+ node: node,
251
+ isNode: true,
252
+ nodeType___needle: "color",
253
+ type___needle: "ConvertNode"
254
+ };
255
+
256
+ const parentInfo = getParent(node, allNodes);
257
+ if (parentInfo?.parent) {
258
+ parentInfo.parent[parentInfo.label] = newNode;
259
+ }
260
+
261
+ return newNode;
262
+ }
263
+
264
+ const isConvertFromTextureNode = (node) => (
265
+ node?.type === "ConvertNode" && node.node.type === "TextureNode" && node["nodeType___needle"] !== node.node["nodeType___needle"]
266
+ );
267
+
268
+ const pruneNodes = (allNodes: Set<any>) : Set<any> => {
269
+
270
+ const nodesToBeExported: Set<any> = new Set();
271
+ for (let node of allNodes) {
272
+ if (nodeShouldNotBeExported(node)) continue;
273
+
274
+ // Math mix nodes take a mix input that should always be a float, the typing gets messed up here because
275
+ // the other inputs that are being mixed can be anything and if we have a convert or a const that goes
276
+ // into the mix input, it gets set as whatever the output of the mix should be, not float. Here we make
277
+ // sure it will be float
278
+ setMixNodeMixToFloat(node);
279
+
280
+ if (node.type == "SplitNode"){
281
+ const parentResponse = getParent(node, allNodes);
282
+ if (node.components.length === 1){
283
+ node["nodeType___needle"] = "float";
284
+ }
285
+ else if(parentResponse) {
286
+ // TODO: this may not be sufficient and it may be better to always count the component lengths
287
+ node["nodeType___needle"] = parentResponse.parent["nodeType___needle"];
288
+ }
289
+ else throw new Error("SplitNode without parent found, this should not happen");
290
+ }
291
+
292
+ // Here we check child nodes to update the connections if they will be ignored later
293
+ updateNodeReferences(node, ["node", "aNode", "bNode", "cNode"]);
294
+
295
+ // Const nodes don't always have a type and sometimes they need to be converted from a value of 0 -> [0, 0, 0]
296
+ // this function does that conversion
297
+ if (node.type == "ConstNode" && node.nodeType == null){
298
+ setConstNodeTypeToParentType(node, getParent(node, allNodes));
299
+ }
300
+
301
+ if (isConvertVector4ToColorNode(node)) {
302
+ nodesToBeExported.add(createVec3ToColorConversionNode(node, allNodes));
303
+ }
304
+
305
+ // We want Texture nodes to export the type they need, rather than something else and then convert
306
+ // here if we have a convert above a Texture that we missed on the first pass because there was
307
+ // some other node in between to prune, set the type on the Texture correctly and kill the convert
308
+ if (isConvertFromTextureNode(node)){
309
+ node.node["nodeType___needle"] = node.convertTo;
310
+ const parentInfo = getParent(node, allNodes);
311
+ if (parentInfo?.parent) {
312
+ parentInfo.parent[parentInfo.label] = node.node;
313
+ }
314
+
315
+ node = node.node;
316
+ }
317
+ nodesToBeExported.add(node);
318
+ }
319
+
320
+ return nodesToBeExported;
321
+ }
322
+
323
+ const setOfAllNodes = getSetOfAllNodes(rootNode);
324
+
325
+ const prunedNodes = pruneNodes(setOfAllNodes);
326
+
327
+ return prunedNodes;
328
+ }
329
+
330
+ function getConstValueString(value: any, type: string){
331
+ switch (type) {
332
+ case "float4":
333
+ return value.isVector4
334
+ ? `(${value.x}, ${value.y}, ${value.z}, ${value.w})`
335
+ : `(${value}, ${value}, ${value}, ${value})`;
336
+ case "float3":
337
+ return value.isVector3
338
+ ? `(${value.x}, ${value.y}, ${value.z})`
339
+ : `(${value}, ${value}, ${value})`;
340
+ case "float2":
341
+ return value.isVector2
342
+ ? `(${value.x}, ${value.y})`
343
+ : `(${value}, ${value})`;
344
+ case "color3f":
345
+ return value.isColor
346
+ ? `(${value.r}, ${value.g}, ${value.b})`
347
+ : `(${value}, ${value}, ${value})`;
348
+ default:
349
+ return (value.isVector4 || value.isVector3 || value.isVector2)
350
+ ? `${value.x}`
351
+ : value.isColor
352
+ ? `${value.r}`
353
+ : `${value}`;
354
+ }
355
+ }
356
+
357
+ function TSLNodeToUsdShadeString(node:any, materialName:string, getUniqueNodeName, textures: TextureMap) {
358
+ const pad = ' ';
359
+ const getType = (nodeType) => {
360
+ const types = {
361
+ float: "float",
362
+ vec2: "vector2",
363
+ vec3: "vector3",
364
+ vec4: "vector4",
365
+ color: "color3"
366
+ };
367
+ return types[nodeType] || "float";
368
+ };
369
+
370
+ const getUsdType = (nodeType) => {
371
+ const usdTypes = {
372
+ float: "float",
373
+ vec2: "float2",
374
+ vec3: "float3",
375
+ vec4: "float4",
376
+ color: "color3f"
377
+ };
378
+ return usdTypes[nodeType] || "float";
379
+ };
380
+
381
+ const type = node["type___needle"];
382
+
383
+ const ndType = node["nodeType___needle"];
384
+
385
+ const mtlxNdType = getType(ndType);
386
+ let usdNdType = getUsdType(ndType);
387
+
388
+ let usdShadeNodeName = "";
389
+ const inputs = new Array<string>();
390
+ switch (type) {
391
+ case "UniformGroupNode":
392
+ case "UniformNode":
393
+ // break out of node loop
394
+ return "";
395
+ case "TimerNode":
396
+ usdShadeNodeName = "time_float";
397
+ break;
398
+ case "ConstNode":
399
+ usdShadeNodeName = "constant_" + mtlxNdType;
400
+ inputs.push(`${usdNdType} inputs:value = ${getConstValueString(node.value, usdNdType)}`);
401
+ break;
402
+ case "JoinNode":
403
+ usdShadeNodeName = "combine" + node.nodes.length + "_" + mtlxNdType;
404
+ let i = 1;
405
+ for (const childNode of node.nodes) {
406
+ inputs.push(`float inputs:in${i++}.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(childNode)}.outputs:out>`);
407
+ }
408
+ break;
409
+ case "ConvertNode":
410
+ const inputType = getType(node.node["nodeType___needle"]);
411
+ usdShadeNodeName = "convert_" + inputType + "_" + mtlxNdType;
412
+ if (node.node)
413
+ inputs.push(`${getUsdType(node.node["nodeType___needle"])} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.node)}.outputs:out>`);
414
+ break;
415
+ case "MathNode":
416
+ usdShadeNodeName = node.method + "_" + mtlxNdType;
417
+
418
+ if (node.aNode && !node.bNode)
419
+ inputs.push(`${getUsdType(node.aNode["nodeType___needle"])} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
420
+ if (node.aNode && node.bNode && !node.cNode) {
421
+
422
+ inputs.push(`${getUsdType(node.aNode["nodeType___needle"])} inputs:in1.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
423
+ inputs.push(`${getUsdType(node.bNode["nodeType___needle"])} inputs:in2.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.bNode)}.outputs:out>`);
424
+ }
425
+
426
+ if (node.aNode && node.bNode && node.cNode && node.method == "clamp") {
427
+ inputs.push(`${getUsdType(node.aNode["nodeType___needle"])} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
428
+ inputs.push(`${getUsdType(node.bNode["nodeType___needle"])} inputs:low.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.bNode)}.outputs:out>`);
429
+ inputs.push(`${getUsdType(node.cNode["nodeType___needle"])} inputs:high.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.cNode)}.outputs:out>`);
430
+ }
431
+
432
+ if (node.aNode && node.bNode && node.cNode && node.method == "mix") {
433
+ inputs.push(`${getUsdType(node.aNode["nodeType___needle"])} inputs:fg.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.bNode)}.outputs:out>`);
434
+ inputs.push(`${getUsdType(node.bNode["nodeType___needle"])} inputs:bg.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
435
+ inputs.push(`float inputs:mix.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.cNode)}.outputs:out>`);
436
+ }
437
+ break;
438
+ case "OperatorNode":
439
+ let opName = "";
440
+ switch (node.op) {
441
+ case "*" : opName = "multiply"; break;
442
+ case "/" : opName = "divide"; break;
443
+ case "+" : opName = "add"; break;
444
+ case "-" : opName = "subtract"; break;
445
+ }
446
+ usdShadeNodeName = opName + "_" + mtlxNdType;
447
+ if (node.aNode && !node.bNode)
448
+ inputs.push(`${getUsdType(node.aNode["nodeType___needle"])} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
449
+ if (node.aNode && node.bNode) {
450
+ const aNodeType = getUsdType(node.aNode["nodeType___needle"])
451
+ const bNodeType = getUsdType(node.bNode["nodeType___needle"])
452
+
453
+ // todo: make this more generic / support all combinations
454
+ if (aNodeType === 'color3f' && bNodeType === 'float' || bNodeType === 'float' && bNodeType === 'color3f') {
455
+ usdShadeNodeName = opName + "_color3FA";
456
+ }
457
+
458
+ inputs.push(`${aNodeType} inputs:in1.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.aNode)}.outputs:out>`);
459
+ inputs.push(`${bNodeType} inputs:in2.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.bNode)}.outputs:out>`);
460
+ }
461
+ break;
462
+ case "TextureNode":
463
+ if (node.uvNode){
464
+ usdShadeNodeName = "tiledimage_" + mtlxNdType;
465
+
466
+ inputs.push(`float2 inputs:texcoord.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.uvNode)}.outputs:out>`);
467
+ }
468
+ else{
469
+ usdShadeNodeName = "image_" + mtlxNdType;
470
+ }
471
+
472
+ const texture = node._value;
473
+ const isRGBA = formatsWithAlphaChannel.includes( texture.format );
474
+ const textureName = texName(texture);
475
+
476
+ inputs.push( `asset inputs:file = @textures/${textureName}.${isRGBA ? 'png' : 'jpg'}@` );
477
+ textures[ textureName ] = { texture, scale: undefined };
478
+ break;
479
+ case "NormalMapNode":
480
+ usdNdType = "float3"
481
+ usdShadeNodeName = "normalmap";
482
+
483
+ inputs.push(`${usdNdType} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.node)}.outputs:out>`);
484
+ break;
485
+ case "AttributeNode":
486
+ usdShadeNodeName = "geompropvalue_" + mtlxNdType;
487
+ inputs.push(`string inputs:geomprop = "st"`);
488
+
489
+ break;
490
+ case "ShaderCallNodeInternal":
491
+ usdShadeNodeName = node["shaderNodeLayoutName___needle"] + "_" + mtlxNdType;
492
+ inputs.push(`${usdNdType} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.inputNodes[0])}.outputs:out>`);
493
+
494
+ break;
495
+ case "SplitNode":
496
+ usdShadeNodeName = "swizzle_" + getType(node.node["nodeType___needle"]) + "_" + mtlxNdType;
497
+ inputs.push(`${getUsdType(node.node["nodeType___needle"])} inputs:in.connect = ${materialRoot}/${materialName}/${getUniqueNodeName(node.node)}.outputs:out>`);
498
+ inputs.push(`string inputs:channels = "${node.components}"`);
499
+ break;
500
+
501
+ }
502
+
503
+ // todo: better way to pad here for sure...
504
+ return `
505
+ ${pad}def Shader "${getUniqueNodeName(node)}"
506
+ ${pad}{
507
+ ${pad}uniform token info:id = "ND_${usdShadeNodeName}"
508
+ ${pad}${usdNdType} outputs:out
509
+ ${pad}${inputs.length > 0 ? inputs.join("\n ") : ""}
510
+ ${pad}}
511
+ `;
512
+ }
513
+
514
+ function getShadersFromNodes( nodes: Set<any>, materialName: string, textures: TextureMap, getUniqueNodeName){
515
+
516
+ let shaderOutput = "";
517
+ for (const node of nodes) {
518
+ shaderOutput += TSLNodeToUsdShadeString(node, materialName, getUniqueNodeName, textures);
519
+ }
520
+
521
+ return shaderOutput;
522
+ }
523
+
524
+ function texName(tex: Texture) {
525
+ // If we have a source, we only want to use the source's id, not the texture's id
526
+ // to avoid exporting the same underlying data multiple times.
527
+ return makeNameSafeForUSD(tex.name) + '_' + (tex.source?.id ?? tex.id);
528
+ }
529
+
530
+ export {
531
+ buildNodeMaterial
532
+ };
@@ -1,10 +1,13 @@
1
1
  import { MODULES } from "../../../engine/engine_modules.js";
2
2
  import { serializable } from "../../../engine/engine_serialization.js";
3
+ import { getParam } from "../../../engine/engine_utils.js";
3
4
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
4
5
  import { VolumeParameter } from "../VolumeParameter.js";
5
6
  import { registerCustomEffectType } from "../VolumeProfile.js";
6
7
 
7
8
 
9
+ const debug = getParam("debugpost");
10
+
8
11
 
9
12
  export enum QualityLevel {
10
13
  LOW = 0,
@@ -32,15 +35,19 @@ export class Antialiasing extends PostProcessingEffect {
32
35
 
33
36
  onCreateEffect(): EffectProviderResult {
34
37
  const effect = new MODULES.POSTPROCESSING.MODULE.SMAAEffect({
35
- preset: MODULES.POSTPROCESSING.MODULE.SMAAPreset.HIGH,
38
+ preset: this.preset?.value ?? MODULES.POSTPROCESSING.MODULE.SMAAPreset.HIGH,
36
39
  edgeDetectionMode: MODULES.POSTPROCESSING.MODULE.EdgeDetectionMode.LUMA,
37
40
  // Keep predication mode disabled (default) since it looks better
38
41
  // predicationMode: MODULES.POSTPROCESSING.MODULE.PredicationMode.DEPTH,
39
42
  });
40
43
 
41
44
  this.preset.onValueChanged = (newValue) => {
45
+ if(debug) console.log("Antialiasing preset changed to", newValue, effect);
42
46
  effect.applyPreset(newValue);
43
47
  };
48
+ // setInterval(()=> {
49
+ // effect.applyPreset(Math.floor(Math.random()*3))
50
+ // }, 1000)
44
51
 
45
52
  // effect.edgeDetectionMaterial.edgeDetectionThreshold = .01;
46
53
 
@@ -93,8 +93,6 @@ export class BloomEffect extends PostProcessingEffect {
93
93
  radius: 0.85, // default value
94
94
  intensity: this.intensity.value,
95
95
  });
96
- // @ts-ignore Well... it's protected but bloom needs this :(
97
- bloom.setAttributes(EffectAttribute.CONVOLUTION);
98
96
  }
99
97
 
100
98
  this.intensity.onValueChanged = newValue => {