From 20022bcd4a8981c1537f093fabcbbadad598d6fc Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 12 Dec 2023 18:42:20 -0800 Subject: [PATCH 01/17] Update three.js to r152 This changelist updates the version of three.js to r152 in the MaterialX Web Viewer, making a handful of adjustments to account for changes in texture storage conventions. --- javascript/MaterialXView/package-lock.json | 32 ++++++------ javascript/MaterialXView/package.json | 2 +- javascript/MaterialXView/source/helper.js | 60 +++------------------- javascript/MaterialXView/source/index.js | 4 +- 4 files changed, 27 insertions(+), 71 deletions(-) diff --git a/javascript/MaterialXView/package-lock.json b/javascript/MaterialXView/package-lock.json index 7a8e6f71d7..d5338a3517 100644 --- a/javascript/MaterialXView/package-lock.json +++ b/javascript/MaterialXView/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "dat.gui": "^0.7.9", - "three": "^0.136.0", + "three": "^0.152.2", "webpack": "^5.89.0" }, "devDependencies": { @@ -161,9 +161,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.8", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", - "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==", + "version": "8.44.9", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.9.tgz", + "integrity": "sha512-6yBxcvwnnYoYT1Uk2d+jvIfsuP4mb2EdIxFnrPABj5a/838qe5bGkNLFOiipX4ULQ7XVQvTxOh7jO+BTAiqsEw==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -806,9 +806,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001566", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", - "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "funding": [ { "type": "opencollective", @@ -1245,9 +1245,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.609", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.609.tgz", - "integrity": "sha512-ihiCP7PJmjoGNuLpl7TjNA8pCQWu09vGyjlPYw1Rqww4gvNuCcmvl+44G+2QyJ6S2K4o+wbTS++Xz0YN8Q9ERw==" + "version": "1.4.613", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.613.tgz", + "integrity": "sha512-r4x5+FowKG6q+/Wj0W9nidx7QO31BJwmR2uEo+Qh3YLGQ8SbBAFuDFpTxzly/I2gsbrFwBuIjrMp423L3O5U3w==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -3542,9 +3542,9 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/three": { - "version": "0.136.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.136.0.tgz", - "integrity": "sha512-+fEMX7nYLz2ZesVP/dyifli5Jf8gR3XPAnFJveQ80aMhibFduzrADnjMbARXh8+W9qLK7rshJCjAIL/6cDxC+A==" + "version": "0.152.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.152.2.tgz", + "integrity": "sha512-Ff9zIpSfkkqcBcpdiFo2f35vA9ZucO+N8TNacJOqaEE6DrB0eufItVMib8bK8Pcju/ZNT6a7blE1GhTpkdsILw==" }, "node_modules/thunky": { "version": "1.1.0", @@ -4066,9 +4066,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz", + "integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/javascript/MaterialXView/package.json b/javascript/MaterialXView/package.json index 8912357208..9518156883 100644 --- a/javascript/MaterialXView/package.json +++ b/javascript/MaterialXView/package.json @@ -11,7 +11,7 @@ "license": "ISC", "dependencies": { "dat.gui": "^0.7.9", - "three": "^0.136.0", + "three": "^0.152.2", "webpack": "^5.89.0" }, "devDependencies": { diff --git a/javascript/MaterialXView/source/helper.js b/javascript/MaterialXView/source/helper.js index 111dfd9b5d..98441a605f 100644 --- a/javascript/MaterialXView/source/helper.js +++ b/javascript/MaterialXView/source/helper.js @@ -19,59 +19,15 @@ const IMAGE_PATH_SEPARATOR = "/"; */ export function prepareEnvTexture(texture, capabilities) { - const rgbaTexture = RGBToRGBA_Float(texture); - rgbaTexture.wrapS = THREE.RepeatWrapping; - rgbaTexture.anisotropy = capabilities.getMaxAnisotropy(); - rgbaTexture.minFilter = THREE.LinearMipmapLinearFilter; - rgbaTexture.magFilter = THREE.LinearFilter; - rgbaTexture.generateMipmaps = true; - rgbaTexture.needsUpdate = true; + let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type); + newTexture.wrapS = THREE.RepeatWrapping; + newTexture.anisotropy = capabilities.getMaxAnisotropy(); + newTexture.minFilter = THREE.LinearMipmapLinearFilter; + newTexture.magFilter = THREE.LinearFilter; + newTexture.generateMipmaps = true; + newTexture.needsUpdate = true; - return rgbaTexture; -} - -/** - * Create a new (half)float texture containing an alpha channel with a value of 1 from a RGB (half)float texture. - * @param {THREE.Texture} texture - */ -function RGBToRGBA_Float(texture) -{ - const w = texture.image.width; - const h = texture.image.height; - const dataSize = texture.image.data.length; - const stride = dataSize / (w *h); - // No need to convert to RGBA if already 4 channel. - if (stride == 3) - { - const rgbData = texture.image.data; - const length = (rgbData.length / 3) * 4; - let rgbaData; - - switch (texture.type) - { - case THREE.FloatType: - rgbaData = new Float32Array(length); - break; - case THREE.HalfFloatType: - rgbaData = new Uint16Array(length); - break; - default: - break; - } - - if (rgbaData) - { - for (let i = 0; i < length / 4; i++) - { - rgbaData[(i * 4) + 0] = rgbData[(i * 3) + 0]; - rgbaData[(i * 4) + 1] = rgbData[(i * 3) + 1]; - rgbaData[(i * 4) + 2] = rgbData[(i * 3) + 2]; - rgbaData[(i * 4) + 3] = 1.0; - } - return new THREE.DataTexture(rgbaData, texture.image.width, texture.image.height, THREE.RGBAFormat, texture.type); - } - } - return texture; + return newTexture; } /** diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js index 56e2e1f5a2..fa729ce4a6 100644 --- a/javascript/MaterialXView/source/index.js +++ b/javascript/MaterialXView/source/index.js @@ -83,10 +83,10 @@ function init() viewer.getEditor().initialize(); const hdrLoader = viewer.getHdrLoader(); - const fileLooder = viewer.getFileLoader(); + const fileLoader = viewer.getFileLoader(); Promise.all([ new Promise(resolve => hdrLoader.setDataType(THREE.FloatType).load('Lights/san_giuseppe_bridge_split.hdr', resolve)), - new Promise(resolve => fileLooder.load('Lights/san_giuseppe_bridge_split.mtlx', resolve)), + new Promise(resolve => fileLoader.load('Lights/san_giuseppe_bridge_split.mtlx', resolve)), new Promise(resolve => hdrLoader.setDataType(THREE.FloatType).load('Lights/irradiance/san_giuseppe_bridge_split.hdr', resolve)), new Promise(function (resolve) { MaterialX().then((module) => { From 1ef4619977c146549032122cabcd1baaa1a1ddd4 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 16 Dec 2023 22:29:59 -0800 Subject: [PATCH 02/17] Web viewer HDRI improvements - Load HDR images in half-float format, improving render performance and browser compatibility. - Clarify HDR image names. --- javascript/MaterialXView/source/index.js | 8 ++++---- javascript/MaterialXView/source/viewer.js | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js index fa729ce4a6..6f0b6e44b3 100644 --- a/javascript/MaterialXView/source/index.js +++ b/javascript/MaterialXView/source/index.js @@ -85,18 +85,18 @@ function init() const hdrLoader = viewer.getHdrLoader(); const fileLoader = viewer.getFileLoader(); Promise.all([ - new Promise(resolve => hdrLoader.setDataType(THREE.FloatType).load('Lights/san_giuseppe_bridge_split.hdr', resolve)), + new Promise(resolve => hdrLoader.load('Lights/san_giuseppe_bridge_split.hdr', resolve)), + new Promise(resolve => hdrLoader.load('Lights/irradiance/san_giuseppe_bridge_split.hdr', resolve)), new Promise(resolve => fileLoader.load('Lights/san_giuseppe_bridge_split.mtlx', resolve)), - new Promise(resolve => hdrLoader.setDataType(THREE.FloatType).load('Lights/irradiance/san_giuseppe_bridge_split.hdr', resolve)), new Promise(function (resolve) { MaterialX().then((module) => { resolve(module); }); }) - ]).then(async ([loadedRadianceTexture, loadedLightSetup, loadedIrradianceTexture, mxIn]) => + ]).then(async ([radianceTexture, irradianceTexture, lightRigXml, mxIn]) => { // Initialize viewer + lighting - await viewer.initialize(mxIn, renderer, loadedRadianceTexture, loadedLightSetup, loadedIrradianceTexture); + await viewer.initialize(mxIn, renderer, radianceTexture, irradianceTexture, lightRigXml); // Load geometry let scene = viewer.getScene(); diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index d1adfd9ef4..58e4613bae 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -1035,7 +1035,7 @@ export class Viewer // Create shader generator, generation context and "base" document which // contains the standard definition libraries and lighting elements. // - async initialize(mtlxIn, renderer, loadedRadianceTexture, loadedLightSetup, loadedIrradianceTexture) + async initialize(mtlxIn, renderer, radianceTexture, irradianceTexture, lightRigXml) { this.mx = mtlxIn; @@ -1047,30 +1047,30 @@ export class Viewer this.stdlib = this.mx.loadStandardLibraries(this.genContext); this.document.importLibrary(this.stdlib); - this.initializeLighting(renderer, loadedRadianceTexture, loadedLightSetup, loadedIrradianceTexture); + this.initializeLighting(renderer, radianceTexture, irradianceTexture, lightRigXml); - loadedRadianceTexture.mapping = THREE.EquirectangularReflectionMapping; - this.getScene().setBackgroundTexture(loadedRadianceTexture); + radianceTexture.mapping = THREE.EquirectangularReflectionMapping; + this.getScene().setBackgroundTexture(radianceTexture); } // // Load in lighting rig document and register lights with generation context // Initialize environment lighting (IBLs). // - async initializeLighting(renderer, loadedRadianceTexture, loadedLightSetup, loadedIrradianceTexture) + async initializeLighting(renderer, radianceTexture, irradianceTexture, lightRigXml) { // Load lighting setup into document const mx = this.getMx(); this.lightRigDoc = mx.createDocument(); - await mx.readFromXmlString(this.lightRigDoc, loadedLightSetup); + await mx.readFromXmlString(this.lightRigDoc, lightRigXml); this.document.importLibrary(this.lightRigDoc); // Register lights with generation context this.lights = findLights(this.document); this.lightData = registerLights(mx, this.lights, this.genContext); - this.radianceTexture = prepareEnvTexture(loadedRadianceTexture, renderer.capabilities); - this.irradianceTexture = prepareEnvTexture(loadedIrradianceTexture, renderer.capabilities); + this.radianceTexture = prepareEnvTexture(radianceTexture, renderer.capabilities); + this.irradianceTexture = prepareEnvTexture(irradianceTexture, renderer.capabilities); } getEditor() { From 95d9ee0a46c6df509f7c92f7fefc684cd9d4c092 Mon Sep 17 00:00:00 2001 From: ld-kerley <154285602+ld-kerley@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:14:40 -0800 Subject: [PATCH 03/17] Fix for custom node groups in graph editor menu (#1617) Currently if you have node definitions added to groups that aren't in the fixed list that MaterialXGraphEditor understands, then they won't be added to the menu. --- source/MaterialXGraphEditor/Graph.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index fc682e8f05..f0d1791143 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -1248,6 +1248,7 @@ void Graph::createNodeUIList(mx::DocumentPtr doc) auto nodeDefs = doc->getNodeDefs(); std::unordered_map> groupToNodeDef; + std::vector groupList = std::vector(NODE_GROUP_ORDER.begin(), NODE_GROUP_ORDER.end()); for (const auto& nodeDef : nodeDefs) { @@ -1257,6 +1258,12 @@ void Graph::createNodeUIList(mx::DocumentPtr doc) group = NODE_GROUP_ORDER.back(); } + // If the group is not in the groupList already (seeded by NODE_GROUP_ORDER) then add it. + if (std::find(groupList.begin(), groupList.end(), group) == groupList.end()) + { + groupList.emplace_back(group); + } + if (groupToNodeDef.find(group) == groupToNodeDef.end()) { groupToNodeDef[group] = std::vector(); @@ -1264,7 +1271,7 @@ void Graph::createNodeUIList(mx::DocumentPtr doc) groupToNodeDef[group].push_back(nodeDef); } - for (const auto& group : NODE_GROUP_ORDER) + for (const auto& group : groupList) { auto it = groupToNodeDef.find(group); if (it != groupToNodeDef.end()) From cbff01a8d27a5017166dfdbb9a77e96b51827c69 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 19 Dec 2023 17:08:46 -0500 Subject: [PATCH 04/17] Update UI library used for Web Viewer (#1618) - Switch to `lil-gui` which fixes a number of dat-gui issues including all input which did not show up anymore (regression). - Same GUI lib as used for ThreeJS examples for consistency. --- javascript/MaterialXView/package-lock.json | 6 ++++++ javascript/MaterialXView/package.json | 2 +- javascript/MaterialXView/source/viewer.js | 20 ++++---------------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/javascript/MaterialXView/package-lock.json b/javascript/MaterialXView/package-lock.json index d5338a3517..2755bef7ea 100644 --- a/javascript/MaterialXView/package-lock.json +++ b/javascript/MaterialXView/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "dat.gui": "^0.7.9", + "lil-gui": "^0.19.1", "three": "^0.152.2", "webpack": "^5.89.0" }, @@ -2246,6 +2247,11 @@ "shell-quote": "^1.8.1" } }, + "node_modules/lil-gui": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.19.1.tgz", + "integrity": "sha512-9dbIg+UxS8RIROI6OH5gV2KrVE0Cn37bcLOQGF2GKN8ibTxDrUSLzzZfkQR82LnZsgs7DEZOOGfn3zhtd6hk0Q==" + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", diff --git a/javascript/MaterialXView/package.json b/javascript/MaterialXView/package.json index 9518156883..4c369406bd 100644 --- a/javascript/MaterialXView/package.json +++ b/javascript/MaterialXView/package.json @@ -10,7 +10,7 @@ "author": "", "license": "ISC", "dependencies": { - "dat.gui": "^0.7.9", + "lil-gui": "^0.19.1", "three": "^0.152.2", "webpack": "^5.89.0" }, diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index 58e4613bae..b986406d76 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -9,7 +9,7 @@ import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'; import { prepareEnvTexture, getLightRotation, findLights, registerLights, getUniformValues } from './helper.js' import { Group } from 'three'; -import { GUI } from 'dat.gui'; +import GUI from 'lil-gui'; const ALL_GEOMETRY_SPECIFIER = "*"; const NO_GEOMETRY_SPECIFIER = ""; @@ -445,13 +445,10 @@ export class Editor // clearFolders() { - Array.from(document.getElementsByClassName('folder')).forEach( + Array.from(document.getElementsByClassName('lil-gui')).forEach( function (element, index, array) { if (element.className) { - let child = element.firstElementChild; - if (child && child.className == 'dg') { - element.remove(); - } + element.remove(); } } ); @@ -466,16 +463,7 @@ export class Editor // Search document to find GUI elements and remove them // If not done then multiple GUIs will be created from different // threads. - Array.from(document.getElementsByClassName('dg')).forEach( - function (element, index, array) { - if (element.className) { - element.remove(); - } - } - ); - - // Create new GUI. - this._gui = new GUI(); + this.clearFolders(); this._gui.open(); return this._gui; From 00e5f734315db84db28b1d3bcab63755bbc4e7d9 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 19 Dec 2023 15:27:31 -0800 Subject: [PATCH 05/17] Minor improvements to web viewer - Assign a title to the Property Editor for clarity. - Launch the viewer with the Property Editor closed. --- javascript/MaterialXView/source/viewer.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index b986406d76..e5990b8566 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -460,11 +460,9 @@ export class Editor // Create the editor initialize() { - // Search document to find GUI elements and remove them - // If not done then multiple GUIs will be created from different - // threads. this.clearFolders(); - this._gui.open(); + this._gui.title("Property Editor"); + this._gui.close(); return this._gui; } From 39138cf570a9857570d995c38e6120451696a6d7 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 19 Dec 2023 17:19:08 -0800 Subject: [PATCH 06/17] Additional improvements to web viewer - Merge separate code paths for GUI initialization and folder clearing. - Use the GUI constructor for title assignment. --- javascript/MaterialXView/source/index.js | 4 +-- javascript/MaterialXView/source/viewer.js | 43 ++++++++--------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js index 6f0b6e44b3..ddd1ec8ffc 100644 --- a/javascript/MaterialXView/source/index.js +++ b/javascript/MaterialXView/source/index.js @@ -41,7 +41,7 @@ function init() materialsSelect.value = materialFilename; materialsSelect.addEventListener('change', (e) => { materialFilename = e.target.value; - viewer.getEditor().clearFolders(); + viewer.getEditor().initialize(); viewer.getMaterial().loadMaterials(viewer, materialFilename); viewer.getEditor().updateProperties(0.9); viewer.getScene().setUpdateTransforms(); @@ -122,7 +122,7 @@ function init() setLoadingCallback(file => { materialFilename = file.fullPath || file.name; - viewer.getEditor().clearFolders(); + viewer.getEditor().initialize(); viewer.getMaterial().loadMaterials(viewer, materialFilename); viewer.getEditor().updateProperties(0.9); viewer.getScene().setUpdateTransforms(); diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index e5990b8566..01006530c8 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -416,6 +416,21 @@ export class Scene */ export class Editor { + // Initialize the editor, clearing any elements from previous materials. + initialize() + { + Array.from(document.getElementsByClassName('lil-gui')).forEach( + function (element, index, array) { + if (element.className) { + element.remove(); + } + } + ); + + this._gui = new GUI( { title: "Property Editor" } ); + this._gui.close(); + } + // Update ui properties // - Hide close button // - Update transparency so scene shows through if overlapping @@ -439,34 +454,6 @@ export class Editor } } - // - // Clear folders with children contain elements for any previous material - // and recreate top gui. - // - clearFolders() - { - Array.from(document.getElementsByClassName('lil-gui')).forEach( - function (element, index, array) { - if (element.className) { - element.remove(); - } - } - ); - - // Create new GUI. - this._gui = new GUI(); - } - - // Create the editor - initialize() - { - this.clearFolders(); - this._gui.title("Property Editor"); - this._gui.close(); - - return this._gui; - } - getGUI() { return this._gui; From 77aaa8a4bc241b397ac9870467ffb9fb84d7ab51 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 20 Dec 2023 10:00:55 -0800 Subject: [PATCH 07/17] Update JavaScript packages This changelist updates all referenced JavaScript packages to their latest version via 'npm update'. --- javascript/MaterialXTest/package-lock.json | 163 +++++++++++---------- javascript/MaterialXTest/package.json | 4 +- javascript/MaterialXView/package-lock.json | 47 +++--- javascript/MaterialXView/package.json | 2 +- 4 files changed, 110 insertions(+), 106 deletions(-) diff --git a/javascript/MaterialXTest/package-lock.json b/javascript/MaterialXTest/package-lock.json index 5c3b779bc7..e7d6980fd8 100644 --- a/javascript/MaterialXTest/package-lock.json +++ b/javascript/MaterialXTest/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@babel/core": "^7.23.5", - "@babel/preset-env": "^7.23.5", + "@babel/core": "^7.23.6", + "@babel/preset-env": "^7.23.6", "@babel/register": "^7.22.15", "chai": "^4.3.10", "copyfiles": "^2.4.1", @@ -59,21 +59,21 @@ } }, "node_modules/@babel/core": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", - "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.5", - "@babel/parser": "^7.23.5", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -89,12 +89,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", - "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -128,14 +128,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -144,9 +144,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.5.tgz", - "integrity": "sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.6.tgz", + "integrity": "sha512-cBXU1vZni/CpGF29iTu4YRbOZt3Wat6zCoMDxRF1MayiEc4URxOj31tT65HUM0CRpMowA3HCJaAOVOUnMf96cw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -184,9 +184,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", - "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -409,14 +409,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", - "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" }, "engines": { "node": ">=6.9.0" @@ -437,9 +437,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -990,12 +990,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz", - "integrity": "sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1516,13 +1517,13 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.5.tgz", - "integrity": "sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.6.tgz", + "integrity": "sha512-2XPn/BqKkZCpzYhUUNZ1ssXw7DcXfKQEjv/uXZUXgaebCMYmkEsfZ2yY+vv+xtXv50WmL5SGhyB6/xsWxIvvOQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.23.5", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", @@ -1562,7 +1563,7 @@ "@babel/plugin-transform-dynamic-import": "^7.23.4", "@babel/plugin-transform-exponentiation-operator": "^7.23.3", "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.3", + "@babel/plugin-transform-for-of": "^7.23.6", "@babel/plugin-transform-function-name": "^7.23.3", "@babel/plugin-transform-json-strings": "^7.23.4", "@babel/plugin-transform-literals": "^7.23.3", @@ -1649,9 +1650,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", - "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", + "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -1675,20 +1676,20 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", - "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -1696,9 +1697,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", - "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -1788,9 +1789,9 @@ } }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1868,13 +1869,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", - "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", + "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.3", + "@babel/helper-define-polyfill-provider": "^0.4.4", "semver": "^6.3.1" }, "peerDependencies": { @@ -1882,12 +1883,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", - "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.3", + "@babel/helper-define-polyfill-provider": "^0.4.4", "core-js-compat": "^3.33.1" }, "peerDependencies": { @@ -1895,12 +1896,12 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", - "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", + "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.3" + "@babel/helper-define-polyfill-provider": "^0.4.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2071,9 +2072,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001566", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", - "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "dev": true, "funding": [ { @@ -2462,9 +2463,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.609", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.609.tgz", - "integrity": "sha512-ihiCP7PJmjoGNuLpl7TjNA8pCQWu09vGyjlPYw1Rqww4gvNuCcmvl+44G+2QyJ6S2K4o+wbTS++Xz0YN8Q9ERw==", + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==", "dev": true }, "node_modules/emoji-regex": { @@ -4012,9 +4013,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true }, "node_modules/regenerator-transform": { diff --git a/javascript/MaterialXTest/package.json b/javascript/MaterialXTest/package.json index cc67644462..122ec55338 100644 --- a/javascript/MaterialXTest/package.json +++ b/javascript/MaterialXTest/package.json @@ -16,8 +16,8 @@ "author": "", "license": "ISC", "devDependencies": { - "@babel/core": "^7.23.5", - "@babel/preset-env": "^7.23.5", + "@babel/core": "^7.23.6", + "@babel/preset-env": "^7.23.6", "@babel/register": "^7.22.15", "chai": "^4.3.10", "copyfiles": "^2.4.1", diff --git a/javascript/MaterialXView/package-lock.json b/javascript/MaterialXView/package-lock.json index 2755bef7ea..474a6ff984 100644 --- a/javascript/MaterialXView/package-lock.json +++ b/javascript/MaterialXView/package-lock.json @@ -9,14 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "dat.gui": "^0.7.9", "lil-gui": "^0.19.1", "three": "^0.152.2", "webpack": "^5.89.0" }, "devDependencies": { "copy-webpack-plugin": "^8.1.1", - "html-webpack-plugin": "^5.5.4", + "html-webpack-plugin": "^5.6.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.15.1" } @@ -162,9 +161,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.9", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.9.tgz", - "integrity": "sha512-6yBxcvwnnYoYT1Uk2d+jvIfsuP4mb2EdIxFnrPABj5a/838qe5bGkNLFOiipX4ULQ7XVQvTxOh7jO+BTAiqsEw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -241,9 +240,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dependencies": { "undici-types": "~5.26.4" } @@ -1061,11 +1060,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/dat.gui": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz", - "integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==" - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1246,9 +1240,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.613", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.613.tgz", - "integrity": "sha512-r4x5+FowKG6q+/Wj0W9nidx7QO31BJwmR2uEo+Qh3YLGQ8SbBAFuDFpTxzly/I2gsbrFwBuIjrMp423L3O5U3w==" + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -1480,9 +1474,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1877,9 +1871,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.4.tgz", - "integrity": "sha512-3wNSaVVxdxcu0jd4FpQFoICdqgxs4zIQQvj+2yQKFfBOnLETQ6X5CDWdeasuGlSsooFlMkEioWDTqBv1wvw5Iw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", "dev": true, "dependencies": { "@types/html-minifier-terser": "^6.0.0", @@ -1896,7 +1890,16 @@ "url": "https://opencollective.com/html-webpack-plugin" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/htmlparser2": { diff --git a/javascript/MaterialXView/package.json b/javascript/MaterialXView/package.json index 4c369406bd..01049bf6c9 100644 --- a/javascript/MaterialXView/package.json +++ b/javascript/MaterialXView/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "copy-webpack-plugin": "^8.1.1", - "html-webpack-plugin": "^5.5.4", + "html-webpack-plugin": "^5.6.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.15.1" } From 5bd76a89efac609097674528ae781a586340ef22 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 22 Dec 2023 14:19:15 -0500 Subject: [PATCH 08/17] Add support for UI attributes in web viewer (#1623) - ui min, max, step support for property editor inputs - label ui advanced folders - enable complete vs reduced to get exposure of consistent inputs as with other utils. - fix nodedef input lookup to handle non-root nodes - use x,y,z,w for vector input names vs full name and ".0". --- javascript/MaterialXView/source/viewer.js | 139 ++++++++++++++++++++-- 1 file changed, 126 insertions(+), 13 deletions(-) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index 01006530c8..34474aeede 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -723,8 +723,10 @@ export class Material var startTranspCheckTime = performance.now(); const isTransparent = mx.isTransparentSurface(elem, gen.getTarget()); genContext.getOptions().hwTransparency = isTransparent; - // Always set to reduced as the parsing of uniforms can be very expensive in WebGL - genContext.getOptions().shaderInterfaceType = mx.ShaderInterfaceType.SHADER_INTERFACE_REDUCED; + // Always set to complete. + // Can consider option to set to reduced as the parsing of large numbers of uniforms (e.g. on shading models) + // can be quite expensive. + genContext.getOptions().shaderInterfaceType = mx.ShaderInterfaceType.SHADER_INTERFACE_COMPLETE; if (logDetailedTime) console.log(" - Transparency check time: ", performance.now() - startTranspCheckTime, "ms"); @@ -776,7 +778,7 @@ export class Material // Update property editor const gui = viewer.getEditor().getGUI(); - this.updateEditor(elem, shader, newMaterial, gui); + this.updateEditor(elem, shader, newMaterial, gui, viewer); if (logDetailedTime) console.log("- Per material generate time: ", performance.now() - startGenerateMat, "ms"); @@ -790,6 +792,9 @@ export class Material // updateEditor(elem, shader, material, gui) { + const DEFAULT_MIN = 0; + const DEFAULT_MAX = 100; + var startTime = performance.now(); const elemPath = elem.getNamePath(); @@ -825,8 +830,13 @@ export class Material continue; } - let currentNode = currentElem ? currentElem.getParent() : null; - let uiname; + let currentNode = null; + if (currentElem.getParent() && currentElem.getParent().getNamePath() != "") + { + currentNode = currentElem.getParent(); + } + let uiname = ""; + let nodeDefInput = null; if (currentNode) { let currentNodePath = currentNode.getNamePath(); @@ -843,15 +853,25 @@ export class Material // Check for ui attributes var nodeDef = currentNode.getNodeDef(); if (nodeDef) { - let input = nodeDef.getActiveInput(name); - if (input) { - uiname = input.getAttribute('uiname'); - let uifolderName = input.getAttribute('uifolder'); + // Remove node name from shader uniform name for non root nodes + let lookup_name = name.replace(currentNode.getName() + '_', ''); + nodeDefInput = nodeDef.getActiveInput(lookup_name); + if (nodeDefInput) + { + uiname = nodeDefInput.getAttribute('uiname'); + let uifolderName = nodeDefInput.getAttribute('uifolder'); if (uifolderName && uifolderName.length) { let newFolderName = currentNodePath + '/' + uifolderName; currentFolder = folderList[newFolderName]; if (!currentFolder) { - currentFolder = matUI.addFolder(uifolderName); + if (nodeDefInput.hasAttribute('uiadvanced')) + { + currentFolder = matUI.addFolder(uifolderName + " (Advanced)"); + } + else + { + currentFolder = matUI.addFolder(uifolderName); + } folderList[newFolderName] = currentFolder; } } @@ -896,14 +916,86 @@ export class Material case 'float': uniformToUpdate = material.uniforms[name]; if (uniformToUpdate && value != null) { - currentFolder.add(material.uniforms[name], 'value').name(path); + + var minValue = DEFAULT_MIN; + if (value < minValue) + { + minValue = value; + } + var maxValue = DEFAULT_MAX; + if (value > maxValue) + { + maxValue = value; + } + var step = 0; + if (nodeDefInput) { + if (nodeDefInput.hasAttribute('uimin')) + minValue = parseFloat(nodeDefInput.getAttribute('uimin')); + if (nodeDefInput.hasAttribute('uimax')) + maxValue = parseFloat(nodeDefInput.getAttribute('uimax')); + if (nodeDefInput.hasAttribute('uistep')) + step = parseFloat(nodeDefInput.getAttribute('uistep')); + } + if (step == 0) + { + step = (maxValue - minValue) / 1000.0; + } + currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); } break; case 'integer': uniformToUpdate = material.uniforms[name]; if (uniformToUpdate && value != null) { - currentFolder.add(material.uniforms[name], 'value').name(path); + + var minValue = DEFAULT_MIN; + if (value < minValue) + { + minValue = value; + } + var maxValue = DEFAULT_MAX; + if (value > maxValue) + { + maxValue = value; + } + var step = 0; + var enumList = [] + if (nodeDefInput) { + if (nodeDefInput.hasAttribute('enum')) + { + enumList = nodeDefInput.getAttribute('enum').split(','); + } + else + { + if (nodeDefInput.hasAttribute('uimin')) + minValue = parseInt(nodeDefInput.getAttribute('uimin')); + if (nodeDefInput.hasAttribute('uimax')) + maxValue = parseInt(nodeDefInput.getAttribute('uimax')); + if (nodeDefInput.hasAttribute('uistep')) + step = parseInt(nodeDefInput.getAttribute('uistep')); + } + } + if (enumList.length == 0) + { + if (step == 0) + { + step = 1 / (maxValue - minValue); + step = Math.ceil(step); + if (step == 0) + { + step = 1; + } + } + } + if (enumList.length == 0) + { + currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); + } + else + { + // TODO: Add enum support + currentFolder.add(material.uniforms[name], 'value' ).name(path); + } } break; @@ -919,9 +1011,30 @@ export class Material case 'vector4': uniformToUpdate = material.uniforms[name]; if (uniformToUpdate && value != null) { + var minValue = [DEFAULT_MIN, DEFAULT_MIN, DEFAULT_MIN, DEFAULT_MIN]; + var maxValue = [DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX]; + var step = [0, 0, 0, 0]; + + if (nodeDefInput) + { + if (nodeDefInput.hasAttribute('uimin')) + minValue = nodeDefInput.getAttribute('uimin').split(',').map(Number); + if (nodeDefInput.hasAttribute('uimax')) + maxValue = nodeDefInput.getAttribute('uimax').split(',').map(Number); + if (nodeDefInput.hasAttribute('uistep')) + step = nodeDefInput.getAttribute('uistep').split(',').map(Number); + } + for (let i = 0; i < 4; ++i) { + if (step[i] == 0) { + step[i] = 1 / (maxValue[i] - minValue[i]); + } + } + + const keyString = ["x", "y", "z", "w"]; let vecFolder = currentFolder.addFolder(path); Object.keys(material.uniforms[name].value).forEach((key) => { - vecFolder.add(material.uniforms[name].value, key).name(path + "." + key); + let w = vecFolder.add(material.uniforms[name].value, + key, minValue[key], maxValue[key], step[key]).name(keyString[key]); }) } break; From dddf104f8706c98fa6d8fc72a10c6b908f0260f0 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Fri, 22 Dec 2023 17:29:56 -0800 Subject: [PATCH 09/17] Improvements to web property editor (#1624) - Add support for uisoftmin and uisoftmax attributes. - Minor coding style updates, harmonizing on Allman braces in new code. - Remove legacy UI logic. --- javascript/MaterialXView/source/viewer.js | 89 ++++++++++++----------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index 34474aeede..b0bcd98fbf 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -442,16 +442,6 @@ export class Editor element.style.opacity = targetOpacity; } ); - - // Hide close button - if (this._hideCloseControl) - { - Array.from(document.getElementsByClassName('close-button')).forEach( - function (element, index, array) { - element.style.display = "none"; - } - ); - } } getGUI() @@ -460,7 +450,6 @@ export class Editor } _gui = null; - _hideCloseControl = false; } class MaterialAssign @@ -864,14 +853,7 @@ export class Material let newFolderName = currentNodePath + '/' + uifolderName; currentFolder = folderList[newFolderName]; if (!currentFolder) { - if (nodeDefInput.hasAttribute('uiadvanced')) - { - currentFolder = matUI.addFolder(uifolderName + " (Advanced)"); - } - else - { - currentFolder = matUI.addFolder(uifolderName); - } + currentFolder = matUI.addFolder(uifolderName); folderList[newFolderName] = currentFolder; } } @@ -911,12 +893,12 @@ export class Material } } - switch (variable.getType().getName()) { - + switch (variable.getType().getName()) + { case 'float': uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { - + if (uniformToUpdate && value != null) + { var minValue = DEFAULT_MIN; if (value < minValue) { @@ -928,11 +910,18 @@ export class Material maxValue = value; } var step = 0; - if (nodeDefInput) { - if (nodeDefInput.hasAttribute('uimin')) + if (nodeDefInput) + { + if (nodeDefInput.hasAttribute('uisoftmin')) + minValue = parseFloat(nodeDefInput.getAttribute('uisoftmin')); + else if (nodeDefInput.hasAttribute('uimin')) minValue = parseFloat(nodeDefInput.getAttribute('uimin')); - if (nodeDefInput.hasAttribute('uimax')) + + if (nodeDefInput.hasAttribute('uisoftmax')) + maxValue = parseFloat(nodeDefInput.getAttribute('uisoftmax')); + else if (nodeDefInput.hasAttribute('uimax')) maxValue = parseFloat(nodeDefInput.getAttribute('uimax')); + if (nodeDefInput.hasAttribute('uistep')) step = parseFloat(nodeDefInput.getAttribute('uistep')); } @@ -946,8 +935,8 @@ export class Material case 'integer': uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { - + if (uniformToUpdate && value != null) + { var minValue = DEFAULT_MIN; if (value < minValue) { @@ -960,17 +949,24 @@ export class Material } var step = 0; var enumList = [] - if (nodeDefInput) { + if (nodeDefInput) + { if (nodeDefInput.hasAttribute('enum')) { enumList = nodeDefInput.getAttribute('enum').split(','); } else { - if (nodeDefInput.hasAttribute('uimin')) + if (nodeDefInput.hasAttribute('uisoftmin')) + minValue = parseInt(nodeDefInput.getAttribute('uisoftmin')); + else if (nodeDefInput.hasAttribute('uimin')) minValue = parseInt(nodeDefInput.getAttribute('uimin')); - if (nodeDefInput.hasAttribute('uimax')) + + if (nodeDefInput.hasAttribute('uisoftmax')) + maxValue = parseInt(nodeDefInput.getAttribute('uisoftmax')); + else if (nodeDefInput.hasAttribute('uimax')) maxValue = parseInt(nodeDefInput.getAttribute('uimax')); + if (nodeDefInput.hasAttribute('uistep')) step = parseInt(nodeDefInput.getAttribute('uistep')); } @@ -1001,7 +997,8 @@ export class Material case 'boolean': uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { + if (uniformToUpdate && value != null) + { currentFolder.add(material.uniforms[name], 'value').name(path); } break; @@ -1010,22 +1007,31 @@ export class Material case 'vector3': case 'vector4': uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { + if (uniformToUpdate && value != null) + { var minValue = [DEFAULT_MIN, DEFAULT_MIN, DEFAULT_MIN, DEFAULT_MIN]; var maxValue = [DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX]; var step = [0, 0, 0, 0]; if (nodeDefInput) { - if (nodeDefInput.hasAttribute('uimin')) + if (nodeDefInput.hasAttribute('uisoftmin')) + minValue = nodeDefInput.getAttribute('uisoftmin').split(',').map(Number); + else if (nodeDefInput.hasAttribute('uimin')) minValue = nodeDefInput.getAttribute('uimin').split(',').map(Number); - if (nodeDefInput.hasAttribute('uimax')) + + if (nodeDefInput.hasAttribute('uisoftmax')) + maxValue = nodeDefInput.getAttribute('uisoftmax').split(',').map(Number); + else if (nodeDefInput.hasAttribute('uimax')) maxValue = nodeDefInput.getAttribute('uimax').split(',').map(Number); + if (nodeDefInput.hasAttribute('uistep')) step = nodeDefInput.getAttribute('uistep').split(',').map(Number); } - for (let i = 0; i < 4; ++i) { - if (step[i] == 0) { + for (let i = 0; i < 4; ++i) + { + if (step[i] == 0) + { step[i] = 1 / (maxValue[i] - minValue[i]); } } @@ -1042,8 +1048,10 @@ export class Material case 'color3': // Irksome way to mape arrays to colors and back uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { - var dummy = { + if (uniformToUpdate && value != null) + { + var dummy = + { color: 0xFF0000 }; const color3 = new THREE.Color(dummy.color); @@ -1053,8 +1061,7 @@ export class Material .onChange(function (value) { const color3 = new THREE.Color(value); material.uniforms[name].value.set(color3.toArray()); - } - ); + }); } break; From eae062a038bcd8f8172b1725e93e35641dc73f61 Mon Sep 17 00:00:00 2001 From: Apoorva Joshi Date: Fri, 29 Dec 2023 07:02:58 +0100 Subject: [PATCH 10/17] Improvements to prefiltered environment maps (#1420) This changelist adds support for prefiltering environment maps on the GPU, using filtered VNDF sampling for efficiency. The MaterialX Viewer can be used to test the new functionality by unchecking the Environment FIS option in Advanced Settings. --- .../genglsl/lib/mx_environment_fis.glsl | 10 -- .../genglsl/lib/mx_environment_prefilter.glsl | 9 +- .../genglsl/lib/mx_microfacet_specular.glsl | 24 +++++ .../genglsl/lib/mx_prefilter_environment.glsl | 76 +++++++++++++ .../JsMaterialXGenShader/JsGenOptions.cpp | 1 + .../MaterialXGenGlsl/GlslShaderGenerator.cpp | 13 ++- source/MaterialXGenMsl/MslShaderGenerator.cpp | 11 ++ source/MaterialXGenShader/GenOptions.h | 5 + .../MaterialXGenShader/HwShaderGenerator.cpp | 13 +++ source/MaterialXGenShader/HwShaderGenerator.h | 2 + source/MaterialXRender/ImageHandler.cpp | 2 +- source/MaterialXRender/ImageHandler.h | 2 +- source/MaterialXRender/LightHandler.h | 27 +++++ source/MaterialXRender/Util.cpp | 20 ++++ source/MaterialXRender/Util.h | 5 + .../MaterialXRenderGlsl/GLTextureHandler.cpp | 2 +- source/MaterialXRenderGlsl/GLTextureHandler.h | 2 +- source/MaterialXRenderGlsl/GlslProgram.cpp | 13 ++- .../MaterialXRenderMsl/MetalTextureHandler.h | 2 +- .../MaterialXRenderMsl/MetalTextureHandler.mm | 6 +- .../MslPipelineStateObject.mm | 2 +- source/MaterialXView/RenderPipeline.h | 1 + source/MaterialXView/RenderPipelineGL.cpp | 102 +++++++++++++++++- source/MaterialXView/RenderPipelineGL.h | 1 + source/MaterialXView/RenderPipelineMetal.h | 2 + source/MaterialXView/RenderPipelineMetal.mm | 98 ++++++++++++++++- source/MaterialXView/Viewer.cpp | 5 + .../PyMaterialXGenShader/PyGenOptions.cpp | 1 + 28 files changed, 425 insertions(+), 32 deletions(-) create mode 100644 libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl index 575991e28d..85c88c3280 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl @@ -1,15 +1,5 @@ #include "mx_microfacet_specular.glsl" -// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html -// Section 20.4 Equation 13 -float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) -{ - const float MIP_LEVEL_OFFSET = 1.5; - float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; - float distortion = sqrt(1.0 - mx_square(dir.y)); - return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); -} - vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) { // Generate tangent frame. diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl index 6def6fb439..e448ae247e 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl @@ -1,12 +1,5 @@ #include "mx_microfacet_specular.glsl" -float mx_latlong_compute_lod(float alpha) -{ - // Select a mip level based on input alpha. - float lodBias = alpha < 0.25 ? sqrt(alpha) : 0.5*alpha + 0.375; - return lodBias * float($envRadianceMips); -} - vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) { N = mx_forward_facing_normal(N, V); @@ -19,7 +12,7 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; - vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_compute_lod(avgAlpha), $envRadiance); + vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_alpha_to_lod(avgAlpha), $envRadiance); return Li * FG; } diff --git a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl index 63aba17869..85430c00ca 100644 --- a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl @@ -593,3 +593,27 @@ vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D envSam vec2 uv = mx_latlong_projection(envDir); return textureLod(envSampler, uv, lod).rgb; } + +// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html +// Section 20.4 Equation 13 +float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) +{ + const float MIP_LEVEL_OFFSET = 1.5; + float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; + float distortion = sqrt(1.0 - mx_square(dir.y)); + return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); +} + +float mx_latlong_alpha_to_lod(float alpha) +{ + // Return the mip level associated with the given alpha in a prefiltered environment. + float lodBias = (alpha < 0.25) ? sqrt(alpha) : 0.5 * alpha + 0.375; + return lodBias * float($envRadianceMips - 1); +} + +float mx_latlong_lod_to_alpha(float lod) +{ + // Return the alpha associated with the given mip level in a prefiltered environment. + float lodBias = lod / float($envRadianceMips - 1); + return (lodBias < 0.5) ? mx_square(lodBias) : 2.0 * (lodBias - 0.375); +} diff --git a/libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl b/libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl new file mode 100644 index 0000000000..fd608871ed --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl @@ -0,0 +1,76 @@ +#include "mx_microfacet_specular.glsl" + +// Construct an orthonormal basis from a unit vector. +// https://graphics.pixar.com/library/OrthonormalB/paper.pdf +mat3 mx_orthonormal_basis(vec3 N) +{ + float sign = (N.z < 0.0) ? -1.0 : 1.0; + float a = -1.0 / (sign + N.z); + float b = N.x * N.y * a; + vec3 X = vec3(1.0 + sign * N.x * N.x * a, sign * b, -sign * N.x); + vec3 Y = vec3(b, sign + N.y * N.y * a, -N.y); + return mat3(X, Y, N); +} + +// The inverse of mx_latlong_projection. +vec3 mx_latlong_map_projection_inverse(vec2 uv) +{ + float latitude = (uv.y - 0.5) * M_PI; + float longitude = (uv.x - 0.5) * M_PI * 2.0; + + float x = -cos(latitude) * sin(longitude); + float y = -sin(latitude); + float z = cos(latitude) * cos(longitude); + + return vec3(x, y, z); +} + +vec3 mx_prefilter_environment() +{ + vec2 uv = gl_FragCoord.xy * pow(2.0, $envPrefilterMip) / vec2(2048.0, 1024.0); + float alpha = mx_latlong_lod_to_alpha(float($envPrefilterMip)); + if ($envPrefilterMip == 0) + { + return textureLod($envRadiance, uv, 0).rgb; + } + + // Compute world normal and transform. + vec3 worldN = mx_latlong_map_projection_inverse(uv); + mat3 tangentToWorld = mx_orthonormal_basis(worldN); + + // Local normal and view vectors are constant and aligned. + vec3 V = vec3(0.0, 0.0, 1.0); + float NdotV = 1.0; + float G1V = mx_ggx_smith_G1(NdotV, alpha); + + // Integrate the LD term for the given environment and alpha. + vec3 radiance = vec3(0.0, 0.0, 0.0); + float weight = 0.0; + int envRadianceSamples = 1024; + for (int i = 0; i < envRadianceSamples; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, envRadianceSamples); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, vec2(alpha)); + vec3 L = -V + 2.0 * H.z * H; + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + + // Compute the geometric term. + float G = mx_ggx_smith_G2(NdotL, NdotV, alpha); + + // Sample the environment light from the given direction. + vec3 Lw = tangentToWorld * L; + float pdf = mx_ggx_NDF(H, vec2(alpha)) * G1V / (4.0 * NdotV); + float lod = mx_latlong_compute_lod(Lw, pdf, float($envRadianceMips - 1), envRadianceSamples); + vec3 sampleColor = mx_latlong_map_lookup(Lw, $envMatrix, lod, $envRadiance); + + // Add the radiance contribution of this sample. + radiance += G * sampleColor; + weight += G; + } + + return radiance / weight; +} diff --git a/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp b/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp index 7e3313cdf7..9b28a6f534 100644 --- a/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp +++ b/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp @@ -42,5 +42,6 @@ EMSCRIPTEN_BINDINGS(GenOptions) .property("hwMaxActiveLightSources", &mx::GenOptions::hwMaxActiveLightSources) .property("hwNormalizeUdimTexCoords", &mx::GenOptions::hwNormalizeUdimTexCoords) .property("hwWriteAlbedoTable", &mx::GenOptions::hwWriteAlbedoTable) + .property("hwWriteEnvPrefilter", &mx::GenOptions::hwWriteEnvPrefilter) ; } diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index ea78e1bee3..b9351ddc08 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -553,7 +553,7 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c bool lighting = requiresLighting(graph); // Define directional albedo approach - if (lighting || context.getOptions().hwWriteAlbedoTable) + if (lighting || context.getOptions().hwWriteAlbedoTable || context.getOptions().hwWriteEnvPrefilter) { emitLine("#define DIRECTIONAL_ALBEDO_METHOD " + std::to_string(int(context.getOptions().hwDirectionalAlbedoMethod)), stage, false); emitLineBreak(stage); @@ -591,6 +591,13 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c emitLineBreak(stage); } + // Emit environment prefiltering code + if (context.getOptions().hwWriteEnvPrefilter) + { + emitLibraryInclude("pbrlib/genglsl/lib/mx_prefilter_environment.glsl", context, stage); + emitLineBreak(stage); + } + // Set the include file to use for uv transformations, // depending on the vertical flip flag. if (context.getOptions().fileTextureVerticalFlip) @@ -636,6 +643,10 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c { emitLine(outputSocket->getVariable() + " = vec4(mx_generate_dir_albedo_table(), 1.0)", stage); } + else if (context.getOptions().hwWriteEnvPrefilter) + { + emitLine(outputSocket->getVariable() + " = vec4(mx_prefilter_environment(), 1.0)", stage); + } else { // Add all function calls. diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 7fe50fef4a..5749f0d211 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -1059,6 +1059,13 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co emitLineBreak(stage); } + // Emit environment prefiltering code + if (context.getOptions().hwWriteEnvPrefilter) + { + emitLibraryInclude("pbrlib/genglsl/lib/mx_prefilter_environment.glsl", context, stage); + emitLineBreak(stage); + } + // Set the include file to use for uv transformations, // depending on the vertical flip flag. if (context.getOptions().fileTextureVerticalFlip) @@ -1104,6 +1111,10 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co { emitLine(outputSocket->getVariable() + " = float4(mx_generate_dir_albedo_table(), 1.0)", stage); } + else if (context.getOptions().hwWriteEnvPrefilter) + { + emitLine(outputSocket->getVariable() + " = float4(mx_prefilter_environment(), 1.0)", stage); + } else { // Add all function calls. diff --git a/source/MaterialXGenShader/GenOptions.h b/source/MaterialXGenShader/GenOptions.h index 34a1efde0b..6af73d62a8 100644 --- a/source/MaterialXGenShader/GenOptions.h +++ b/source/MaterialXGenShader/GenOptions.h @@ -90,6 +90,7 @@ class MX_GENSHADER_API GenOptions hwMaxActiveLightSources(3), hwNormalizeUdimTexCoords(false), hwWriteAlbedoTable(false), + hwWriteEnvPrefilter(false), hwImplicitBitangents(true), emitColorTransforms(true) { @@ -174,6 +175,10 @@ class MX_GENSHADER_API GenOptions /// Defaults to false. bool hwWriteAlbedoTable; + /// Enables the generation of a prefiltered environment map. + /// Defaults to false. + bool hwWriteEnvPrefilter; + /// Calculate fallback bitangents from existing normals and tangents /// inside the bitangent node. bool hwImplicitBitangents; diff --git a/source/MaterialXGenShader/HwShaderGenerator.cpp b/source/MaterialXGenShader/HwShaderGenerator.cpp index 0db78eda27..6ba94d1280 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.cpp +++ b/source/MaterialXGenShader/HwShaderGenerator.cpp @@ -59,6 +59,7 @@ const string T_ENV_RADIANCE = "$envRadiance"; const string T_ENV_RADIANCE_MIPS = "$envRadianceMips"; const string T_ENV_RADIANCE_SAMPLES = "$envRadianceSamples"; const string T_ENV_IRRADIANCE = "$envIrradiance"; +const string T_ENV_PREFILTER_MIP = "$envPrefilterMip"; const string T_REFRACTION_TWO_SIDED = "$refractionTwoSided"; const string T_ALBEDO_TABLE = "$albedoTable"; const string T_ALBEDO_TABLE_SIZE = "$albedoTableSize"; @@ -113,6 +114,7 @@ const string ENV_RADIANCE = "u_envRadiance"; const string ENV_RADIANCE_MIPS = "u_envRadianceMips"; const string ENV_RADIANCE_SAMPLES = "u_envRadianceSamples"; const string ENV_IRRADIANCE = "u_envIrradiance"; +const string ENV_PREFILTER_MIP = "u_envPrefilterMip"; const string REFRACTION_TWO_SIDED = "u_refractionTwoSided"; const string ALBEDO_TABLE = "u_albedoTable"; const string ALBEDO_TABLE_SIZE = "u_albedoTableSize"; @@ -222,6 +224,7 @@ HwShaderGenerator::HwShaderGenerator(SyntaxPtr syntax) : _tokenSubstitutions[HW::T_AMB_OCC_GAIN] = HW::AMB_OCC_GAIN; _tokenSubstitutions[HW::T_VERTEX_DATA_INSTANCE] = HW::VERTEX_DATA_INSTANCE; _tokenSubstitutions[HW::T_LIGHT_DATA_INSTANCE] = HW::LIGHT_DATA_INSTANCE; + _tokenSubstitutions[HW::T_ENV_PREFILTER_MIP] = HW::ENV_PREFILTER_MIP; // Setup closure contexts for defining closure functions // @@ -359,6 +362,16 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element psPrivateUniforms->add(Type::INTEGER, HW::T_ALBEDO_TABLE_SIZE, Value::createValue(64)); } + // Add uniforms for environment prefiltering. + if (context.getOptions().hwWriteEnvPrefilter) + { + psPrivateUniforms->add(Type::FILENAME, HW::T_ENV_RADIANCE); + psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_PREFILTER_MIP, Value::createValue(1)); + const Matrix44 yRotationPI = Matrix44::createScale(Vector3(-1, 1, -1)); + psPrivateUniforms->add(Type::MATRIX44, HW::T_ENV_MATRIX, Value::createValue(yRotationPI)); + psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_RADIANCE_MIPS, Value::createValue(1)); + } + // Create uniforms for the published graph interface for (ShaderGraphInputSocket* inputSocket : graph->getInputSockets()) { diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h index bba572c631..f839ac56bd 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.h +++ b/source/MaterialXGenShader/HwShaderGenerator.h @@ -126,6 +126,7 @@ extern MX_GENSHADER_API const string T_ENV_RADIANCE; extern MX_GENSHADER_API const string T_ENV_RADIANCE_MIPS; extern MX_GENSHADER_API const string T_ENV_RADIANCE_SAMPLES; extern MX_GENSHADER_API const string T_ENV_IRRADIANCE; +extern MX_GENSHADER_API const string T_ENV_PREFILTER_MIP; extern MX_GENSHADER_API const string T_REFRACTION_TWO_SIDED; extern MX_GENSHADER_API const string T_ALBEDO_TABLE; extern MX_GENSHADER_API const string T_ALBEDO_TABLE_SIZE; @@ -182,6 +183,7 @@ extern MX_GENSHADER_API const string ENV_RADIANCE; extern MX_GENSHADER_API const string ENV_RADIANCE_MIPS; extern MX_GENSHADER_API const string ENV_RADIANCE_SAMPLES; extern MX_GENSHADER_API const string ENV_IRRADIANCE; +extern MX_GENSHADER_API const string ENV_PREFILTER_MIP; extern MX_GENSHADER_API const string REFRACTION_TWO_SIDED; extern MX_GENSHADER_API const string ALBEDO_TABLE; extern MX_GENSHADER_API const string ALBEDO_TABLE_SIZE; diff --git a/source/MaterialXRender/ImageHandler.cpp b/source/MaterialXRender/ImageHandler.cpp index 2d56207f32..b148bf63d9 100644 --- a/source/MaterialXRender/ImageHandler.cpp +++ b/source/MaterialXRender/ImageHandler.cpp @@ -165,7 +165,7 @@ void ImageHandler::unbindImages() } } -bool ImageHandler::createRenderResources(ImagePtr, bool) +bool ImageHandler::createRenderResources(ImagePtr, bool, bool) { return false; } diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h index e8eaf99b2f..e5d2082f8d 100644 --- a/source/MaterialXRender/ImageHandler.h +++ b/source/MaterialXRender/ImageHandler.h @@ -230,7 +230,7 @@ class MX_RENDER_API ImageHandler } /// Create rendering resources for the given image. - virtual bool createRenderResources(ImagePtr image, bool generateMipMaps); + virtual bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false); /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRender/LightHandler.h b/source/MaterialXRender/LightHandler.h index 852ccfa41d..a080c72081 100644 --- a/source/MaterialXRender/LightHandler.h +++ b/source/MaterialXRender/LightHandler.h @@ -37,6 +37,7 @@ class MX_RENDER_API LightHandler _lightTransform(Matrix44::IDENTITY), _directLighting(true), _indirectLighting(true), + _usePrefilteredMap(false), _envSampleCount(DEFAULT_ENV_SAMPLE_COUNT), _refractionTwoSided(false) { @@ -101,6 +102,30 @@ class MX_RENDER_API LightHandler return _envRadianceMap; } + /// Set the environment radiance map for the prefiltered environment lighting model. + void setEnvPrefilteredMap(ImagePtr map) + { + _envPrefilteredMap = map; + } + + /// Return the environment radiance map for the prefiltered environment lighting model. + ImagePtr getEnvPrefilteredMap() const + { + return _envPrefilteredMap; + } + + /// Set whether to use the prefiltered environment lighting model. + void setUsePrefilteredMap(bool val) + { + _usePrefilteredMap = val; + } + + /// Return whether to use the prefiltered environment lighting model. + bool getUsePrefilteredMap() + { + return _usePrefilteredMap; + } + /// Set the environment irradiance map void setEnvIrradianceMap(ImagePtr map) { @@ -216,8 +241,10 @@ class MX_RENDER_API LightHandler Matrix44 _lightTransform; bool _directLighting; bool _indirectLighting; + bool _usePrefilteredMap; ImagePtr _envRadianceMap; + ImagePtr _envPrefilteredMap; ImagePtr _envIrradianceMap; int _envSampleCount; diff --git a/source/MaterialXRender/Util.cpp b/source/MaterialXRender/Util.cpp index e8ec0f7c48..f33c67173e 100644 --- a/source/MaterialXRender/Util.cpp +++ b/source/MaterialXRender/Util.cpp @@ -76,6 +76,26 @@ ShaderPtr createAlbedoTableShader(GenContext& context, return shader; } +ShaderPtr createEnvPrefilterShader(GenContext& context, + DocumentPtr stdLib, + const string& shaderName) +{ + // Construct a dummy nodegraph. + DocumentPtr doc = createDocument(); + doc->importLibrary(stdLib); + NodeGraphPtr nodeGraph = doc->addNodeGraph(); + NodePtr constant = nodeGraph->addNode("constant"); + OutputPtr output = nodeGraph->addOutput(); + output->setConnectedNode(constant); + + // Generate the shader + GenContext tableContext = context; + tableContext.getOptions().hwWriteEnvPrefilter = true; + ShaderPtr shader = createShader(shaderName, tableContext, output); + + return shader; +} + ShaderPtr createBlurShader(GenContext& context, DocumentPtr stdLib, const string& shaderName, diff --git a/source/MaterialXRender/Util.h b/source/MaterialXRender/Util.h index 922c06e529..bf1a3d543c 100644 --- a/source/MaterialXRender/Util.h +++ b/source/MaterialXRender/Util.h @@ -47,6 +47,11 @@ MX_RENDER_API ShaderPtr createAlbedoTableShader(GenContext& context, DocumentPtr stdLib, const string& shaderName); +/// Create a shader that generates a prefiltered environment map. +MX_RENDER_API ShaderPtr createEnvPrefilterShader(GenContext& context, + DocumentPtr stdLib, + const string& shaderName); + /// Create a blur shader, using the given standard libraries for code generation. MX_RENDER_API ShaderPtr createBlurShader(GenContext& context, DocumentPtr stdLib, diff --git a/source/MaterialXRenderGlsl/GLTextureHandler.cpp b/source/MaterialXRenderGlsl/GLTextureHandler.cpp index 314a78c257..02a0a53927 100644 --- a/source/MaterialXRenderGlsl/GLTextureHandler.cpp +++ b/source/MaterialXRenderGlsl/GLTextureHandler.cpp @@ -91,7 +91,7 @@ bool GLTextureHandler::unbindImage(ImagePtr image) return false; } -bool GLTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps) +bool GLTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps, bool) { if (image->getResourceId() == GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID) { diff --git a/source/MaterialXRenderGlsl/GLTextureHandler.h b/source/MaterialXRenderGlsl/GLTextureHandler.h index 942d6dc446..13eaab098f 100644 --- a/source/MaterialXRenderGlsl/GLTextureHandler.h +++ b/source/MaterialXRenderGlsl/GLTextureHandler.h @@ -37,7 +37,7 @@ class MX_RENDERGLSL_API GLTextureHandler : public ImageHandler bool unbindImage(ImagePtr image) override; /// Create rendering resources for the given image. - bool createRenderResources(ImagePtr image, bool generateMipMaps) override; + bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false) override; /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 4497019e91..eecab8036e 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -578,9 +578,20 @@ void GlslProgram::bindLighting(LightHandlerPtr lightHandler, ImageHandlerPtr ima Matrix44 envRotation = Matrix44::createRotationY(PI) * lightHandler->getLightTransform().getTranspose(); bindUniform(HW::ENV_MATRIX, Value::createValue(envRotation), false); bindUniform(HW::ENV_RADIANCE_SAMPLES, Value::createValue(lightHandler->getEnvSampleCount()), false); + ImagePtr envRadiance = nullptr; + if (lightHandler->getIndirectLighting()) + { + envRadiance = lightHandler->getUsePrefilteredMap() ? + lightHandler->getEnvPrefilteredMap() : + lightHandler->getEnvRadianceMap(); + } + else + { + envRadiance = imageHandler->getZeroImage(); + } ImageMap envImages = { - { HW::ENV_RADIANCE, lightHandler->getIndirectLighting() ? lightHandler->getEnvRadianceMap() : imageHandler->getZeroImage() }, + { HW::ENV_RADIANCE, envRadiance }, { HW::ENV_IRRADIANCE, lightHandler->getIndirectLighting() ? lightHandler->getEnvIrradianceMap() : imageHandler->getZeroImage() } }; for (const auto& env : envImages) diff --git a/source/MaterialXRenderMsl/MetalTextureHandler.h b/source/MaterialXRenderMsl/MetalTextureHandler.h index 4c329f3f6d..c78469a4ce 100644 --- a/source/MaterialXRenderMsl/MetalTextureHandler.h +++ b/source/MaterialXRenderMsl/MetalTextureHandler.h @@ -57,7 +57,7 @@ class MX_RENDERMSL_API MetalTextureHandler : public ImageHandler id getMTLSamplerStateForImage(unsigned int index); /// Create rendering resources for the given image. - bool createRenderResources(ImagePtr image, bool generateMipMaps) override; + bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false) override; /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRenderMsl/MetalTextureHandler.mm b/source/MaterialXRenderMsl/MetalTextureHandler.mm index 745019ac92..ab8da46f1f 100644 --- a/source/MaterialXRenderMsl/MetalTextureHandler.mm +++ b/source/MaterialXRenderMsl/MetalTextureHandler.mm @@ -128,7 +128,7 @@ return false; } -bool MetalTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps) +bool MetalTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget) { id texture = nil; @@ -149,9 +149,7 @@ texDesc.height = image->getHeight(); texDesc.mipmapLevelCount = generateMipMaps ? image->getMaxMipCount() : 1; texDesc.usage = MTLTextureUsageShaderRead | - // For now, we set generate mip maps flag off, - // when we want to use the texture as render target - (!generateMipMaps ? MTLTextureUsageRenderTarget : 0); + (useAsRenderTarget ? MTLTextureUsageRenderTarget : 0); texDesc.resourceOptions = MTLResourceStorageModePrivate; texDesc.pixelFormat = pixelFormat; if(generateMipMaps) diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 4f8378ae46..f0cc8e47bb 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -594,7 +594,7 @@ int GetStrideOfMetalType(MTLDataType type) // Bind environment lights. ImageMap envLights = { - { HW::ENV_RADIANCE, lightHandler->getEnvRadianceMap() }, + { HW::ENV_RADIANCE, lightHandler->getUsePrefilteredMap() ? lightHandler->getEnvPrefilteredMap() : lightHandler->getEnvRadianceMap() }, { HW::ENV_IRRADIANCE, lightHandler->getEnvIrradianceMap() } }; for (const auto& env : envLights) diff --git a/source/MaterialXView/RenderPipeline.h b/source/MaterialXView/RenderPipeline.h index 87baac3fa4..3b7e7a48b7 100644 --- a/source/MaterialXView/RenderPipeline.h +++ b/source/MaterialXView/RenderPipeline.h @@ -50,6 +50,7 @@ class RenderPipeline virtual void bakeTextures() = 0; virtual void updateAlbedoTable(int tableSize) = 0; + virtual void updatePrefilteredMap() = 0; virtual std::shared_ptr createTextureBaker(unsigned int width, unsigned int height, mx::Image::BaseType baseType) = 0; diff --git a/source/MaterialXView/RenderPipelineGL.cpp b/source/MaterialXView/RenderPipelineGL.cpp index f08704d0a3..68ac0be040 100644 --- a/source/MaterialXView/RenderPipelineGL.cpp +++ b/source/MaterialXView/RenderPipelineGL.cpp @@ -110,6 +110,100 @@ void GLRenderPipeline::updateAlbedoTable(int tableSize) glDrawBuffer(GL_BACK); } +void GLRenderPipeline::updatePrefilteredMap() +{ + auto& genContext = _viewer->_genContext; + auto& lightHandler = _viewer->_lightHandler; + auto& imageHandler = _viewer->_imageHandler; + + if (lightHandler->getEnvPrefilteredMap()) + { + return; + } + + // Create the prefilter shader. + mx::GlslMaterialPtr material = nullptr; + try + { + mx::ShaderPtr hwShader = mx::createEnvPrefilterShader(genContext, _viewer->_stdLib, "__ENV_PREFILTER__"); + material = mx::GlslMaterial::create(); + material->generateShader(hwShader); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to generate prefilter shader", e.what()); + } + + mx::ImagePtr srcTex = lightHandler->getEnvRadianceMap(); + + int w = srcTex->getWidth(); + int h = srcTex->getHeight(); + int numMips = srcTex->getMaxMipCount(); + + // Create texture to hold the prefiltered environment. + mx::GLTextureHandlerPtr glImageHandler = std::dynamic_pointer_cast(imageHandler); + mx::ImagePtr outTex = mx::Image::create(w, h, 3, mx::Image::BaseType::HALF); + glImageHandler->createRenderResources(outTex, true, true); + + mx::GlslProgramPtr program = material->getProgram(); + + try + { + int i = 0; + while (w > 0 && h > 0) + { + // Create framebuffer + unsigned int framebuffer; + glGenFramebuffers(1, &framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, outTex->getResourceId(), i); + glViewport(0, 0, w, h); + material->bindShader(); + + // Bind the source texture + mx::ImageSamplingProperties samplingProperties; + samplingProperties.uaddressMode = mx::ImageSamplingProperties::AddressMode::PERIODIC; + samplingProperties.vaddressMode = mx::ImageSamplingProperties::AddressMode::CLAMP; + samplingProperties.filterType = mx::ImageSamplingProperties::FilterType::LINEAR; + imageHandler->bindImage(srcTex, samplingProperties); + int textureLocation = glImageHandler->getBoundTextureLocation(srcTex->getResourceId()); + assert(textureLocation >= 0); + material->getProgram()->bindUniform(mx::HW::ENV_RADIANCE, mx::Value::createValue(textureLocation)); + // Bind other uniforms + program->bindUniform(mx::HW::ENV_PREFILTER_MIP, mx::Value::createValue(i)); + const mx::Matrix44 yRotationPI = mx::Matrix44::createScale(mx::Vector3(-1, 1, -1)); + program->bindUniform(mx::HW::ENV_MATRIX, mx::Value::createValue(yRotationPI)); + program->bindUniform(mx::HW::ENV_RADIANCE_MIPS, mx::Value::createValue(numMips)); + + _viewer->renderScreenSpaceQuad(material); + + glDeleteFramebuffers(1, &framebuffer); + + w /= 2; + h /= 2; + i++; + } + } + catch (mx::ExceptionRenderError& e) + { + for (const std::string& error : e.errorLog()) + { + std::cerr << error << std::endl; + } + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to render prefiltered environment", e.what()); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to render prefiltered environment", e.what()); + } + + // Clean up. + glViewport(0, 0, _viewer->m_fbsize[0], _viewer->m_fbsize[1]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + lightHandler->setEnvPrefilteredMap(outTex); +} + mx::ImagePtr GLRenderPipeline::getShadowMap(int shadowMapSize) { auto& genContext = _viewer->_genContext; @@ -219,7 +313,13 @@ void GLRenderPipeline::renderFrame(void*, int shadowMapSize, const char* dirLigh float lightRotation = _viewer->_lightRotation; auto& searchPath = _viewer->_searchPath; auto& geometryHandler = _viewer->_geometryHandler; - + + // Update prefiltered environment. + if (lightHandler->getUsePrefilteredMap() && !_viewer->_materialAssignments.empty()) + { + updatePrefilteredMap(); + } + // Initialize OpenGL state glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); diff --git a/source/MaterialXView/RenderPipelineGL.h b/source/MaterialXView/RenderPipelineGL.h index fcb64a6436..00ebcbc6eb 100644 --- a/source/MaterialXView/RenderPipelineGL.h +++ b/source/MaterialXView/RenderPipelineGL.h @@ -31,6 +31,7 @@ class GLRenderPipeline : public RenderPipeline mx::ImageHandlerPtr createImageHandler() override; mx::MaterialPtr createMaterial() override; void updateAlbedoTable(int tableSize) override; + void updatePrefilteredMap() override; std::shared_ptr createTextureBaker(unsigned int width, unsigned int height, mx::Image::BaseType baseType) override; diff --git a/source/MaterialXView/RenderPipelineMetal.h b/source/MaterialXView/RenderPipelineMetal.h index 1ed8c063bd..9cd2b2f6b3 100644 --- a/source/MaterialXView/RenderPipelineMetal.h +++ b/source/MaterialXView/RenderPipelineMetal.h @@ -40,6 +40,7 @@ class MetalRenderPipeline : public RenderPipeline mx::ImageHandlerPtr createImageHandler() override; mx::MaterialPtr createMaterial() override; void updateAlbedoTable(int tableSize) override; + void updatePrefilteredMap() override; void renderFrame(void* color_texture, int shadowMapSize, const char* dirLightNodeCat) override; void bakeTextures() override; mx::ImagePtr getFrameImage() override; @@ -50,6 +51,7 @@ class MetalRenderPipeline : public RenderPipeline protected: mx::ImagePtr getShadowMap(int shadowMapSize) override; mx::MetalFramebufferPtr _shadowMapFramebuffer; + mx::MetalFramebufferPtr _prefilterFramebuffer; mx::ImagePtr _shadowMap[SHADOWMAP_TEX_COUNT]; }; diff --git a/source/MaterialXView/RenderPipelineMetal.mm b/source/MaterialXView/RenderPipelineMetal.mm index 026e35720a..0dc85b8aa4 100644 --- a/source/MaterialXView/RenderPipelineMetal.mm +++ b/source/MaterialXView/RenderPipelineMetal.mm @@ -155,6 +155,96 @@ } } +void MetalRenderPipeline::updatePrefilteredMap() +{ + auto& genContext = _viewer->_genContext; + auto& lightHandler = _viewer->_lightHandler; + auto& imageHandler = _viewer->_imageHandler; + + if (lightHandler->getEnvPrefilteredMap()) + { + return; + } + + mx::ImagePtr srcTex = lightHandler->getEnvRadianceMap(); + int w = srcTex->getWidth(); + int h = srcTex->getHeight(); + + mx::MetalTextureHandlerPtr mtlImageHandler = std::dynamic_pointer_cast(imageHandler); + mx::ImagePtr outTex = mx::Image::create(w, h, 3, mx::Image::BaseType::HALF); + mtlImageHandler->createRenderResources(outTex, true, true); + id metalTex = mtlImageHandler->getAssociatedMetalTexture(outTex); + + // Create framebuffer. + _prefilterFramebuffer = mx::MetalFramebuffer::create( + MTL(device), + w, h, + 4, + mx::Image::BaseType::HALF, + metalTex + ); + + MTL_PUSH_FRAMEBUFFER(_prefilterFramebuffer); + + // Create shader. + mx::ShaderPtr hwShader = mx::createEnvPrefilterShader(genContext, _viewer->_stdLib, "__ENV_PREFILTER__"); + mx::MslMaterialPtr material = mx::MslMaterial::create(); + try + { + material->generateShader(hwShader); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to generate convolution shader", e.what()); + } + + int i = 0; + + while (w > 0 && h > 0) + { + MTL(beginCommandBuffer()); + MTLRenderPassDescriptor* desc = [MTLRenderPassDescriptor new]; + [desc.colorAttachments[0] setTexture:metalTex]; + [desc.colorAttachments[0] setLevel:i]; + [desc.colorAttachments[0] setLoadAction:MTLLoadActionDontCare]; + [desc.colorAttachments[0] setStoreAction:MTLStoreActionStore]; + [desc.depthAttachment setTexture:_prefilterFramebuffer->getDepthTexture()]; + [desc.depthAttachment setLoadAction:MTLLoadActionDontCare]; + [desc.depthAttachment setStoreAction:MTLStoreActionDontCare]; + [desc setStencilAttachment:nil]; + + MTL(beginEncoder(desc)); + [MTL(renderCmdEncoder) setDepthStencilState:MTL_DEPTHSTENCIL_STATE(opaque)]; + + _prefilterFramebuffer->bind(desc); + material->bindShader(); + material->getProgram()->bindUniform(mx::HW::ENV_PREFILTER_MIP, mx::Value::createValue(i)); + + bool prevValue = lightHandler->getUsePrefilteredMap(); + lightHandler->setUsePrefilteredMap(false); + material->getProgram()->prepareUsedResources( + MTL(renderCmdEncoder), + _viewer->_identityCamera, + nullptr, + imageHandler, + lightHandler); + lightHandler->setUsePrefilteredMap(prevValue); + + _viewer->renderScreenSpaceQuad(material); + + MTL(endCommandBuffer()); + [desc release]; + + w /= 2; + h /= 2; + i++; + } + + MTL_POP_FRAMEBUFFER(); + + lightHandler->setEnvPrefilteredMap(outTex); +} + mx::ImagePtr MetalRenderPipeline::getShadowMap(int shadowMapSize) { auto& genContext = _viewer->_genContext; @@ -175,7 +265,7 @@ !mtlImageHandler->getAssociatedMetalTexture(_shadowMap[i])) { _shadowMap[i] = mx::Image::create(shadowMapSize, shadowMapSize, 2, mx::Image::BaseType::FLOAT); - _viewer->_imageHandler->createRenderResources(_shadowMap[i], false); + _viewer->_imageHandler->createRenderResources(_shadowMap[i], false, true); } shadowMapTex[i] = @@ -315,6 +405,12 @@ auto& searchPath = _viewer->_searchPath; auto& geometryHandler = _viewer->_geometryHandler; + // Update prefiltered environment. + if (lightHandler->getUsePrefilteredMap() && !_viewer->_materialAssignments.empty()) + { + updatePrefilteredMap(); + } + // Update lighting state. lightHandler->setLightTransform(mx::Matrix44::createRotationY(lightRotation / 180.0f * M_PI)); diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index c06846f2ce..eeaf7a82b0 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -485,9 +485,12 @@ void Viewer::loadEnvironmentLight() // Release any existing environment maps and store the new ones. _imageHandler->releaseRenderResources(_lightHandler->getEnvRadianceMap()); + _imageHandler->releaseRenderResources(_lightHandler->getEnvPrefilteredMap()); _imageHandler->releaseRenderResources(_lightHandler->getEnvIrradianceMap()); + _lightHandler->setEnvRadianceMap(envRadianceMap); _lightHandler->setEnvIrradianceMap(envIrradianceMap); + _lightHandler->setEnvPrefilteredMap(nullptr); // Look for a light rig using an expected filename convention. if (!_splitDirectLight) @@ -746,12 +749,14 @@ void Viewer::createAdvancedSettings(Widget* parent) ng::CheckBox* importanceSampleBox = new ng::CheckBox(advancedPopup, "Environment FIS"); importanceSampleBox->set_checked(_genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS); + _lightHandler->setUsePrefilteredMap(_genContext.getOptions().hwSpecularEnvironmentMethod != mx::SPECULAR_ENVIRONMENT_FIS); importanceSampleBox->set_callback([this](bool enable) { _genContext.getOptions().hwSpecularEnvironmentMethod = enable ? mx::SPECULAR_ENVIRONMENT_FIS : mx::SPECULAR_ENVIRONMENT_PREFILTER; #ifndef MATERIALXVIEW_METAL_BACKEND _genContextEssl.getOptions().hwSpecularEnvironmentMethod = _genContext.getOptions().hwSpecularEnvironmentMethod; #endif + _lightHandler->setUsePrefilteredMap(!enable); reloadShaders(); }); diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp index 75b5fb11bb..c40728ad26 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp @@ -38,6 +38,7 @@ void bindPyGenOptions(py::module& mod) .def_readwrite("hwNormalizeUdimTexCoords", &mx::GenOptions::hwNormalizeUdimTexCoords) .def_readwrite("hwAmbientOcclusion", &mx::GenOptions::hwAmbientOcclusion) .def_readwrite("hwWriteAlbedoTable", &mx::GenOptions::hwWriteAlbedoTable) + .def_readwrite("hwWriteEnvPrefilter", &mx::GenOptions::hwWriteEnvPrefilter) .def_readwrite("hwImplicitBitangents", &mx::GenOptions::hwImplicitBitangents) .def_readwrite("emitColorTransforms", &mx::GenOptions::emitColorTransforms) .def(py::init<>()); From 438f65ddb800ace92f5082607d9e30ffeac3e42d Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 30 Dec 2023 11:23:55 -0800 Subject: [PATCH 11/17] Clarify GLSL data generation shaders - Use the word "generate" consistently in GLSL data generation files and functions, e.g. mx_generate_albedo_table.glsl, mx_generate_prefilter_env.glsl. - Improve documentation for GLSL data generation functions. - Replace constant texture dimensions with the textureSize call. --- ...ble.glsl => mx_generate_albedo_table.glsl} | 0 ...nt.glsl => mx_generate_prefilter_env.glsl} | 19 +++++++------------ .../genglsl/lib/mx_microfacet_specular.glsl | 5 +++-- .../MaterialXGenGlsl/GlslShaderGenerator.cpp | 6 +++--- source/MaterialXGenMsl/MslShaderGenerator.cpp | 6 +++--- 5 files changed, 16 insertions(+), 20 deletions(-) rename libraries/pbrlib/genglsl/lib/{mx_table.glsl => mx_generate_albedo_table.glsl} (100%) rename libraries/pbrlib/genglsl/lib/{mx_prefilter_environment.glsl => mx_generate_prefilter_env.glsl} (90%) diff --git a/libraries/pbrlib/genglsl/lib/mx_table.glsl b/libraries/pbrlib/genglsl/lib/mx_generate_albedo_table.glsl similarity index 100% rename from libraries/pbrlib/genglsl/lib/mx_table.glsl rename to libraries/pbrlib/genglsl/lib/mx_generate_albedo_table.glsl diff --git a/libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl b/libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl similarity index 90% rename from libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl rename to libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl index fd608871ed..e437e886af 100644 --- a/libraries/pbrlib/genglsl/lib/mx_prefilter_environment.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl @@ -25,22 +25,17 @@ vec3 mx_latlong_map_projection_inverse(vec2 uv) return vec3(x, y, z); } -vec3 mx_prefilter_environment() +vec3 mx_generate_prefilter_env() { - vec2 uv = gl_FragCoord.xy * pow(2.0, $envPrefilterMip) / vec2(2048.0, 1024.0); - float alpha = mx_latlong_lod_to_alpha(float($envPrefilterMip)); - if ($envPrefilterMip == 0) - { - return textureLod($envRadiance, uv, 0).rgb; - } + // The tangent view vector is aligned with the normal. + vec3 V = vec3(0.0, 0.0, 1.0); + float NdotV = 1.0; - // Compute world normal and transform. + // Compute derived properties. + vec2 uv = gl_FragCoord.xy * pow(2.0, $envPrefilterMip) / vec2(textureSize($envRadiance, 0)); vec3 worldN = mx_latlong_map_projection_inverse(uv); mat3 tangentToWorld = mx_orthonormal_basis(worldN); - - // Local normal and view vectors are constant and aligned. - vec3 V = vec3(0.0, 0.0, 1.0); - float NdotV = 1.0; + float alpha = mx_latlong_lod_to_alpha(float($envPrefilterMip)); float G1V = mx_ggx_smith_G1(NdotV, alpha); // Integrate the LD term for the given environment and alpha. diff --git a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl index 85430c00ca..a27f717a24 100644 --- a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl @@ -594,6 +594,7 @@ vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D envSam return textureLod(envSampler, uv, lod).rgb; } +// Return the mip level with the appropriate coverage for a filtered importance sample. // https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html // Section 20.4 Equation 13 float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) @@ -604,16 +605,16 @@ float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamp return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); } +// Return the mip level associated with the given alpha in a prefiltered environment. float mx_latlong_alpha_to_lod(float alpha) { - // Return the mip level associated with the given alpha in a prefiltered environment. float lodBias = (alpha < 0.25) ? sqrt(alpha) : 0.5 * alpha + 0.375; return lodBias * float($envRadianceMips - 1); } +// Return the alpha associated with the given mip level in a prefiltered environment. float mx_latlong_lod_to_alpha(float lod) { - // Return the alpha associated with the given mip level in a prefiltered environment. float lodBias = lod / float($envRadianceMips - 1); return (lodBias < 0.5) ? mx_square(lodBias) : 2.0 * (lodBias - 0.375); } diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index b9351ddc08..e506c700c7 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -587,14 +587,14 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c // Emit directional albedo table code. if (context.getOptions().hwWriteAlbedoTable) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_table.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_albedo_table.glsl", context, stage); emitLineBreak(stage); } // Emit environment prefiltering code if (context.getOptions().hwWriteEnvPrefilter) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_prefilter_environment.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl", context, stage); emitLineBreak(stage); } @@ -645,7 +645,7 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c } else if (context.getOptions().hwWriteEnvPrefilter) { - emitLine(outputSocket->getVariable() + " = vec4(mx_prefilter_environment(), 1.0)", stage); + emitLine(outputSocket->getVariable() + " = vec4(mx_generate_prefilter_env(), 1.0)", stage); } else { diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 5749f0d211..10c368177c 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -1055,14 +1055,14 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co // Emit directional albedo table code. if (context.getOptions().hwWriteAlbedoTable) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_table.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_albedo_table.glsl", context, stage); emitLineBreak(stage); } // Emit environment prefiltering code if (context.getOptions().hwWriteEnvPrefilter) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_prefilter_environment.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl", context, stage); emitLineBreak(stage); } @@ -1113,7 +1113,7 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co } else if (context.getOptions().hwWriteEnvPrefilter) { - emitLine(outputSocket->getVariable() + " = float4(mx_prefilter_environment(), 1.0)", stage); + emitLine(outputSocket->getVariable() + " = float4(mx_generate_prefilter_env(), 1.0)", stage); } else { From d4c6f60984b9ec4d7be69d8402b97b0d18e63591 Mon Sep 17 00:00:00 2001 From: ld-kerley <154285602+ld-kerley@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:11:01 -0800 Subject: [PATCH 12/17] Fix missing MSL case in PyMaterialX build (#1630) Fix missing MATERIALX_BUILD_GEN_MSL in CMakeLists.txt for PyMaterialX. --- source/PyMaterialX/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/PyMaterialX/CMakeLists.txt b/source/PyMaterialX/CMakeLists.txt index eda1ba0db4..2bbe2c9506 100644 --- a/source/PyMaterialX/CMakeLists.txt +++ b/source/PyMaterialX/CMakeLists.txt @@ -44,7 +44,7 @@ endif() add_subdirectory(PyMaterialXCore) add_subdirectory(PyMaterialXFormat) -if (MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL) +if (MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL OR MATERIALX_BUILD_GEN_MSL) add_subdirectory(PyMaterialXGenShader) if (MATERIALX_BUILD_GEN_GLSL) add_subdirectory(PyMaterialXGenGlsl) From 473d563896a4accb1d570726704ba7aba137779a Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Wed, 3 Jan 2024 19:22:12 -0500 Subject: [PATCH 13/17] Add enumeration support to web viewer (#1632) - Scan for `enum` and `enumvalues` if attributes exist on input. If no `enumvalues` exist then map to "default" of 0..<enum list size>. - Create a drop-down for each enumerated input. --- javascript/MaterialXView/source/viewer.js | 34 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index b0bcd98fbf..3eff576be3 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -949,11 +949,17 @@ export class Material } var step = 0; var enumList = [] + var enumValues = [] if (nodeDefInput) { if (nodeDefInput.hasAttribute('enum')) { + // Get enum and enum values attributes (if present) enumList = nodeDefInput.getAttribute('enum').split(','); + if (nodeDefInput.hasAttribute('enumvalues')) + { + enumValues = nodeDefInput.getAttribute('enumvalues').split(',').map(Number); + } } else { @@ -989,8 +995,30 @@ export class Material } else { - // TODO: Add enum support - currentFolder.add(material.uniforms[name], 'value' ).name(path); + // Map enumList strings to values + // Map to 0..N if no values are specified via enumvalues attribute + if (enumValues.length == 0) + { + for (let i = 0; i < enumList.length; ++i) + { + enumValues.push(i); + } + } + const enumeration = {}; + enumList.forEach((str, index) => { + enumeration[str] = enumValues[index]; + }); + + // Function to handle enum drop-down + function handleDropdownChange(value) { + if (material.uniforms[name]) + { + material.uniforms[name].value = value; + } + } + const defaultOption = enumList[value]; // Set the default selected option + const dropdownController = gui.add(enumeration, defaultOption, enumeration).name(path); + dropdownController.onChange(handleDropdownChange); } } break; @@ -1046,7 +1074,7 @@ export class Material break; case 'color3': - // Irksome way to mape arrays to colors and back + // Irksome way to map arrays to colors and back uniformToUpdate = material.uniforms[name]; if (uniformToUpdate && value != null) { From 39d6d5b614d7f9e77fe82d36f18c70f5139a81a3 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 3 Jan 2024 16:23:31 -0800 Subject: [PATCH 14/17] Initial nprlib with viewdirection node (#1631) This changelist introduces an NPR (non-photorealistic rendering) data library to MaterialX, initially consisting of a single `viewdirection` node. The NPR data library is designed for the portable expression of artistic, non-physically-based materials, with common examples being cartoon shading, architectural diagrams, and edge highlighting. In future versions of MaterialX, we expect this data library to be extended with additional primitives and artist-facing graphs as they are requested by the graphics community and approved by the MaterialX TSC. For shader generation, MaterialX initially supports the NPR data library in GLSL, ESSL, MSL, and OSL, with MDL being omitted for now, based on intentional restrictions in its design philosophy. --- .../nprlib/genglsl/nprlib_genglsl_impl.mtlx | 17 ++++++ .../nprlib/genmdl/nprlib_genmdl_impl.mtlx | 17 ++++++ .../nprlib/genmsl/nprlib_genmsl_impl.mtlx | 17 ++++++ .../nprlib/genosl/nprlib_genosl_impl.mtlx | 17 ++++++ libraries/nprlib/nprlib_defs.mtlx | 23 ++++++++ ...nvmap_shader.mtlx => environment_map.mtlx} | 21 +++---- resources/Materials/TestSuite/_options.mtlx | 2 +- .../TestSuite/nprlib/edge_brighten.mtlx | 28 ++++++++++ .../Materials/TestSuite/nprlib/starfield.mtlx | 25 +++++++++ .../MaterialXGenGlsl/GlslShaderGenerator.cpp | 3 + .../Nodes/ViewDirectionNodeGlsl.cpp | 55 +++++++++++++++++++ .../Nodes/ViewDirectionNodeGlsl.h | 26 +++++++++ .../MaterialXGenMdl/mdl/materialx/stdlib.mdl | 16 ++++++ source/MaterialXGenMsl/MslShaderGenerator.cpp | 3 + .../Nodes/ViewDirectionNodeMsl.cpp | 55 +++++++++++++++++++ .../Nodes/ViewDirectionNodeMsl.h | 26 +++++++++ source/MaterialXRender/ShaderMaterial.cpp | 2 +- source/MaterialXView/Viewer.cpp | 54 +----------------- 18 files changed, 338 insertions(+), 69 deletions(-) create mode 100644 libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx create mode 100644 libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx create mode 100644 libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx create mode 100644 libraries/nprlib/genosl/nprlib_genosl_impl.mtlx create mode 100644 libraries/nprlib/nprlib_defs.mtlx rename resources/Lights/{envmap_shader.mtlx => environment_map.mtlx} (69%) create mode 100644 resources/Materials/TestSuite/nprlib/edge_brighten.mtlx create mode 100644 resources/Materials/TestSuite/nprlib/starfield.mtlx create mode 100644 source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp create mode 100644 source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h create mode 100644 source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp create mode 100644 source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h diff --git a/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx new file mode 100644 index 0000000000..7ddc4cee83 --- /dev/null +++ b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx new file mode 100644 index 0000000000..b6472e0c51 --- /dev/null +++ b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx new file mode 100644 index 0000000000..b8f9a4e3aa --- /dev/null +++ b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx b/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx new file mode 100644 index 0000000000..0b077b6406 --- /dev/null +++ b/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/nprlib_defs.mtlx b/libraries/nprlib/nprlib_defs.mtlx new file mode 100644 index 0000000000..e724658ae5 --- /dev/null +++ b/libraries/nprlib/nprlib_defs.mtlx @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/resources/Lights/envmap_shader.mtlx b/resources/Lights/environment_map.mtlx similarity index 69% rename from resources/Lights/envmap_shader.mtlx rename to resources/Lights/environment_map.mtlx index 8c9c6ec0f5..abd14d546b 100644 --- a/resources/Lights/envmap_shader.mtlx +++ b/resources/Lights/environment_map.mtlx @@ -1,17 +1,10 @@ - + - - - - - - - - + - + @@ -46,11 +39,11 @@ - + - - - + + + diff --git a/resources/Materials/TestSuite/_options.mtlx b/resources/Materials/TestSuite/_options.mtlx index bb29fbd7c1..1da00394e6 100644 --- a/resources/Materials/TestSuite/_options.mtlx +++ b/resources/Materials/TestSuite/_options.mtlx @@ -91,7 +91,7 @@ - + diff --git a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx new file mode 100644 index 0000000000..7e9aca7f22 --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/nprlib/starfield.mtlx b/resources/Materials/TestSuite/nprlib/starfield.mtlx new file mode 100644 index 0000000000..6898054a6d --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/starfield.mtlx @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index e506c700c7..5b20ee1b03 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,8 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, FrameNodeGlsl::create); // registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, TimeNodeGlsl::create); + // + registerImplementation("IM_viewdirection_vector3_" + GlslShaderGenerator::TARGET, ViewDirectionNodeGlsl::create); // registerImplementation("IM_surface_" + GlslShaderGenerator::TARGET, SurfaceNodeGlsl::create); diff --git a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp new file mode 100644 index 0000000000..198465c9af --- /dev/null +++ b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp @@ -0,0 +1,55 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +MATERIALX_NAMESPACE_BEGIN + +ShaderNodeImplPtr ViewDirectionNodeGlsl::create() +{ + return std::make_shared(); +} + +void ViewDirectionNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +{ + ShaderStage& vs = shader.getStage(Stage::VERTEX); + ShaderStage& ps = shader.getStage(Stage::PIXEL); + + addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); + addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); + addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps); +} + +void ViewDirectionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + const ShaderGenerator& shadergen = context.getShaderGenerator(); + + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { + VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); + const string prefix = vertexData.getInstance() + "."; + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + if (!position->isEmitted()) + { + position->setEmitted(); + shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); + } + } + + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); + const string prefix = vertexData.getInstance() + "."; + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + shadergen.emitLineBegin(stage); + shadergen.emitOutput(node.getOutput(), true, false, context, stage); + shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage); + shadergen.emitLineEnd(stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h new file mode 100644 index 0000000000..24cafe2f1d --- /dev/null +++ b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h @@ -0,0 +1,26 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_VIEWDIRECTIONNODEGLSL_H +#define MATERIALX_VIEWDIRECTIONNODEGLSL_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// ViewDirection node implementation for GLSL +class MX_GENGLSL_API ViewDirectionNodeGlsl : public GlslImplementation +{ + public: + static ShaderNodeImplPtr create(); + + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl index 4ba4f0875a..4cae1547aa 100644 --- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl @@ -1366,6 +1366,22 @@ export float mx_time_float( return ::state::animation_time(); } +export float3 mx_viewdirection_vector3( + uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_world) + [[ + anno::description("Enumeration {model,object,world}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: nprlib") + ]] +{ + // Not implemented: mx_viewdirection_vector3 + float3 defaultValue = float3(0.0, 0.0, 1.0); + return defaultValue; +} + export color mx_modulo_color3( color mxp_in1 = color(0.0, 0.0, 0.0), color mxp_in2 = color(1.0, 1.0, 1.0) diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 10c368177c..7a2461a5a8 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -200,6 +201,8 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, FrameNodeMsl::create); // registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, TimeNodeMsl::create); + // + registerImplementation("IM_viewdirection_vector3_" + MslShaderGenerator::TARGET, ViewDirectionNodeMsl::create); // registerImplementation("IM_surface_" + MslShaderGenerator::TARGET, SurfaceNodeMsl::create); diff --git a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp new file mode 100644 index 0000000000..84a6b02b4f --- /dev/null +++ b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp @@ -0,0 +1,55 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +MATERIALX_NAMESPACE_BEGIN + +ShaderNodeImplPtr ViewDirectionNodeMsl::create() +{ + return std::make_shared(); +} + +void ViewDirectionNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +{ + ShaderStage& vs = shader.getStage(Stage::VERTEX); + ShaderStage& ps = shader.getStage(Stage::PIXEL); + + addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); + addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); + addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps); +} + +void ViewDirectionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + const ShaderGenerator& shadergen = context.getShaderGenerator(); + + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { + VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); + const string prefix = vertexData.getInstance() + "."; + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + if (!position->isEmitted()) + { + position->setEmitted(); + shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); + } + } + + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); + const string prefix = vertexData.getInstance() + "."; + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + shadergen.emitLineBegin(stage); + shadergen.emitOutput(node.getOutput(), true, false, context, stage); + shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage); + shadergen.emitLineEnd(stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h new file mode 100644 index 0000000000..be7a40108a --- /dev/null +++ b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h @@ -0,0 +1,26 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_VIEWDIRECTIONNODEMSL_H +#define MATERIALX_VIEWDIRECTIONNODEMSL_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// ViewDirection node implementation for MSL +class MX_GENMSL_API ViewDirectionNodeMsl : public MslImplementation +{ + public: + static ShaderNodeImplPtr create(); + + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXRender/ShaderMaterial.cpp b/source/MaterialXRender/ShaderMaterial.cpp index 4e8ccc491f..c61c6d3c04 100644 --- a/source/MaterialXRender/ShaderMaterial.cpp +++ b/source/MaterialXRender/ShaderMaterial.cpp @@ -73,7 +73,7 @@ bool ShaderMaterial::generateEnvironmentShader(GenContext& context, readFromXmlFile(envDoc, filename); doc->importLibrary(envDoc); - NodeGraphPtr envGraph = doc->getNodeGraph("environmentDraw"); + NodeGraphPtr envGraph = doc->getNodeGraph("envMap"); if (!envGraph) { return false; diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index eeaf7a82b0..f6da076f17 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -137,55 +137,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } -// ViewDir implementation for GLSL -// as needed for the environment shader. -template -class ViewDir : public NodeGraphImpl -{ -public: - static mx::ShaderNodeImplPtr create() - { - return std::make_shared(); - } - - void createVariables(const mx::ShaderNode&, mx::GenContext&, mx::Shader& shader) const override - { - mx::ShaderStage& vs = shader.getStage(mx::Stage::VERTEX); - mx::ShaderStage& ps = shader.getStage(mx::Stage::PIXEL); - addStageInput(mx::HW::VERTEX_INPUTS, mx::Type::VECTOR3, mx::HW::T_IN_POSITION, vs); - addStageConnector(mx::HW::VERTEX_DATA, mx::Type::VECTOR3, mx::HW::T_POSITION_WORLD, vs, ps); - addStageUniform(mx::HW::PRIVATE_UNIFORMS, mx::Type::VECTOR3, mx::HW::T_VIEW_POSITION, ps); - } - - void emitFunctionCall(const mx::ShaderNode& node, mx::GenContext& context, mx::ShaderStage& stage) const override - { - const mx::ShaderGenerator& shadergen = context.getShaderGenerator(); - - DEFINE_SHADER_STAGE(stage, mx::Stage::VERTEX) - { - mx::VariableBlock& vertexData = stage.getOutputBlock(mx::HW::VERTEX_DATA); - const mx::string prefix = vertexData.getInstance() + "."; - mx::ShaderPort* position = vertexData[mx::HW::T_POSITION_WORLD]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); - } - } - - DEFINE_SHADER_STAGE(stage, mx::Stage::PIXEL) - { - mx::VariableBlock& vertexData = stage.getInputBlock(mx::HW::VERTEX_DATA); - const mx::string prefix = vertexData.getInstance() + "."; - mx::ShaderPort* position = vertexData[mx::HW::T_POSITION_WORLD]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + mx::HW::T_VIEW_POSITION + ")", stage); - shadergen.emitLineEnd(stage); - } - } -}; - } // anonymous namespace // @@ -297,10 +248,8 @@ Viewer::Viewer(const std::string& materialFilename, _renderPipeline = MetalRenderPipeline::create(this); _renderPipeline->initialize(ng::metal_device(), ng::metal_command_queue()); - _genContext.getShaderGenerator().registerImplementation("IM_viewdir_vector3_" + _genContext.getShaderGenerator().getTarget(), ViewDir::create); #else _renderPipeline = GLRenderPipeline::create(this); - _genContext.getShaderGenerator().registerImplementation("IM_viewdir_vector3_" + _genContext.getShaderGenerator().getTarget(), ViewDir::create); // Set Essl generator options _genContextEssl.getOptions().targetColorSpaceOverride = "lin_rec709"; @@ -317,7 +266,6 @@ Viewer::Viewer(const std::string& materialFilename, _genContextMdl.getOptions().targetColorSpaceOverride = "lin_rec709"; _genContextMdl.getOptions().fileTextureVerticalFlip = false; #endif - // Register the API Spcefic implementation for used by the environment shader. } void Viewer::initialize() @@ -2395,7 +2343,7 @@ mx::MaterialPtr Viewer::getEnvironmentMaterial() { if (!_envMaterial) { - mx::FilePath envFilename = _searchPath.find(mx::FilePath("resources/Lights/envmap_shader.mtlx")); + mx::FilePath envFilename = _searchPath.find(mx::FilePath("resources/Lights/environment_map.mtlx")); try { _envMaterial = _renderPipeline->createMaterial(); From 8ab122f8cda6a98a094294b1494e423589afdfc9 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 3 Jan 2024 17:39:05 -0800 Subject: [PATCH 15/17] Improve shader generation for viewdirection This changelist improves shader generation logic for the new viewdirection node, allowing it to work correctly in derived hardware languages such as ESSL. --- source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp | 6 +++--- source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp index 198465c9af..f9714b5d33 100644 --- a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp @@ -26,12 +26,12 @@ void ViewDirectionNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shad void ViewDirectionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const ShaderGenerator& shadergen = context.getShaderGenerator(); + const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); DEFINE_SHADER_STAGE(stage, Stage::VERTEX) { VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = vertexData.getInstance() + "."; + const string prefix = shadergen.getVertexDataPrefix(vertexData); ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; if (!position->isEmitted()) { @@ -43,7 +43,7 @@ void ViewDirectionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = vertexData.getInstance() + "."; + const string prefix = shadergen.getVertexDataPrefix(vertexData); ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; shadergen.emitLineBegin(stage); shadergen.emitOutput(node.getOutput(), true, false, context, stage); diff --git a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp index 84a6b02b4f..1443b5c320 100644 --- a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp @@ -26,12 +26,12 @@ void ViewDirectionNodeMsl::createVariables(const ShaderNode&, GenContext&, Shade void ViewDirectionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const ShaderGenerator& shadergen = context.getShaderGenerator(); + const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); DEFINE_SHADER_STAGE(stage, Stage::VERTEX) { VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = vertexData.getInstance() + "."; + const string prefix = shadergen.getVertexDataPrefix(vertexData); ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; if (!position->isEmitted()) { @@ -43,7 +43,7 @@ void ViewDirectionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = vertexData.getInstance() + "."; + const string prefix = shadergen.getVertexDataPrefix(vertexData); ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; shadergen.emitLineBegin(stage); shadergen.emitOutput(node.getOutput(), true, false, context, stage); From 5def239b82c20a7bf4875686e03743bc421a68f6 Mon Sep 17 00:00:00 2001 From: Frieder Erdmann <55715326+friedererdmann@users.noreply.github.com> Date: Thu, 4 Jan 2024 04:03:03 +0100 Subject: [PATCH 16/17] Add creatematrix nodes to build matrices from vectors (#1553) I'm opening this PR to add creatematrix, a constructor for Matrix33 from 3 Vector3s, Matrix44 from 4 Vector3s and Matrix44 from 4 Vector4s from the specification document (https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/documents/Specification/MaterialX.Specification.md#math-nodes). --- .../mx_creatematrix_vector3_matrix33.glsl | 6 +++ .../mx_creatematrix_vector3_matrix44.glsl | 7 ++++ .../mx_creatematrix_vector4_matrix44.glsl | 7 ++++ .../stdlib/genglsl/stdlib_genglsl_impl.mtlx | 5 +++ .../stdlib/genmdl/stdlib_genmdl_impl.mtlx | 5 +++ .../stdlib/genmsl/stdlib_genmsl_impl.mtlx | 5 +++ libraries/stdlib/genosl/mx_creatematrix.osl | 23 +++++++++++ .../stdlib/genosl/stdlib_genosl_impl.mtlx | 5 +++ libraries/stdlib/stdlib_defs.mtlx | 27 +++++++++++++ .../TestSuite/stdlib/math/matrix.mtlx | 29 ++++++++++++++ .../MaterialXGenMdl/mdl/materialx/stdlib.mdl | 40 +++++++++++++++++++ 11 files changed, 159 insertions(+) create mode 100644 libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl create mode 100644 libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl create mode 100644 libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl create mode 100644 libraries/stdlib/genosl/mx_creatematrix.osl create mode 100644 resources/Materials/TestSuite/stdlib/math/matrix.mtlx diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl new file mode 100644 index 0000000000..aa10ef5b98 --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl @@ -0,0 +1,6 @@ +void mx_creatematrix_vector3_matrix33(vec3 in1, vec3 in2, vec3 in3, out mat3 result) +{ + result = mat3(in1.x, in1.y, in1.z, + in2.x, in2.y, in2.z, + in3.x, in3.y, in3.z); +} diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl new file mode 100644 index 0000000000..194fad421a --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl @@ -0,0 +1,7 @@ +void mx_creatematrix_vector3_matrix44(vec3 in1, vec3 in2, vec3 in3, vec3 in4, out mat4 result) +{ + result = mat4(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + in4.x, in4.y, in4.z, 1.0); +} diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl new file mode 100644 index 0000000000..665a22212b --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl @@ -0,0 +1,7 @@ +void mx_creatematrix_vector4_matrix44(vec4 in1, vec4 in2, vec4 in3, vec4 in4, out mat4 result) +{ + result = mat4(in1.x, in1.y, in1.z, in1.w, + in2.x, in2.y, in2.z, in2.w, + in3.x, in3.y, in3.z, in3.w, + in4.x, in4.y, in4.z, in4.w); +} diff --git a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx index 07aae6ce66..6f67b21d33 100644 --- a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx +++ b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx @@ -748,6 +748,11 @@ + + + + + diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx index 022f0896f1..6c550c92db 100644 --- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx +++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx @@ -754,6 +754,11 @@ + + + + + diff --git a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx index dea1c49636..40be6f8c46 100644 --- a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx +++ b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx @@ -748,6 +748,11 @@ + + + + + diff --git a/libraries/stdlib/genosl/mx_creatematrix.osl b/libraries/stdlib/genosl/mx_creatematrix.osl new file mode 100644 index 0000000000..933dce00ba --- /dev/null +++ b/libraries/stdlib/genosl/mx_creatematrix.osl @@ -0,0 +1,23 @@ +void mx_creatematrix_vector3_matrix33(vector in1, vector in2, vector in3, out matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + 0.0, 0.0, 0.0, 1.0); +} + +void mx_creatematrix_vector3_matrix44(vector3 in1, vector3 in2, vector3 in3, vector3 in4, out matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + in4.x, in4.y, in4.z, 1.0); +} + +void mx_creatematrix_vector4_matrix44(vector4 in1, vector4 in2, vector4 in3, vector4 in4, out matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, in1.w, + in2.x, in2.y, in2.z, in2.w, + in3.x, in3.y, in3.z, in3.w, + in4.x, in4.y, in4.z, in4.w); +} diff --git a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx index 42828ce641..a984d912b8 100644 --- a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx +++ b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx @@ -751,6 +751,11 @@ + + + + + diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx index 3f187e2be1..90ccb57a98 100644 --- a/libraries/stdlib/stdlib_defs.mtlx +++ b/libraries/stdlib/stdlib_defs.mtlx @@ -4359,6 +4359,33 @@ + + + + + + + + + + + + + + + + + + + + + + + +