From 6ff89e0f5ddb6f9f19feccd2f6f010aa44fbb124 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 3 Dec 2020 14:42:36 -0500 Subject: [PATCH 01/35] Initial check-in + test. --- .../nodegraph_inputs/nodegraph_nodegraph.mtlx | 47 +++++++++++++++++++ source/MaterialXCore/Interface.cpp | 34 +++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx new file mode 100644 index 0000000000..20d45173bc --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index b0725104ff..a11aa12a17 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -329,8 +329,15 @@ OutputPtr Input::getConnectedOutput() const // Look for output on a node else if (hasNodeName()) { + const string& nodeName = getNodeName(); ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(getNodeName()) : nullptr; + NodePtr node = graph ? graph->getNode(nodeName) : nullptr; + if (!node && graph) + { + ConstElementPtr parent = graph->getParent(); + graph = parent->getAncestorOfType(); + node = graph ? graph->getNode(nodeName) : nullptr; + } if (node) { std::vector outputs = node->getOutputs(); @@ -357,6 +364,21 @@ OutputPtr Input::getConnectedOutput() const NodePtr Input::getConnectedNode() const { + // Traverse through interface names to nodegraph input + const string& interfaceName = getInterfaceName(); + if (!interfaceName.empty()) + { + ConstNodeGraphPtr graph = getAncestorOfType(); + if (graph && !graph->hasNodeDefString()) + { + InputPtr graphInput = graph->getInput(interfaceName); + if (graphInput && (graphInput->hasNodeName() || graphInput->hasNodeGraphString())) + { + return graphInput->getConnectedNode(); + } + } + } + OutputPtr output = getConnectedOutput(); if (output) { @@ -366,8 +388,16 @@ NodePtr Input::getConnectedNode() const } if (hasNodeName()) { + // Check on current parent, and graph parent if any + const string& nodeName = getNodeName(); ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(getNodeName()) : nullptr; + NodePtr node = graph ? graph->getNode(nodeName) : nullptr; + if (!node && graph) + { + ConstElementPtr parent = graph->getParent(); + graph = parent->getAncestorOfType(); + node = graph ? graph->getNode(nodeName) : nullptr; + } if (node) { return node; From 3983d410ff8f92debc1737f88fd0a687742ef412 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 3 Dec 2020 16:53:26 -0500 Subject: [PATCH 02/35] Add testing and validation. Fix runtime mtlx export to output "nodegraph" or "nodename" as required based on connection type. --- source/MaterialXCore/Interface.cpp | 20 ++++++++----- source/MaterialXCore/Interface.h | 4 +++ source/MaterialXCore/Node.cpp | 27 +++++++++++++++++ source/MaterialXRuntime/RtFileIo.cpp | 13 +++++++-- .../MaterialXTest/MaterialXCore/Traversal.cpp | 29 ++++++++++++++++++- 5 files changed, 82 insertions(+), 11 deletions(-) diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index a11aa12a17..84284664b0 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -362,22 +362,28 @@ OutputPtr Input::getConnectedOutput() const return result; } -NodePtr Input::getConnectedNode() const +InputPtr Input::getInterface() const { - // Traverse through interface names to nodegraph input const string& interfaceName = getInterfaceName(); if (!interfaceName.empty()) { ConstNodeGraphPtr graph = getAncestorOfType(); if (graph && !graph->hasNodeDefString()) { - InputPtr graphInput = graph->getInput(interfaceName); - if (graphInput && (graphInput->hasNodeName() || graphInput->hasNodeGraphString())) - { - return graphInput->getConnectedNode(); - } + return graph->getInput(interfaceName); } } + return nullptr; +} + +NodePtr Input::getConnectedNode() const +{ + // Traverse through interface names to nodegraph input + InputPtr graphInput = getInterface(); + if (graphInput && (graphInput->hasNodeName() || graphInput->hasNodeGraphString())) + { + return graphInput->getConnectedNode(); + } OutputPtr output = getConnectedOutput(); if (output) diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index c9ae9ef259..ffbda6b9a1 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -268,6 +268,10 @@ class Input : public PortElement /// @name Traversal /// @{ + /// Return the input on the parent graph corresponding to the interface name + /// for the element. + InputPtr getInterface() const; + /// Return the Edge with the given index that lies directly upstream from /// this element in the dataflow graph. Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index d44ff80245..655b52c4d4 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -634,6 +634,33 @@ bool NodeGraph::validate(string* message) const validateRequire(getOutputCount() == nodeDef->getActiveOutputs().size(), res, message, "NodeGraph implementation has a different number of outputs than its NodeDef"); } } + // Check interfaces on nodegraphs which are not definitions + if (!hasNodeDefString()) + { + for (NodePtr node : getNodes()) + { + for (InputPtr input : node->getInputs()) + { + const string& interfaceName = input->getInterfaceName(); + if (!interfaceName.empty()) + { + InputPtr interfaceInput = input->getInterface(); + validateRequire(interfaceInput != nullptr, res, message, "NodeGraph interface input: \"" + interfaceName + "\" does not exist on nodegraph"); + string connectedNodeName = interfaceInput ? interfaceInput->getNodeName() : EMPTY_STRING; + if (connectedNodeName.empty()) + { + connectedNodeName = interfaceInput->getNodeGraphString(); + } + if (interfaceInput && !connectedNodeName.empty()) + { + NodePtr connectedNode = input->getConnectedNode(); + validateRequire(connectedNode != nullptr, res, message, "Nodegraph input: \"" + interfaceInput->getNamePath() + + "\" specifies connection to non existent node: \"" + connectedNodeName + "\""); + } + } + } + } + } return GraphElement::validate(message) && res; } diff --git a/source/MaterialXRuntime/RtFileIo.cpp b/source/MaterialXRuntime/RtFileIo.cpp index 689ca94373..dc1784668a 100644 --- a/source/MaterialXRuntime/RtFileIo.cpp +++ b/source/MaterialXRuntime/RtFileIo.cpp @@ -939,9 +939,16 @@ namespace { // Write connections to upstream nodes. RtOutput source = nodegraphInput.getConnection(); - RtNode sourceNode = source.getParent(); - input->setNodeName(sourceNode.getName()); - if (sourceNode.numOutputs() > 1) + RtPrim sourcePrim = source.getParent(); + if (sourcePrim.hasApi()) + { + input->setNodeGraphString(sourcePrim.getName()); + } + else + { + input->setNodeName(sourcePrim.getName()); + } + if (sourcePrim.numOutputs() > 1) { input->setOutputString(source.getName()); } diff --git a/source/MaterialXTest/MaterialXCore/Traversal.cpp b/source/MaterialXTest/MaterialXCore/Traversal.cpp index 38e22068f8..d6c12a99bb 100644 --- a/source/MaterialXTest/MaterialXCore/Traversal.cpp +++ b/source/MaterialXTest/MaterialXCore/Traversal.cpp @@ -6,10 +6,12 @@ #include #include +#include +#include namespace mx = MaterialX; -TEST_CASE("Traversal", "[traversal]") +TEST_CASE("IntraGraph Traversal", "[traversal]") { // Test null iterators. mx::TreeIterator nullTree = mx::NULL_TREE_ITERATOR; @@ -171,3 +173,28 @@ TEST_CASE("Traversal", "[traversal]") REQUIRE(!output->hasUpstreamCycle()); REQUIRE(doc->validate()); } + +TEST_CASE("InterGraph Tranversal", "[traversal]") +{ + mx::FileSearchPath searchPath; + const mx::FilePath currentPath = mx::FilePath::getCurrentPath(); + searchPath.append(currentPath / mx::FilePath("libraries")); + + mx::DocumentPtr doc = mx::createDocument(); + mx::StringSet libFiles = mx::loadLibraries({ "stdlib", "pbrlib", "bxdf" }, searchPath, doc); + + mx::FilePath testFile = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx"); + mx::readFromXmlFile(doc, testFile, searchPath); + REQUIRE(doc->validate()); + + for (mx::NodeGraphPtr graph : doc->getNodeGraphs()) + { + for (mx::InputPtr interfaceInput : graph->getInputs()) + { + if (interfaceInput && (!interfaceInput->getNodeName().empty() || !interfaceInput->getNodeGraphString().empty())) + { + REQUIRE(interfaceInput->getConnectedNode() != nullptr); + } + } + } +} From e2260d511f114c5247c4581a24e46419b1172afd Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 4 Dec 2020 09:24:08 -0500 Subject: [PATCH 03/35] Fix invalid test document found via new interface validation. --- .../stdlib/upgrade/1_38_parameter_to_input.mtlx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx index 18c1925d8b..b44b473fd4 100644 --- a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx +++ b/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx @@ -2,10 +2,10 @@ - + - + @@ -15,8 +15,8 @@ - - + + @@ -33,12 +33,12 @@ - + - + @@ -63,14 +63,14 @@ - + - + From a92ad8a218d3c824857e84c94743f1d11fb1d916 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 4 Dec 2020 12:25:59 -0500 Subject: [PATCH 04/35] Add test for : - multiple output connectins - downstream node connections. --- .../nodegraph_inputs/nodegraph_nodegraph.mtlx | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx index 20d45173bc..b7350fe991 100644 --- a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx @@ -3,32 +3,59 @@ + - + - + + + + + - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + - + @@ -36,7 +63,7 @@ - + From 2e25652449d992daaca815182d368ae8a8d548a0 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 7 Dec 2020 17:06:22 -0500 Subject: [PATCH 05/35] multi-output node -> nodegraph update. --- .../nodegraph_inputs/nodegraph_nodegraph.mtlx | 71 +++++++++++++++++-- source/MaterialXCore/Interface.cpp | 5 ++ source/MaterialXCore/Node.cpp | 15 +++- 3 files changed, 85 insertions(+), 6 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx index b7350fe991..24ce99374b 100644 --- a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx @@ -2,13 +2,13 @@ - - + + - + - + @@ -40,6 +40,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -53,7 +114,7 @@ - + diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index 84284664b0..9f86990fc1 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -468,6 +468,11 @@ bool Input::validate(string* message) const { validateRequire(getDefaultGeomProp() != nullptr, res, message, "Invalid defaultgeomprop string"); } + InputPtr interfaceInput = getInterface(); + if (interfaceInput) + { + return interfaceInput->validate() && res; + } return PortElement::validate(message) && res; } diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index 655b52c4d4..fee9908b19 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -118,7 +118,20 @@ OutputPtr Node::getNodeDefOutput(ElementPtr connectingElement) OutputPtr output = OutputPtr(); if (connectedInput) { - output = connectedInput->getConnectedOutput(); + InputPtr interfaceInput = nullptr; + if (connectedInput->hasInterfaceName()) + { + interfaceInput = connectedInput->getInterface(); + if (interfaceInput) + { + outputName = &(interfaceInput->getOutputString()); + output = interfaceInput->getConnectedOutput(); + } + } + if (!interfaceInput) + { + output = connectedInput->getConnectedOutput(); + } } if (output) { From 92546db8d9f300d82165e62d5875dce108a4dd49 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 7 Dec 2020 17:16:44 -0500 Subject: [PATCH 06/35] Fix test. --- .../stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx index 24ce99374b..dd2ab4b33f 100644 --- a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx @@ -63,7 +63,6 @@ - - - + + From 134fb2dd71a507a44453b7198b72ed8e4007dce5 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 8 Dec 2020 15:23:47 -0500 Subject: [PATCH 07/35] Add call to connect nodegraphs to each other same as node for Runtime. Add new test to start testing cascaded nodegraphs. --- .../nodegraph_inputs/cascade_nodegraphs.mtlx | 69 +++++++++++++++++++ source/MaterialXRuntime/RtFileIo.cpp | 62 ++++++++++------- 2 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 resources/Materials/TestSuite/stdlib/nodegraph_inputs/cascade_nodegraphs.mtlx diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/cascade_nodegraphs.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/cascade_nodegraphs.mtlx new file mode 100644 index 0000000000..fada0b4114 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/cascade_nodegraphs.mtlx @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MaterialXRuntime/RtFileIo.cpp b/source/MaterialXRuntime/RtFileIo.cpp index dc1784668a..02ec8156ed 100644 --- a/source/MaterialXRuntime/RtFileIo.cpp +++ b/source/MaterialXRuntime/RtFileIo.cpp @@ -210,40 +210,53 @@ namespace output->connect(input); } - void createNodeConnections(const vector& nodeElements, PvtPrim* parent, PvtStage* stage, const PvtRenamingMapper& mapper) + void createNodeConnection(InterfaceElementPtr nodeElem, PvtPrim* parent, PvtStage* stage, const PvtRenamingMapper& mapper) { - for (const NodePtr& nodeElem : nodeElements) + PvtPrim* node = findPrimOrThrow(RtToken(nodeElem->getName()), parent, mapper); + for (InputPtr elemInput : nodeElem->getInputs()) { - PvtPrim* node = findPrimOrThrow(RtToken(nodeElem->getName()), parent, mapper); - for (const InputPtr& elemInput : nodeElem->getInputs()) + PvtInput* input = findInputOrThrow(RtToken(elemInput->getName()), node); + string connectedNodeName = elemInput->getNodeName(); + if (connectedNodeName.empty()) { - PvtInput* input = findInputOrThrow(RtToken(elemInput->getName()), node); - string connectedNodeName = elemInput->getNodeName(); - if (connectedNodeName.empty()) - { - connectedNodeName = elemInput->getNodeGraphString(); - } - if (!connectedNodeName.empty()) + connectedNodeName = elemInput->getNodeGraphString(); + } + if (!connectedNodeName.empty()) + { + PvtPrim* connectedNode = findPrimOrThrow(RtToken(connectedNodeName), parent, mapper); + RtToken outputName(elemInput->getOutputString()); + if (outputName == EMPTY_TOKEN && connectedNode) { - PvtPrim* connectedNode = findPrimOrThrow(RtToken(connectedNodeName), parent, mapper); - RtToken outputName(elemInput->getOutputString()); - if (outputName == EMPTY_TOKEN && connectedNode) + RtNode rtConnectedNode(connectedNode->hnd()); + auto output = rtConnectedNode.getOutput(); + if (output) { - RtNode rtConnectedNode(connectedNode->hnd()); - auto output = rtConnectedNode.getOutput(); - if (output) - { - outputName = output.getName(); - } + outputName = output.getName(); } - PvtOutput* output = findOutputOrThrow(outputName, connectedNode); - - createConnection(output, input, elemInput->getChannels(), stage); } + PvtOutput* output = findOutputOrThrow(outputName, connectedNode); + + createConnection(output, input, elemInput->getChannels(), stage); } } } + void createNodeConnections(const vector& nodeElements, PvtPrim* parent, PvtStage* stage, const PvtRenamingMapper& mapper) + { + for (auto nodeElem : nodeElements) + { + createNodeConnection(nodeElem->asA(), parent, stage, mapper); + } + } + + void createNodeGraphConnections(const vector& nodeElements, PvtPrim* parent, PvtStage* stage, const PvtRenamingMapper& mapper) + { + for (auto nodeElem : nodeElements) + { + createNodeConnection(nodeElem->asA(), parent, stage, mapper); + } + } + PvtPrim* readNodeDef(const NodeDefPtr& src, PvtStage* stage) { const RtToken name(src->getName()); @@ -729,6 +742,9 @@ namespace // Create connections between all root level nodes. createNodeConnections(doc->getNodes(), stage->getRootPrim(), stage, mapper); + // Create connections between all nodegraphs + createNodeGraphConnections(doc->getNodeGraphs(), stage->getRootPrim(), stage, mapper); + // Read look information if (!options || options->readLookInformation) { From c5fd321ac7e950af88a0600e5f443eeeb90f677b Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 8 Dec 2020 17:01:12 -0500 Subject: [PATCH 08/35] Fix codacy warning. --- source/MaterialXTest/MaterialXCore/Traversal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaterialXTest/MaterialXCore/Traversal.cpp b/source/MaterialXTest/MaterialXCore/Traversal.cpp index d6c12a99bb..ecdef65767 100644 --- a/source/MaterialXTest/MaterialXCore/Traversal.cpp +++ b/source/MaterialXTest/MaterialXCore/Traversal.cpp @@ -181,7 +181,7 @@ TEST_CASE("InterGraph Tranversal", "[traversal]") searchPath.append(currentPath / mx::FilePath("libraries")); mx::DocumentPtr doc = mx::createDocument(); - mx::StringSet libFiles = mx::loadLibraries({ "stdlib", "pbrlib", "bxdf" }, searchPath, doc); + mx::loadLibraries({ "stdlib", "pbrlib", "bxdf" }, searchPath, doc); mx::FilePath testFile = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx"); mx::readFromXmlFile(doc, testFile, searchPath); From 459c16cc3b0d2889de53632b53e7793ec77ad3be Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 24 Nov 2020 17:23:12 -0800 Subject: [PATCH 09/35] Simplify image codec test --- .../stdlib/texture/image_codecs.mtlx | 80 ++++++------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/texture/image_codecs.mtlx b/resources/Materials/TestSuite/stdlib/texture/image_codecs.mtlx index fb39657242..7659e7c8cf 100644 --- a/resources/Materials/TestSuite/stdlib/texture/image_codecs.mtlx +++ b/resources/Materials/TestSuite/stdlib/texture/image_codecs.mtlx @@ -1,75 +1,47 @@ - - + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - + From 2cc92db2a6171a7dfcfaa02f7958b20a6ae94716 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 25 Nov 2020 11:16:31 -0800 Subject: [PATCH 10/35] Additional parameter updates for 1.38 --- source/MaterialXCore/Document.cpp | 30 ++++++++++++------------------ source/MaterialXCore/Element.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index ecc9d326c8..47bbbf5ec4 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -502,14 +502,13 @@ void Document::upgradeVersion(bool applyFutureUpdates) child->removeAttribute("shadertype"); } } - else if (child->isA()) + else if (child->getCategory() == "parameter") { - ParameterPtr param = child->asA(); - if (param->getType() == "opgraphnode") + if (child->getAttribute(TypedElement::TYPE_ATTRIBUTE) == "opgraphnode") { if (elem->isA()) { - InputPtr input = changeChildCategory(elem, param, Input::CATEGORY)->asA(); + InputPtr input = updateChildSubclass(elem, child); input->setNodeName(input->getAttribute("value")); input->removeAttribute("value"); if (input->getConnectedNode()) @@ -811,12 +810,11 @@ void Document::upgradeVersion(bool applyFutureUpdates) { intest->setName("value1"); } - ParameterPtr cutoff = node->getParameter("cutoff"); + ElementPtr cutoff = node->getChild("cutoff"); if (cutoff) { - InputPtr value2 = node->addInput("value2", DEFAULT_TYPE_STRING); - value2->copyContentFrom(cutoff); - node->removeChild(cutoff->getName()); + cutoff = updateChildSubclass(node, cutoff); + cutoff->setName("value2"); } InputPtr in1 = node->getInput("in1"); InputPtr in2 = node->getInput("in2"); @@ -943,11 +941,10 @@ void Document::upgradeVersion(bool applyFutureUpdates) } for (auto nodedef : getMatchingNodeDefs(ROTATE3D)) { - ParameterPtr param = nodedef->getParameter(AXIS); - if (param) + ElementPtr axis = nodedef->getChild(AXIS); + if (axis) { - nodedef->removeParameter(AXIS); - nodedef->addInput(AXIS, "vector3"); + updateChildSubclass(nodedef, axis); } } @@ -984,13 +981,10 @@ void Document::upgradeVersion(bool applyFutureUpdates) } else if (nodeCategory == ROTATE3D) { - ParameterPtr param = node->getParameter(AXIS); - if (param) + ElementPtr axis = node->getChild(AXIS); + if (axis) { - const string v = param->getValueString(); - node->removeParameter(AXIS); - InputPtr input = node->addInput(AXIS, "vector3"); - input->setValueString(v); + updateChildSubclass(node, axis); } } } diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index 630a9c5a9c..20d325298e 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -566,12 +566,15 @@ class Element : public std::enable_shared_from_this /// type, then the zero value for the data type is returned. template T getTypedAttribute(const string& attrib) const { - try - { - return fromValueString(getAttribute(attrib)); - } - catch (ExceptionTypeError&) + if (hasAttribute(attrib)) { + try + { + return fromValueString(getAttribute(attrib)); + } + catch (ExceptionTypeError&) + { + } } return {}; } From 68e97c01ee8f5c67f154214e7dc259fd23dfc5ea Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 25 Nov 2020 16:59:13 -0800 Subject: [PATCH 11/35] Remove Parameter class This changelist removes the legacy Parameter class from the v1.38 branch of MaterialX. --- source/MaterialXCore/Document.cpp | 22 +- source/MaterialXCore/Element.cpp | 3 +- source/MaterialXCore/Interface.cpp | 149 +------------ source/MaterialXCore/Interface.h | 129 ----------- source/MaterialXCore/Material.cpp | 22 -- source/MaterialXCore/Material.h | 9 - source/MaterialXCore/Node.cpp | 3 +- source/MaterialXCore/Node.h | 6 +- .../Nodes/LightCompoundNodeGlsl.cpp | 6 +- .../Nodes/LightShaderNodeGlsl.cpp | 6 +- source/MaterialXGenShader/ShaderGraph.cpp | 201 ------------------ source/MaterialXGenShader/ShaderNode.cpp | 8 - .../PyMaterialX/PyMaterialXCore/PyElement.cpp | 1 - .../PyMaterialXCore/PyInterface.cpp | 13 -- 14 files changed, 16 insertions(+), 562 deletions(-) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 47bbbf5ec4..e4bd4fa34c 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -687,7 +687,7 @@ void Document::upgradeVersion(bool applyFutureUpdates) if (activeValue->getAttribute("publicname") == child->getName() && !shaderRef->getChild(child->getName())) { - if (activeValue->isA()) + if (activeValue->getCategory() == "parameter") { BindParamPtr bindParam = shaderRef->addBindParam(activeValue->getName(), activeValue->getType()); bindParam->setValueString(child->getAttribute("value")); @@ -880,24 +880,16 @@ void Document::upgradeVersion(bool applyFutureUpdates) // Convert backdrop nodes to backdrop elements else if (nodeCategory == "backdrop") { - const string& nodeName = node->getName(); - BackdropPtr backdrop = addBackdrop(nodeName); - for (auto param : node->getParameters()) + BackdropPtr backdrop = addBackdrop(node->getName()); + for (ElementPtr child : node->getChildren()) { - ValuePtr value = param ? param->getValue() : nullptr; - if (value) + if (child->getCategory() == "parameter" && + child->hasAttribute(ValueElement::VALUE_ATTRIBUTE)) { - if (value->isA()) - { - backdrop->setAttribute(param->getName(), value->asA()); - } - else if (value->isA()) - { - backdrop->setTypedAttribute(param->getName(), value->asA()); - } + backdrop->setAttribute(child->getName(), child->getAttribute(ValueElement::VALUE_ATTRIBUTE)); } } - removeNode(nodeName); + removeNode(node->getName()); } } diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 70d4464014..58589fd874 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -580,7 +580,7 @@ bool ValueElement::validate(string* message) const } if (hasInterfaceName()) { - validateRequire(isA() || isA(), res, message, "Only parameter and input elements support interface names"); + validateRequire(isA(), res, message, "Only input elements support interface names"); ConstNodeGraphPtr nodeGraph = getAncestorOfType(); NodeDefPtr nodeDef = nodeGraph ? nodeGraph->getNodeDef() : nullptr; if (nodeDef) @@ -780,7 +780,6 @@ INSTANTIATE_CONCRETE_SUBCLASS(Node, "node") INSTANTIATE_CONCRETE_SUBCLASS(NodeDef, "nodedef") INSTANTIATE_CONCRETE_SUBCLASS(NodeGraph, "nodegraph") INSTANTIATE_CONCRETE_SUBCLASS(Output, "output") -INSTANTIATE_CONCRETE_SUBCLASS(Parameter, "parameter") INSTANTIATE_CONCRETE_SUBCLASS(Property, "property") INSTANTIATE_CONCRETE_SUBCLASS(PropertyAssign, "propertyassign") INSTANTIATE_CONCRETE_SUBCLASS(PropertySet, "propertyset") diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index b0725104ff..b52240b597 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -206,97 +206,6 @@ bool PortElement::validChannelsString(const string& channels, const string& sour return true; } -// -// Parameter methods -// - -Edge Parameter::getUpstreamEdge(ConstMaterialPtr material, size_t index) const -{ - if (material && index < getUpstreamEdgeCount()) - { - ConstElementPtr parent = getParent(); - ConstInterfaceElementPtr interface = parent ? parent->asA() : nullptr; - ConstNodeDefPtr nodeDef = interface ? interface->getDeclaration() : nullptr; - if (nodeDef) - { - // Apply BindParam elements to the Parameter. - for (ShaderRefPtr shaderRef : material->getActiveShaderRefs()) - { - if (shaderRef->getNodeDef()->hasInheritedBase(nodeDef)) - { - for (BindParamPtr bindParam : shaderRef->getBindParams()) - { - if (bindParam->getName() == getName() && bindParam->hasValue()) - { - return Edge(getSelfNonConst(), nullptr, bindParam); - } - } - } - } - } - } - - return NULL_EDGE; -} - -OutputPtr Parameter::getConnectedOutput() const -{ - OutputPtr output = OutputPtr(); - - const string& outputString = getAttribute(PortElement::OUTPUT_ATTRIBUTE); - if (!outputString.empty()) - { - const string connectedGraph = getAttribute(PortElement::NODE_GRAPH_ATTRIBUTE); - const string connectedNode = getAttribute(PortElement::NODE_NAME_ATTRIBUTE); - - // Look for an output in a nodegraph - if (!connectedGraph.empty()) - { - NodeGraphPtr nodeGraph = resolveRootNameReference(connectedGraph); - if (nodeGraph) - { - output = nodeGraph->getOutput(outputString); - } - } - // Look for output on a node within a nodegraph - else if (!connectedNode.empty()) - { - ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(connectedNode) : nullptr; - if (node) - { - output = node->getOutput(outputString); - } - } - // Look for a document level output - else - { - output = getDocument()->getOutput(outputString); - } - } - return output; -} - -NodePtr Parameter::getConnectedNode() const -{ - OutputPtr output = getConnectedOutput(); - if (output) - { - return output->getConnectedNode(); - } - const string connectedNode = getAttribute(PortElement::NODE_NAME_ATTRIBUTE); - if (!connectedNode.empty()) - { - ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(connectedNode) : nullptr; - if (node) - { - return node; - } - } - return nullptr; -} - // // Input methods // @@ -473,30 +382,6 @@ bool Output::validate(string* message) const // InterfaceElement methods // -ParameterPtr InterfaceElement::getActiveParameter(const string& name) const -{ - for (ConstElementPtr elem : traverseInheritance()) - { - ParameterPtr param = elem->asA()->getParameter(name); - if (param) - { - return param; - } - } - return nullptr; -} - -vector InterfaceElement::getActiveParameters() const -{ - vector activeParams; - for (ConstElementPtr elem : traverseInheritance()) - { - vector params = elem->asA()->getParameters(); - activeParams.insert(activeParams.end(), params.begin(), params.end()); - } - return activeParams; -} - InputPtr InterfaceElement::getActiveInput(const string& name) const { for (ConstElementPtr elem : traverseInheritance()) @@ -615,28 +500,6 @@ vector InterfaceElement::getActiveValueElements() const return activeValueElems; } -ValuePtr InterfaceElement::getParameterValue(const string& name, const string& target) const -{ - ParameterPtr param = getParameter(name); - if (param) - { - return param->getValue(); - } - - // Return the value, if any, stored in our declaration. - ConstNodeDefPtr decl = getDeclaration(target); - if (decl) - { - param = decl->getParameter(name); - if (param) - { - return param->getValue(); - } - } - - return ValuePtr(); -} - ValuePtr InterfaceElement::getInputValue(const string& name, const string& target) const { InputPtr input = getInput(name); @@ -662,11 +525,7 @@ ValuePtr InterfaceElement::getInputValue(const string& name, const string& targe void InterfaceElement::registerChildElement(ElementPtr child) { TypedElement::registerChildElement(child); - if (child->isA()) - { - _parameterCount++; - } - else if (child->isA()) + if (child->isA()) { _inputCount++; } @@ -679,11 +538,7 @@ void InterfaceElement::registerChildElement(ElementPtr child) void InterfaceElement::unregisterChildElement(ElementPtr child) { TypedElement::unregisterChildElement(child); - if (child->isA()) - { - _parameterCount--; - } - else if (child->isA()) + if (child->isA()) { _inputCount--; } diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index c9ae9ef259..a8694fc8cd 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -16,7 +16,6 @@ namespace MaterialX { -class Parameter; class PortElement; class Input; class Output; @@ -24,11 +23,6 @@ class InterfaceElement; class Node; class NodeDef; -/// A shared pointer to a Parameter -using ParameterPtr = shared_ptr; -/// A shared pointer to a const Parameter -using ConstParameterPtr = shared_ptr; - /// A shared pointer to a PortElement using PortElementPtr = shared_ptr; /// A shared pointer to a const PortElement @@ -51,50 +45,6 @@ using ConstInterfaceElementPtr = shared_ptr; using CharSet = std::set; -/// @class Parameter -/// A parameter element within a Node or NodeDef. -/// -/// A Parameter holds a single uniform value, which may be modified within the -/// scope of a Material. -class Parameter : public ValueElement -{ - public: - Parameter(ElementPtr parent, const string& name) : - ValueElement(parent, CATEGORY, name) - { - } - virtual ~Parameter() { } - - protected: - using NodePtr = shared_ptr; - - public: - /// @name Traversal - /// @{ - - /// Return the Edge with the given index that lies directly upstream from - /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; - - /// Return the number of queriable upstream edges for this element. - size_t getUpstreamEdgeCount() const override - { - return 1; - } - - /// Return the output, if any, to which this element is connected. - OutputPtr getConnectedOutput() const; - - /// Return the node, if any, to which this element is connected. - NodePtr getConnectedNode() const; - - /// @} - - public: - static const string CATEGORY; -}; - /// @class PortElement /// The base class for port elements such as Input and Output. /// @@ -379,7 +329,6 @@ class InterfaceElement : public TypedElement protected: InterfaceElement(ElementPtr parent, const string& category, const string& name) : TypedElement(parent, category, name), - _parameterCount(0), _inputCount(0), _outputCount(0) { @@ -413,56 +362,6 @@ class InterfaceElement : public TypedElement return getAttribute(NODE_DEF_ATTRIBUTE); } - /// @} - /// @name Parameters - /// @{ - - /// Add a Parameter to this interface. - /// @param name The name of the new Parameter. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @param type An optional type string. - /// @return A shared pointer to the new Parameter. - ParameterPtr addParameter(const string& name = DEFAULT_TYPE_STRING, - const string& type = DEFAULT_TYPE_STRING) - { - ParameterPtr child = addChild(name); - child->setType(type); - return child; - } - - /// Return the Parameter, if any, with the given name. - ParameterPtr getParameter(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all Parameter elements. - vector getParameters() const - { - return getChildrenOfType(); - } - - /// Return the number of Parameter elements. - size_t getParameterCount() const - { - return _parameterCount; - } - - /// Remove the Parameter, if any, with the given name. - void removeParameter(const string& name) - { - removeChildOfType(name); - } - - /// Return the first Parameter with the given name that belongs to this - /// interface, taking interface inheritance into account. - ParameterPtr getActiveParameter(const string& name) const; - - /// Return a vector of all Parameter elements that belong to this interface, - /// taking interface inheritance into account. - vector getActiveParameters() const; - /// @} /// @name Inputs /// @{ @@ -636,22 +535,6 @@ class InterfaceElement : public TypedElement /// @name Values /// @{ - /// Set the typed value of a parameter by its name, creating a child element - /// to hold the parameter if needed. - template ParameterPtr setParameterValue(const string& name, - const T& value, - const string& type = EMPTY_STRING); - - /// Return the typed value of a parameter by its name, taking both the - /// calling element and its declaration into account. - /// @param name The name of the parameter to be evaluated. - /// @param target An optional target name, which will be used to filter - /// the declarations that are considered. - /// @return If the given parameter is found in this interface or its - /// declaration, then a shared pointer to its value is returned; - /// otherwise, an empty shared pointer is returned. - ValuePtr getParameterValue(const string& name, const string& target = EMPTY_STRING) const; - /// Set the typed value of an input by its name, creating a child element /// to hold the input if needed. template InputPtr setInputValue(const string& name, @@ -719,22 +602,10 @@ class InterfaceElement : public TypedElement void unregisterChildElement(ElementPtr child) override; private: - size_t _parameterCount; size_t _inputCount; size_t _outputCount; }; -template ParameterPtr InterfaceElement::setParameterValue(const string& name, - const T& value, - const string& type) -{ - ParameterPtr param = getChildOfType(name); - if (!param) - param = addParameter(name); - param->setValue(value, type); - return param; -} - template InputPtr InterfaceElement::setInputValue(const string& name, const T& value, const string& type) diff --git a/source/MaterialXCore/Material.cpp b/source/MaterialXCore/Material.cpp index 5da0beb05a..ac0dfe841f 100644 --- a/source/MaterialXCore/Material.cpp +++ b/source/MaterialXCore/Material.cpp @@ -128,28 +128,6 @@ bool Material::validate(string* message) const return Element::validate(message) && res; } -// -// BindParam methods -// - -bool BindParam::validate(string* message) const -{ - bool res = true; - ConstElementPtr parent = getParent(); - ConstShaderRefPtr shaderRef = parent ? parent->asA() : nullptr; - NodeDefPtr nodeDef = shaderRef ? shaderRef->getNodeDef() : nullptr; - if (nodeDef) - { - ParameterPtr param = nodeDef->getActiveParameter(getName()); - validateRequire(param != nullptr, res, message, "BindParam does not match a Parameter in the referenced NodeDef"); - if (param) - { - validateRequire(getType() == param->getType(), res, message, "Type mismatch between BindParam and Parameter"); - } - } - return ValueElement::validate(message) && res; -} - // // BindInput methods // diff --git a/source/MaterialXCore/Material.h b/source/MaterialXCore/Material.h index e389e572fd..0d1d6b715d 100644 --- a/source/MaterialXCore/Material.h +++ b/source/MaterialXCore/Material.h @@ -216,15 +216,6 @@ class BindParam : public ValueElement } virtual ~BindParam() { } - /// @name Validation - /// @{ - - /// Validate that the given element tree, including all descendants, is - /// consistent with the MaterialX specification. - bool validate(string* message = nullptr) const override; - - /// @} - public: static const string CATEGORY; }; diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index d44ff80245..234b78c2b2 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -590,8 +590,7 @@ ValueElementPtr NodeGraph::getChildWithInterface(const string& childPath) ElementPtr elem = getDescendant(childPath); ValueElementPtr valueElem = elem->asA(); InputPtr input = valueElem ? valueElem->asA() : nullptr; - ParameterPtr param = valueElem ? valueElem->asA() : nullptr; - if (!input && !param) + if (!input) { throw Exception("Child not found in node graph: " + childPath); } diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index 5360800519..cae6fee253 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -324,16 +324,16 @@ class NodeGraph : public GraphElement ConstNodeDefPtr getDeclaration(const string& target = EMPTY_STRING) const override; /// Add a new interface to an existing NodeDef associated with this NodeGraph. - /// @param inputPath Path to Input or Parameter to declare as an interface. + /// @param inputPath Path to Input to declare as an interface. /// @param interfaceName Name of interface. void addInterface(const string& inputPath, const string& interfaceName); /// Remove an interface from an existing NodeDef associated with this NodeGraph. - /// @param inputPath Path to Input or Parameter to remove interface from. + /// @param inputPath Path to Input to remove interface from. void removeInterface(const string& inputPath); /// Rename an interface on an existing NodeDef associated with this NodeGraph. - /// @param inputPath Path to Input or Parameter to reinterface. + /// @param inputPath Path to Input to reinterface. /// @param interfaceName Name of interface. void renameInterface(const string& inputPath, const string& interfaceName); diff --git a/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp index a0e428822f..cbef1fee4f 100644 --- a/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp @@ -30,17 +30,13 @@ void LightCompoundNodeGlsl::initialize(const InterfaceElement& element, GenConte { CompoundNode::initialize(element, context); - // Store light uniforms for all inputs and parameters on the interface + // Store light uniforms for all inputs on the interface const NodeGraph& graph = static_cast(element); NodeDefPtr nodeDef = graph.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { _lightUniforms.add(TypeDesc::get(input->getType()), input->getName()); } - for (ParameterPtr param : nodeDef->getActiveParameters()) - { - _lightUniforms.add(TypeDesc::get(param->getType()), param->getName()); - } } void LightCompoundNodeGlsl::createVariables(const ShaderNode&, GenContext& context, Shader& shader) const diff --git a/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp index 33c4eec128..99a158492a 100644 --- a/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp @@ -41,16 +41,12 @@ void LightShaderNodeGlsl::initialize(const InterfaceElement& element, GenContext const Implementation& impl = static_cast(element); - // Store light uniforms for all inputs and parameters on the interface + // Store light uniforms for all inputs on the interface NodeDefPtr nodeDef = impl.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { _lightUniforms.add(TypeDesc::get(input->getType()), input->getName(), input->getValue()); } - for (ParameterPtr param : nodeDef->getActiveParameters()) - { - _lightUniforms.add(TypeDesc::get(param->getType()), param->getName(), param->getValue()); - } } void LightShaderNodeGlsl::createVariables(const ShaderNode&, GenContext& context, Shader& shader) const diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index fc68d9b76f..8f48cfb6d4 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -593,21 +593,6 @@ ShaderGraphPtr ShaderGraph::createSurfaceShader( inputSocket->setUnit(unit); } } - for (const ParameterPtr& nodeParameter : nodeDef->getActiveParameters()) - { - const string& paramName = nodeParameter->getName(); - const string path = nodePath + NAME_PATH_SEPARATOR + paramName; - ShaderInput* input = newNode->getInput(paramName); - if (input && input->getPath().empty()) - { - input->setPath(path); - } - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(paramName); - if (inputSocket && inputSocket->getPath().empty()) - { - inputSocket->setPath(path); - } - } // Start traversal from this shader node root = node; @@ -771,192 +756,6 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name } } - else if (element->isA()) - { - ShaderRefPtr shaderRef = element->asA(); - NodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (!nodeDef) - { - throw ExceptionShaderGenError("Could not find a nodedef for shader '" + shaderRef->getName() + "'"); - } - - graph = std::make_shared(parent, name, element->getDocument(), context.getReservedWords()); - - // Create input sockets - graph->addInputSockets(*nodeDef, context); - - // Create output sockets - graph->addOutputSockets(*nodeDef); - - // Create this shader node in the graph. - const string& newNodeName = shaderRef->getName(); - ShaderNodePtr newNode = ShaderNode::create(graph.get(), newNodeName, *nodeDef, context); - graph->addNode(newNode); - - // Connect it to the graph output - ShaderGraphOutputSocket* outputSocket = graph->getOutputSocket(); - outputSocket->makeConnection(newNode->getOutput()); - outputSocket->setPath(shaderRef->getNamePath()); - - // Share metadata. - graph->setMetadata(newNode->getMetadata()); - - string targetColorSpace; - ColorManagementSystemPtr colorManagementSystem = context.getShaderGenerator().getColorManagementSystem(); - if (colorManagementSystem) - { - targetColorSpace = context.getOptions().targetColorSpaceOverride.empty() ? - element->getDocument()->getColorSpace() : context.getOptions().targetColorSpaceOverride; - } - - // Handle node parameters - const string& targetDistanceUnit = context.getOptions().targetDistanceUnit; - UnitSystemPtr unitSystem = context.getShaderGenerator().getUnitSystem(); - for (ParameterPtr elem : nodeDef->getActiveParameters()) - { - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(elem->getName()); - ShaderInput* input = newNode->getInput(elem->getName()); - if (!inputSocket || !input) - { - throw ExceptionShaderGenError("Shader parameter '" + elem->getName() + "' doesn't match an existing input on graph '" + graph->getName() + "'"); - } - - BindParamPtr bindParam = shaderRef->getBindParam(elem->getName()); - if (bindParam) - { - // Copy value from binding - ValuePtr bindParamValue = bindParam->getResolvedValue(); - if (bindParamValue) - { - inputSocket->setValue(bindParamValue); - - input->setBindInput(); - graph->populateColorTransformMap(colorManagementSystem, input, bindParam, targetColorSpace, true); - graph->populateUnitTransformMap(unitSystem, input, bindParam, targetDistanceUnit, true); - } - inputSocket->setPath(bindParam->getNamePath()); - input->setPath(inputSocket->getPath()); - const string& bindParamUnit = bindParam->getUnit(); - if (!bindParamUnit.empty()) - { - inputSocket->setUnit(bindParamUnit); - input->setUnit(bindParamUnit); - } - } - - // Connect to the graph input - inputSocket->makeConnection(input); - - // Share metadata. - inputSocket->setMetadata(input->getMetadata()); - } - - // Handle node inputs - for (const InputPtr& nodeDefInput : nodeDef->getActiveInputs()) - { - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(nodeDefInput->getName()); - ShaderInput* input = newNode->getInput(nodeDefInput->getName()); - if (!inputSocket || !input) - { - throw ExceptionShaderGenError("Shader input '" + nodeDefInput->getName() + "' doesn't match an existing input on graph '" + graph->getName() + "'"); - } - - BindInputPtr bindInput = shaderRef->getBindInput(nodeDefInput->getName()); - if (bindInput) - { - // Copy value from binding - ValuePtr bindInputValue = bindInput->getResolvedValue(); - if (bindInputValue) - { - inputSocket->setValue(bindInputValue); - - input->setBindInput(); - graph->populateColorTransformMap(colorManagementSystem, input, bindInput, targetColorSpace, true); - graph->populateUnitTransformMap(unitSystem, input, bindInput, targetDistanceUnit, true); - } - inputSocket->setPath(bindInput->getNamePath()); - input->setPath(inputSocket->getPath()); - const string& bindInputUnit = bindInput->getUnit(); - if (!bindInputUnit.empty()) - { - inputSocket->setUnit(bindInputUnit); - input->setUnit(bindInputUnit); - } - } - - GeomPropDefPtr geomprop = nodeDefInput->getDefaultGeomProp(); - if (geomprop) - { - inputSocket->setGeomProp(geomprop->getName()); - input->setGeomProp(geomprop->getName()); - } - - // If no explicit connection, connect to geometric node if a geomprop is used - // or otherwise to the graph interface. - const string& connection = bindInput ? bindInput->getOutputString() : EMPTY_STRING; - if (connection.empty()) - { - if (geomprop) - { - graph->addDefaultGeomNode(input, *geomprop, context); - } - else - { - inputSocket->makeConnection(input); - } - } - - // Share metadata. - inputSocket->setMetadata(input->getMetadata()); - } - - // Add shaderRef nodedef paths - const string& nodePath = shaderRef->getNamePath(); - for (auto nodeInput : nodeDef->getActiveInputs()) - { - const string& inputName = nodeInput->getName(); - const string path = nodePath + NAME_PATH_SEPARATOR + inputName; - const string& unit = nodeInput->getUnit(); - ShaderInput* input = newNode->getInput(inputName); - if (input && input->getPath().empty()) - { - input->setPath(path); - } - if (input && input->getUnit().empty() && !unit.empty()) - { - input->setUnit(unit); - } - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(inputName); - if (inputSocket && inputSocket->getPath().empty()) - { - inputSocket->setPath(path); - } - if (inputSocket && inputSocket->getUnit().empty() && !unit.empty()) - { - inputSocket->setUnit(unit); - } - } - for (const ParameterPtr& nodeParameter : nodeDef->getActiveParameters()) - { - const string& paramName = nodeParameter->getName(); - const string path = nodePath + NAME_PATH_SEPARATOR + paramName; - ShaderInput* input = newNode->getInput(paramName); - if (input && input->getPath().empty()) - { - input->setPath(path); - } - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(paramName); - if (inputSocket && inputSocket->getPath().empty()) - { - inputSocket->setPath(path); - } - } - - // Start traversal from this shaderref and material - root = shaderRef; - material = shaderRef->getParent()->asA(); - } - if (!graph) { throw ExceptionShaderGenError("Shader generation from element '" + element->getName() + "' of type '" + element->getCategory() + "' is not supported"); diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 94c3d35709..52917c2396 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -419,14 +419,6 @@ void ShaderNode::initialize(const Node& node, const NodeDef& nodeDef, GenContext input->setPath(nodePath + NAME_PATH_SEPARATOR + nodeInput->getName()); } } - for (auto nodeParameter : nodeDef.getActiveParameters()) - { - ShaderInput* input = getInput(nodeParameter->getName()); - if (input && input->getPath().empty()) - { - input->setPath(nodePath + NAME_PATH_SEPARATOR + nodeParameter->getName()); - } - } } void ShaderNode::createMetadata(const NodeDef& nodeDef, GenContext& context) diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index 80e49f5f72..6d265c02b0 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -125,7 +125,6 @@ void bindPyElement(py::module& mod) BIND_ELEMENT_FUNC_INSTANCE(Node) BIND_ELEMENT_FUNC_INSTANCE(NodeDef) BIND_ELEMENT_FUNC_INSTANCE(NodeGraph) - BIND_ELEMENT_FUNC_INSTANCE(Parameter) BIND_ELEMENT_FUNC_INSTANCE(Property) BIND_ELEMENT_FUNC_INSTANCE(PropertySet) BIND_ELEMENT_FUNC_INSTANCE(PropertySetAssign) diff --git a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp index 21dbd7e2a2..cd9d76040c 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp @@ -13,14 +13,10 @@ namespace py = pybind11; namespace mx = MaterialX; #define BIND_INTERFACE_TYPE_INSTANCE(NAME, T) \ -.def("_setParameterValue" #NAME, &mx::InterfaceElement::setParameterValue, py::arg("name"), py::arg("value"), py::arg("type") = mx::EMPTY_STRING) \ .def("_setInputValue" #NAME, &mx::InterfaceElement::setInputValue, py::arg("name"), py::arg("value"), py::arg("type") = mx::EMPTY_STRING) void bindPyInterface(py::module& mod) { - py::class_(mod, "Parameter") - .def_readonly_static("CATEGORY", &mx::Parameter::CATEGORY); - py::class_(mod, "PortElement") .def("setNodeName", &mx::PortElement::setNodeName) .def("getNodeName", &mx::PortElement::getNodeName) @@ -53,14 +49,6 @@ void bindPyInterface(py::module& mod) .def("setNodeDefString", &mx::InterfaceElement::setNodeDefString) .def("hasNodeDefString", &mx::InterfaceElement::hasNodeDefString) .def("getNodeDefString", &mx::InterfaceElement::getNodeDefString) - .def("addParameter", &mx::InterfaceElement::addParameter, - py::arg("name") = mx::EMPTY_STRING, py::arg("type") = mx::DEFAULT_TYPE_STRING) - .def("getParameter", &mx::InterfaceElement::getParameter) - .def("getParameters", &mx::InterfaceElement::getParameters) - .def("getParameterCount", &mx::InterfaceElement::getParameterCount) - .def("removeParameter", &mx::InterfaceElement::removeParameter) - .def("getActiveParameter", &mx::InterfaceElement::getActiveParameter) - .def("getActiveParameters", &mx::InterfaceElement::getActiveParameters) .def("addInput", &mx::InterfaceElement::addInput, py::arg("name") = mx::EMPTY_STRING, py::arg("type") = mx::DEFAULT_TYPE_STRING, py::arg("isUniform") = false) @@ -87,7 +75,6 @@ void bindPyInterface(py::module& mod) .def("getActiveTokens", &mx::InterfaceElement::getActiveTokens) .def("getActiveValueElement", &mx::InterfaceElement::getActiveValueElement) .def("getActiveValueElements", &mx::InterfaceElement::getActiveValueElements) - .def("_getParameterValue", &mx::InterfaceElement::getParameterValue) .def("_getInputValue", &mx::InterfaceElement::getInputValue) .def("setTokenValue", &mx::InterfaceElement::setTokenValue) .def("getTokenValue", &mx::InterfaceElement::getTokenValue) From 6b68b55a40dbe0f9bc558be0020575a21f00b8fb Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Fri, 27 Nov 2020 11:27:22 -0800 Subject: [PATCH 12/35] Remove ShaderRef classes --- python/MaterialX/main.py | 29 -- python/MaterialXTest/main.py | 70 +-- source/MaterialXCore/Definition.cpp | 16 - source/MaterialXCore/Definition.h | 12 +- source/MaterialXCore/Document.cpp | 93 ++-- source/MaterialXCore/Element.cpp | 73 +-- source/MaterialXCore/Element.h | 63 +-- source/MaterialXCore/Interface.cpp | 38 -- source/MaterialXCore/Interface.h | 11 - source/MaterialXCore/Material.cpp | 200 +-------- source/MaterialXCore/Material.h | 417 ------------------ source/MaterialXCore/Node.cpp | 25 -- source/MaterialXCore/Node.h | 2 +- source/MaterialXGenShader/ShaderGraph.cpp | 65 +-- source/MaterialXGenShader/ShaderGraph.h | 4 +- source/MaterialXGenShader/Util.cpp | 215 +-------- source/MaterialXGenShader/Util.h | 10 - .../MaterialXTest/MaterialXCore/Document.cpp | 20 - source/MaterialXTest/MaterialXCore/Look.cpp | 1 - .../MaterialXTest/MaterialXCore/Material.cpp | 76 ---- .../MaterialXTest/MaterialXFormat/XmlIo.cpp | 17 - .../MaterialXGenShader/GenShaderUtil.cpp | 5 - .../MaterialXRender/RenderUtil.cpp | 10 - source/MaterialXView/Viewer.cpp | 77 +--- .../PyMaterialXCore/PyDefinition.cpp | 3 +- .../PyMaterialX/PyMaterialXCore/PyElement.cpp | 7 +- .../PyMaterialXCore/PyMaterial.cpp | 48 -- 27 files changed, 89 insertions(+), 1518 deletions(-) diff --git a/python/MaterialX/main.py b/python/MaterialX/main.py index 792e18c04f..b52022b20d 100644 --- a/python/MaterialX/main.py +++ b/python/MaterialX/main.py @@ -172,37 +172,8 @@ def _setOverrideValue(self, name, value, typeString = ''): method = getattr(self.__class__, "_setOverrideValue" + getTypeString(value)) return method(self, name, value, typeString) -def _addShaderRef(self, name = '', node = ''): - "Add a shader ref to the material." - return self._addShaderRef(name, node) - -def _getReferencedShaderDefs(self): - "(Deprecated) Return a list of all shader nodedefs referenced by this material." - warnings.warn("This function is deprecated; call Material.getShaderNodeDefs instead.", DeprecationWarning, stacklevel = 2) - return self.getShaderNodeDefs() - -def _getReferencingMaterialAssigns(self): - "(Deprecated) Return a list of all material assigns that reference this material." - warnings.warn("This function is deprecated; call Material.getGeometryBindings instead.", DeprecationWarning, stacklevel = 2) - return self.getGeometryBindings() - Material.addOverride = _addOverride Material.setOverrideValue = _setOverrideValue -Material.addShaderRef = _addShaderRef -Material.getReferencedShaderDefs = _getReferencedShaderDefs -Material.getReferencingMaterialAssigns = _getReferencingMaterialAssigns - - -# -# ShaderRef -# - -def _getReferencedShaderDef(self): - "(Deprecated) Return the NodeDef that this element references." - warnings.warn("This function is deprecated; call ShaderRef.getNodeDef instead.", DeprecationWarning, stacklevel = 2) - return self.getNodeDef() - -ShaderRef.getReferencedShaderDef = _getReferencedShaderDef # diff --git a/python/MaterialXTest/main.py b/python/MaterialXTest/main.py index 7f39afe412..9b7943f55f 100644 --- a/python/MaterialXTest/main.py +++ b/python/MaterialXTest/main.py @@ -242,66 +242,10 @@ def test_BuildDocument(self): roughness.setIsUniform(True); self.assertTrue(roughness.getIsUniform() == True) - # Create a material that instantiates the shader. - material = doc.addMaterial() - shaderRef = material.addShaderRef('shaderRef1', 'simpleSrf') - self.assertTrue(material.getPrimaryShaderName() == 'simpleSrf') - self.assertTrue(len(material.getPrimaryShaderInputs()) == 3) - self.assertTrue(len(material.getPrimaryShaderTokens()) == 1) - self.assertTrue(roughness.getBoundValue(material) == 0.25) - - # Bind a shader input to a float value. - bindInput = shaderRef.addBindInput('roughness') - bindInput.setValue(0.5) - self.assertTrue(roughness.getBoundValue(material) == 0.5) - self.assertTrue(roughness.getDefaultValue() == 0.25) - - # Bind a shader input to a value. - bindInput = shaderRef.addBindInput('specColor') - bindInput.setValue(mx.Color3(0.5)) - self.assertTrue(specColor.getBoundValue(material) == mx.Color3(0.5)) - self.assertTrue(specColor.getDefaultValue() == mx.Color3(0.0)) - - # Bind a shader input to a graph output. - bindInput = shaderRef.addBindInput('diffColor') - bindInput.setConnectedOutput(output2) - self.assertTrue(diffColor.getUpstreamElement(material) == output2) - self.assertTrue(diffColor.getBoundValue(material) is None) - self.assertTrue(diffColor.getDefaultValue() == mx.Color3(1.0)) - - # Bind a shader token to a value. - bindToken = shaderRef.addBindToken('texId') - bindToken.setValue('02') - self.assertTrue(texId.getBoundValue(material) == '02') - self.assertTrue(texId.getDefaultValue() == '01') - - # Create an inherited material. - material2 = doc.addMaterial() - material2.setInheritsFrom(material) - self.assertTrue(roughness.getBoundValue(material2) == 0.5) - self.assertTrue(diffColor.getUpstreamElement(material2) == output2) - - # Create a look for the material. + # Create a look. look = doc.addLook() self.assertTrue(len(doc.getLooks()) == 1) - # Bind the material to a geometry string. - matAssign1 = look.addMaterialAssign("matAssign1", material.getName()) - matAssign1.setGeom("/robot1") - self.assertTrue(matAssign1.getReferencedMaterial() == material) - self.assertTrue(len(material.getGeometryBindings("/robot1")) == 1) - self.assertTrue(len(material.getGeometryBindings("/robot2")) == 0) - - # Bind the material to a collection. - matAssign2 = look.addMaterialAssign("matAssign2", material.getName()) - collection = doc.addCollection() - collection.setIncludeGeom("/robot2") - collection.setExcludeGeom("/robot2/left_arm") - matAssign2.setCollection(collection) - self.assertTrue(len(material.getGeometryBindings("/robot2")) == 1) - self.assertTrue(len(material.getGeometryBindings("/robot2/right_arm")) == 1) - self.assertTrue(len(material.getGeometryBindings("/robot2/left_arm")) == 0) - # Create a property assignment. propertyAssign = look.addPropertyAssign() propertyAssign.setProperty("twosided") @@ -482,18 +426,6 @@ def test_ReadXml(self): valueElementCount += 1 self.assertTrue(valueElementCount > 0) - # Traverse upstream from each shader input. - for material in doc.getMaterials(): - self.assertTrue(material.getPrimaryShaderNodeDef()) - edgeCount = 0 - for shaderInput in material.getPrimaryShaderInputs(): - boundValue = shaderInput.getBoundValue(material) - upstreamElement = shaderInput.getUpstreamElement(material) - self.assertTrue(boundValue is not None or upstreamElement is not None) - for _ in shaderInput.traverseGraph(material): - edgeCount += 1 - self.assertTrue(edgeCount > 0) - # Serialize to XML. writeOptions = mx.XmlWriteOptions() writeOptions.writeXIncludeEnable = False diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp index d56a984668..3fa4183466 100644 --- a/source/MaterialXCore/Definition.cpp +++ b/source/MaterialXCore/Definition.cpp @@ -117,22 +117,6 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const return InterfaceElementPtr(); } -vector NodeDef::getInstantiatingShaderRefs() const -{ - vector shaderRefs; - for (MaterialPtr mat : getDocument()->getMaterials()) - { - for (ShaderRefPtr shaderRef : mat->getShaderRefs()) - { - if (shaderRef->getNodeDef()->hasInheritedBase(getSelf())) - { - shaderRefs.push_back(shaderRef); - } - } - } - return shaderRefs; -} - bool NodeDef::validate(string* message) const { bool res = true; diff --git a/source/MaterialXCore/Definition.h b/source/MaterialXCore/Definition.h index c963ba5457..dd2667456c 100644 --- a/source/MaterialXCore/Definition.h +++ b/source/MaterialXCore/Definition.h @@ -24,7 +24,6 @@ class Implementation; class TypeDef; class TargetDef; class Member; -class ShaderRef; class Unit; class UnitDef; class UnitTypeDef; @@ -79,7 +78,7 @@ using AttributeDefDefPtr = shared_ptr; /// A node definition element within a Document. /// /// A NodeDef provides the declaration of a node interface, which may then -/// be instantiated as a Node or a ShaderRef. +/// be instantiated as a Node. class NodeDef : public InterfaceElement { public: @@ -89,8 +88,6 @@ class NodeDef : public InterfaceElement } virtual ~NodeDef() { } - using ShaderRefPtr = shared_ptr; - /// @name Node String /// @{ @@ -150,13 +147,6 @@ class NodeDef : public InterfaceElement /// an Implementation element or a NodeGraph element. InterfaceElementPtr getImplementation(const string& target = EMPTY_STRING) const; - /// @} - /// @name Shader References - /// @{ - - /// Return all ShaderRef elements that instantiate this NodeDef. - vector getInstantiatingShaderRefs() const; - /// @} /// @name Validation /// @{ diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index e4bd4fa34c..e87392127a 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -536,15 +536,15 @@ void Document::upgradeVersion(bool applyFutureUpdates) // Assign nodedef names to shaderrefs. for (MaterialPtr mat : getMaterials()) { - for (ShaderRefPtr shaderRef : mat->getShaderRefs()) + for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) { - if (!shaderRef->getNodeDef()) + if (!getShaderNodeDef(shaderRef)) { NodeDefPtr nodeDef = getNodeDef(shaderRef->getName()); if (nodeDef) { - shaderRef->setNodeDefString(nodeDef->getName()); - shaderRef->setNodeString(nodeDef->getNodeString()); + shaderRef->setAttribute(NodeDef::NODE_DEF_ATTRIBUTE, nodeDef->getName()); + shaderRef->setAttribute(NodeDef::NODE_ATTRIBUTE, nodeDef->getNodeString()); } } } @@ -559,13 +559,14 @@ void Document::upgradeVersion(bool applyFutureUpdates) { for (MaterialPtr mat : getMaterials()) { - for (ShaderRefPtr shaderRef : mat->getShaderRefs()) + for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) { - if (shaderRef->getNodeDef() == nodeDef && !shaderRef->getChild(input->getName())) + if (getShaderNodeDef(shaderRef) == nodeDef && !shaderRef->getChild(input->getName())) { - BindInputPtr bind = shaderRef->addBindInput(input->getName(), input->getType()); - bind->setNodeGraphString(input->getAttribute("opgraph")); - bind->setOutputString(input->getAttribute("graphoutput")); + ElementPtr bindInput = shaderRef->addChildOfCategory("bindinput", input->getName()); + bindInput->setAttribute(TypedElement::TYPE_ATTRIBUTE, input->getType()); + bindInput->setAttribute("nodegraph", input->getAttribute("opgraph")); + bindInput->setAttribute("output", input->getAttribute("graphoutput")); } } } @@ -578,13 +579,9 @@ void Document::upgradeVersion(bool applyFutureUpdates) // Combine udim assignments into udim sets. for (GeomInfoPtr geomInfo : getGeomInfos()) { - vector origChildren = geomInfo->getChildren(); - for (ElementPtr child : origChildren) + for (ElementPtr child : geomInfo->getChildrenOfType("geomattr")) { - if (child->getCategory() == "geomattr") - { - changeChildCategory(geomInfo, child, GeomProp::CATEGORY); - } + changeChildCategory(geomInfo, child, GeomProp::CATEGORY); } } if (getGeomPropValue("udim") && !getGeomPropValue("udimset")) @@ -626,18 +623,17 @@ void Document::upgradeVersion(bool applyFutureUpdates) { for (ElementPtr elem : traverseTree()) { - TypedElementPtr typedElem = elem->asA(); - ValueElementPtr valueElem = elem->asA(); - MaterialAssignPtr matAssign = elem->asA(); - if (typedElem && typedElem->getType() == "matrix") + if (elem->getAttribute(TypedElement::TYPE_ATTRIBUTE) == "matrix") { - typedElem->setType(getTypeString()); + elem->setAttribute(TypedElement::TYPE_ATTRIBUTE, getTypeString()); } - if (valueElem && valueElem->hasAttribute("default")) + if (elem->hasAttribute("default") && !elem->hasAttribute(ValueElement::VALUE_ATTRIBUTE)) { - valueElem->setValueString(elem->getAttribute("default")); - valueElem->removeAttribute("default"); + elem->setAttribute(ValueElement::VALUE_ATTRIBUTE, elem->getAttribute("default")); + elem->removeAttribute("default"); } + + MaterialAssignPtr matAssign = elem->asA(); if (matAssign) { matAssign->setMaterial(matAssign->getName()); @@ -651,25 +647,21 @@ void Document::upgradeVersion(bool applyFutureUpdates) { for (ElementPtr elem : traverseTree()) { - ValueElementPtr valueElem = elem->asA(); MaterialPtr material = elem->asA(); LookPtr look = elem->asA(); GeomInfoPtr geomInfo = elem->asA(); - if (valueElem) + if (elem->getAttribute(TypedElement::TYPE_ATTRIBUTE) == GEOMNAME_TYPE_STRING && + elem->getAttribute(ValueElement::VALUE_ATTRIBUTE) == "*") { - if (valueElem->getType() == GEOMNAME_TYPE_STRING && - valueElem->getValueString() == "*") - { - valueElem->setValueString(UNIVERSAL_GEOM_NAME); - } - if (valueElem->getType() == FILENAME_TYPE_STRING) - { - StringMap stringMap; - stringMap["%UDIM"] = UDIM_TOKEN; - stringMap["%UVTILE"] = UV_TILE_TOKEN; - valueElem->setValueString(replaceSubstrings(valueElem->getValueString(), stringMap)); - } + elem->setAttribute(ValueElement::VALUE_ATTRIBUTE, UNIVERSAL_GEOM_NAME); + } + if (elem->getAttribute(TypedElement::TYPE_ATTRIBUTE) == FILENAME_TYPE_STRING) + { + StringMap stringMap; + stringMap["%UDIM"] = UDIM_TOKEN; + stringMap["%UVTILE"] = UV_TILE_TOKEN; + elem->setAttribute(ValueElement::VALUE_ATTRIBUTE, replaceSubstrings(elem->getAttribute(ValueElement::VALUE_ATTRIBUTE), stringMap)); } vector origChildren = elem->getChildren(); @@ -677,9 +669,9 @@ void Document::upgradeVersion(bool applyFutureUpdates) { if (material && child->getCategory() == "override") { - for (ShaderRefPtr shaderRef : material->getShaderRefs()) + for (ElementPtr shaderRef : material->getChildrenOfType("shaderref")) { - NodeDefPtr nodeDef = shaderRef->getNodeDef(); + NodeDefPtr nodeDef = getShaderNodeDef(shaderRef); if (nodeDef) { for (ValueElementPtr activeValue : nodeDef->getActiveValueElements()) @@ -689,13 +681,15 @@ void Document::upgradeVersion(bool applyFutureUpdates) { if (activeValue->getCategory() == "parameter") { - BindParamPtr bindParam = shaderRef->addBindParam(activeValue->getName(), activeValue->getType()); - bindParam->setValueString(child->getAttribute("value")); + ElementPtr bindParam = shaderRef->addChildOfCategory("bindparam", activeValue->getName()); + bindParam->setAttribute(TypedElement::TYPE_ATTRIBUTE, activeValue->getType()); + bindParam->setAttribute(ValueElement::VALUE_ATTRIBUTE, child->getAttribute("value")); } else if (activeValue->isA()) { - BindInputPtr bindInput = shaderRef->addBindInput(activeValue->getName(), activeValue->getType()); - bindInput->setValueString(child->getAttribute("value")); + ElementPtr bindInput = shaderRef->addChildOfCategory("bindinput", activeValue->getName()); + bindInput->setAttribute(TypedElement::TYPE_ATTRIBUTE, activeValue->getType()); + bindInput->setAttribute(ValueElement::VALUE_ATTRIBUTE, child->getAttribute("value")); } } } @@ -751,13 +745,9 @@ void Document::upgradeVersion(bool applyFutureUpdates) // Convert geometric attributes to geometric properties. for (GeomInfoPtr geomInfo : getGeomInfos()) { - vector origChildren = geomInfo->getChildren(); - for (ElementPtr child : origChildren) + for (ElementPtr child : geomInfo->getChildrenOfType("geomattr")) { - if (child->getCategory() == "geomattr") - { - changeChildCategory(geomInfo, child, GeomProp::CATEGORY); - } + changeChildCategory(geomInfo, child, GeomProp::CATEGORY); } } for (ElementPtr elem : traverseTree()) @@ -881,10 +871,9 @@ void Document::upgradeVersion(bool applyFutureUpdates) else if (nodeCategory == "backdrop") { BackdropPtr backdrop = addBackdrop(node->getName()); - for (ElementPtr child : node->getChildren()) + for (ElementPtr child : node->getChildrenOfType("parameter")) { - if (child->getCategory() == "parameter" && - child->hasAttribute(ValueElement::VALUE_ATTRIBUTE)) + if (child->hasAttribute(ValueElement::VALUE_ATTRIBUTE)) { backdrop->setAttribute(child->getName(), child->getAttribute(ValueElement::VALUE_ATTRIBUTE)); } diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 58589fd874..f5feff16b7 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -414,10 +414,7 @@ bool Element::validate(string* message) const return res; } -StringResolverPtr Element::createStringResolver(const string& geom, - ConstMaterialPtr material, - const string& target, - const string& type) const +StringResolverPtr Element::createStringResolver(const string& geom) const { StringResolverPtr resolver = StringResolver::create(); @@ -441,21 +438,6 @@ StringResolverPtr Element::createStringResolver(const string& geom, } } - // If a material is specified, then apply it to the filename map. - if (material) - { - for (TokenPtr token : material->getPrimaryShaderTokens(target, type)) - { - ValuePtr boundValue = token->getBoundValue(material); - if (boundValue->isA()) - { - string key = "[" + token->getName() + "]"; - string value = boundValue->asA(); - resolver->setFilenameSubstitution(key, value); - } - } - } - return resolver; } @@ -512,20 +494,6 @@ string ValueElement::getResolvedValueString(StringResolverPtr resolver) const return resolver->resolve(getValueString(), getType()); } -ValuePtr ValueElement::getBoundValue(ConstMaterialPtr material) const -{ - ElementPtr upstreamElem = getUpstreamElement(material); - if (!upstreamElem) - { - return getDefaultValue(); - } - if (upstreamElem->isA()) - { - return upstreamElem->asA()->getValue(); - } - return ValuePtr(); -} - ValuePtr ValueElement::getDefaultValue() const { if (hasValue()) @@ -632,39 +600,6 @@ bool ValueElement::validate(string* message) const return TypedElement::validate(message) && res; } -// -// Token methods -// - -Edge Token::getUpstreamEdge(ConstMaterialPtr material, size_t index) const -{ - if (material && index < getUpstreamEdgeCount()) - { - ConstElementPtr parent = getParent(); - ConstInterfaceElementPtr interface = parent ? parent->asA() : nullptr; - ConstNodeDefPtr nodeDef = interface ? interface->getDeclaration() : nullptr; - if (nodeDef) - { - // Apply BindToken elements to the Token. - for (ShaderRefPtr shaderRef : material->getActiveShaderRefs()) - { - if (shaderRef->getNodeDef()->hasInheritedBase(nodeDef)) - { - for (BindTokenPtr bindToken : shaderRef->getBindTokens()) - { - if (bindToken->getName() == getName() && bindToken->hasValue()) - { - return Edge(getSelfNonConst(), nullptr, bindToken); - } - } - } - } - } - } - - return NULL_EDGE; -} - // // StringResolver methods // @@ -760,9 +695,6 @@ INSTANTIATE_SUBCLASS(T) INSTANTIATE_CONCRETE_SUBCLASS(AttributeDef, "attributedef") INSTANTIATE_CONCRETE_SUBCLASS(Backdrop, "backdrop") -INSTANTIATE_CONCRETE_SUBCLASS(BindParam, "bindparam") -INSTANTIATE_CONCRETE_SUBCLASS(BindInput, "bindinput") -INSTANTIATE_CONCRETE_SUBCLASS(BindToken, "bindtoken") INSTANTIATE_CONCRETE_SUBCLASS(Collection, "collection") INSTANTIATE_CONCRETE_SUBCLASS(Document, "materialx") INSTANTIATE_CONCRETE_SUBCLASS(GenericElement, "generic") @@ -784,8 +716,7 @@ INSTANTIATE_CONCRETE_SUBCLASS(Property, "property") INSTANTIATE_CONCRETE_SUBCLASS(PropertyAssign, "propertyassign") INSTANTIATE_CONCRETE_SUBCLASS(PropertySet, "propertyset") INSTANTIATE_CONCRETE_SUBCLASS(PropertySetAssign, "propertysetassign") -INSTANTIATE_CONCRETE_SUBCLASS(ShaderRef, "shaderref") -INSTANTIATE_CONCRETE_SUBCLASS(TargetDef, "targetdef") + /// applicable set of geometry token substitutions. By default, no /// geometry token substitutions are applied. If the universal geometry /// name "/" is given, then all geometry token substitutions are applied, - /// @param material An optional material element, which will be used to - /// select the applicable set of interface token substitutions. - /// @param target An optional target name, which will be used to filter - /// the shader references within the material that are considered. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader references within the material that are - /// considered. /// @return A shared pointer to a StringResolver. - /// @todo The StringResolver returned by this method doesn't yet take - /// variant assignments into account. - StringResolverPtr createStringResolver(const string& geom = EMPTY_STRING, - ConstMaterialPtr material = nullptr, - const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const; + StringResolverPtr createStringResolver(const string& geom = EMPTY_STRING) const; /// Return a single-line description of this element, including its category, /// name, and attributes. string asString() const; - /// @} - - protected: - // Resolve a reference to a named element at the root scope of this document, - // taking the namespace at the scope of this element into account. + /// Resolve a reference to a named element at the root scope of this document, + /// taking the namespace at the scope of this element into account. template shared_ptr resolveRootNameReference(const string& name) const { ConstElementPtr root = getRoot(); @@ -845,6 +830,9 @@ class Element : public std::enable_shared_from_this return child ? child : root->getChildOfType(name); } + /// @} + + protected: // Enforce a requirement within a validate method, updating the validation // state and optional output text if the requirement is not met. void validateRequire(bool expression, bool& res, string* message, string errorDesc) const; @@ -1090,29 +1078,7 @@ class ValueElement : public TypedElement return Value::createValueFromStrings(getResolvedValueString(resolver), getType()); } - /// @} - /// @name Bound Value - /// @{ - - /// Return the value that is bound to this element within the context of a - /// given material. For example, a BindParam within the material will - /// affect the value of its correponding Parameter, and a BindInput will - /// affect the value of its corresponding Input. - /// - /// If this element is bound to an Output of a NodeGraph, rather than to a - /// uniform value, then an empty shared pointer is returned. - /// - /// If no data binding is applied by the material, then the default value for - /// this element is returned. - /// - /// @param material The material whose data bindings will be applied to - /// the evaluation. - /// @return A shared pointer to a typed value, or an empty shared pointer if - /// no bound or default value was found. - ValuePtr getBoundValue(ConstMaterialPtr material) const; - - /// Return the default value for this element, which will be used as its bound - /// value when no external binding from a material is present. + /// Return the default value for this element. /// /// @return A shared pointer to a typed value, or an empty shared pointer if /// no default value was found. @@ -1222,21 +1188,6 @@ class Token : public ValueElement } virtual ~Token() { } - /// @name Traversal - /// @{ - - /// Return the Edge with the given index that lies directly upstream from - /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; - - /// Return the number of queriable upstream edges for this element. - size_t getUpstreamEdgeCount() const override - { - return 1; - } - - /// @} public: static const string CATEGORY; }; diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index b52240b597..bd5b7c4a2b 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -285,44 +285,6 @@ NodePtr Input::getConnectedNode() const return PortElement::getConnectedNode(); } -Edge Input::getUpstreamEdge(ConstMaterialPtr material, size_t index) const -{ - if (material && index < getUpstreamEdgeCount()) - { - ConstElementPtr parent = getParent(); - ConstInterfaceElementPtr interface = parent ? parent->asA() : nullptr; - ConstNodeDefPtr nodeDef = interface ? interface->getDeclaration() : nullptr; - if (nodeDef) - { - // Apply BindInput elements to the Input. - for (ShaderRefPtr shaderRef : material->getActiveShaderRefs()) - { - if (shaderRef->getNodeDef()->hasInheritedBase(nodeDef)) - { - for (BindInputPtr bindInput : shaderRef->getBindInputs()) - { - if (bindInput->getName() != getName()) - { - continue; - } - OutputPtr output = bindInput->getConnectedOutput(); - if (output) - { - return Edge(getSelfNonConst(), bindInput, output); - } - if (bindInput->hasValue()) - { - return Edge(getSelfNonConst(), nullptr, bindInput); - } - } - } - } - } - } - - return NULL_EDGE; -} - GeomPropDefPtr Input::getDefaultGeomProp() const { const string& defaultGeomProp = getAttribute(DEFAULT_GEOM_PROP_ATTRIBUTE); diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index a8694fc8cd..23ccab23ae 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -218,17 +218,6 @@ class Input : public PortElement /// @name Traversal /// @{ - /// Return the Edge with the given index that lies directly upstream from - /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; - - /// Return the number of queriable upstream edges for this element. - size_t getUpstreamEdgeCount() const override - { - return 1; - } - /// Return the output, if any, to which this element is connected. OutputPtr getConnectedOutput() const; diff --git a/source/MaterialXCore/Material.cpp b/source/MaterialXCore/Material.cpp index ac0dfe841f..1f7a210ef6 100644 --- a/source/MaterialXCore/Material.cpp +++ b/source/MaterialXCore/Material.cpp @@ -10,54 +10,9 @@ namespace MaterialX { -const string BindInput::NODE_GRAPH_ATTRIBUTE = "nodegraph"; -const string BindInput::OUTPUT_ATTRIBUTE = "output"; - -const string ShaderRef::NODE_ATTRIBUTE = "node"; -const string ShaderRef::NODE_DEF_ATTRIBUTE = "nodedef"; - -// -// Material methods -// - -ShaderRefPtr Material::addShaderRef(const string& name, const string& node) -{ - ShaderRefPtr shaderRef = addChild(name); - if (!node.empty()) - { - shaderRef->setNodeString(node); - } - return shaderRef; -} - -vector Material::getActiveShaderRefs() const -{ - vector activeShaderRefs; - for (ConstElementPtr elem : traverseInheritance()) - { - vector shaderRefs = elem->asA()->getShaderRefs(); - activeShaderRefs.insert(activeShaderRefs.end(), shaderRefs.begin(), shaderRefs.end()); - } - return activeShaderRefs; -} - -vector Material::getShaderNodeDefs(const string& target, const string& type) const +vector Material::getShaderNodeDefs(const string&, const string&) const { - vector nodeDefs; - for (ShaderRefPtr shaderRef : getActiveShaderRefs()) - { - NodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (!nodeDef || !targetStringsMatch(nodeDef->getTarget(), target)) - { - continue; - } - if (!type.empty() && type != nodeDef->getType()) - { - continue; - } - nodeDefs.push_back(nodeDef); - } - return nodeDefs; + return {}; } vector Material::getGeometryBindings(const string& geom) const @@ -118,155 +73,4 @@ vector Material::getPrimaryShaderTokens(const string& target, const st return res; } -bool Material::validate(string* message) const -{ - bool res = true; - if (!hasInheritanceCycle()) - { - validateRequire(!getActiveShaderRefs().empty(), res, message, "Missing shader reference"); - } - return Element::validate(message) && res; -} - -// -// BindInput methods -// - -void BindInput::setConnectedOutput(ConstOutputPtr output) -{ - if (output) - { - setOutputString(output->getName()); - ConstElementPtr parent = output->getParent(); - if (parent->isA()) - { - setNodeGraphString(parent->getName()); - } - else - { - removeAttribute(NODE_GRAPH_ATTRIBUTE); - } - } - else - { - removeAttribute(OUTPUT_ATTRIBUTE); - removeAttribute(NODE_GRAPH_ATTRIBUTE); - } -} - -OutputPtr BindInput::getConnectedOutput() const -{ - if (hasNodeGraphString()) - { - NodeGraphPtr nodeGraph = resolveRootNameReference(getNodeGraphString()); - return nodeGraph ? nodeGraph->getOutput(getOutputString()) : OutputPtr(); - } - return getDocument()->getOutput(getOutputString()); -} - -bool BindInput::validate(string* message) const -{ - bool res = true; - ConstElementPtr parent = getParent(); - ConstShaderRefPtr shaderRef = parent ? parent->asA() : nullptr; - NodeDefPtr nodeDef = shaderRef ? shaderRef->getNodeDef() : nullptr; - if (nodeDef) - { - InputPtr input = nodeDef->getActiveInput(getName()); - validateRequire(input != nullptr, res, message, "BindInput does not match an Input in the referenced NodeDef"); - if (input) - { - validateRequire(getType() == input->getType(), res, message, "Type mismatch between BindInput and Input"); - } - } - if (hasNodeGraphString()) - { - NodeGraphPtr nodeGraph = resolveRootNameReference(getNodeGraphString()); - validateRequire(nodeGraph != nullptr, res, message, "Invalid node graph attribute on BindInput"); - } - if (hasOutputString()) - { - OutputPtr output = getConnectedOutput(); - validateRequire(output != nullptr, res, message, "Invalid output attribute on BindInput"); - } - return ValueElement::validate(message) && res; -} - -// -// BindToken methods -// - -bool BindToken::validate(string* message) const -{ - bool res = true; - ConstElementPtr parent = getParent(); - ConstShaderRefPtr shaderRef = parent ? parent->asA() : nullptr; - NodeDefPtr nodeDef = shaderRef ? shaderRef->getNodeDef() : nullptr; - if (nodeDef) - { - TokenPtr token = nodeDef->getActiveToken(getName()); - validateRequire(token != nullptr, res, message, "BindToken does not match a Token in the referenced NodeDef"); - } - return ValueElement::validate(message) && res; -} - -// -// ShaderRef methods -// - -NodeDefPtr ShaderRef::getNodeDef() const -{ - if (hasNodeDefString()) - { - return resolveRootNameReference(getNodeDefString()); - } - if (hasNodeString()) - { - vector nodeDefs = getDocument()->getMatchingNodeDefs(getQualifiedName(getNodeString())); - vector secondary = getDocument()->getMatchingNodeDefs(getNodeString()); - nodeDefs.insert(nodeDefs.end(), secondary.begin(), secondary.end()); - for (NodeDefPtr nodeDef : nodeDefs) - { - if (targetStringsMatch(nodeDef->getTarget(), getTarget()) && - nodeDef->isVersionCompatible(getSelf()) && - (!hasType() || nodeDef->getType() == getType())) - { - return nodeDef; - } - } - } - return NodeDefPtr(); -} - -bool ShaderRef::validate(string* message) const -{ - bool res = true; - NodeDefPtr nodeDef = getNodeDef(); - TypeDefPtr typeDef = nodeDef ? resolveRootNameReference(nodeDef->getType()) : TypeDefPtr(); - if (!nodeDef) - { - validateRequire(!hasNodeString() && !hasNodeDefString(), res, message, "Shader reference to a non-existent nodedef"); - } - if (typeDef) - { - validateRequire(typeDef->getSemantic() == SHADER_SEMANTIC, res, message, "Shader reference to a non-shader nodedef"); - } - return TypedElement::validate(message) && res; -} - -Edge ShaderRef::getUpstreamEdge(ConstMaterialPtr material, size_t index) const -{ - if (index < getUpstreamEdgeCount()) - { - BindInputPtr input = getBindInputs()[index]; - ElementPtr upstreamOutput = input->getConnectedOutput(); - if (upstreamOutput) - { - return Edge(getSelfNonConst(), input, upstreamOutput); - } - } - - return NULL_EDGE; -} - } // namespace MaterialX diff --git a/source/MaterialXCore/Material.h b/source/MaterialXCore/Material.h index 0d1d6b715d..fdd38b9ced 100644 --- a/source/MaterialXCore/Material.h +++ b/source/MaterialXCore/Material.h @@ -19,11 +19,6 @@ namespace MaterialX { class Material; -class ShaderRef; -class BindParam; -class BindInput; -class BindToken; -class Override; class MaterialInherit; class MaterialAssign; class Collection; @@ -33,26 +28,6 @@ using MaterialPtr = shared_ptr; /// A shared pointer to a const Material using ConstMaterialPtr = shared_ptr; -/// A shared pointer to a ShaderRef -using ShaderRefPtr = shared_ptr; -/// A shared pointer to a const ShaderRef -using ConstShaderRefPtr = shared_ptr; - -/// A shared pointer to a BindParam -using BindParamPtr = shared_ptr; -/// A shared pointer to a const BindParam -using ConstBindParamPtr = shared_ptr; - -/// A shared pointer to a BindInput -using BindInputPtr = shared_ptr; -/// A shared pointer to a const BindInput -using ConstBindInputPtr = shared_ptr; - -/// A shared pointer to a BindToken -using BindTokenPtr = shared_ptr; -/// A shared pointer to a const BindToken -using ConstBindTokenPtr = shared_ptr; - /// @class Material /// A material element within a Document. /// @@ -72,42 +47,6 @@ class Material : public Element using CollectionPtr = shared_ptr; public: - /// @name ShaderRef Elements - /// @{ - - /// Add a ShaderRef to the material. - /// @param name The name of the new ShaderRef. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @param node An optional node string, which should match the node - /// attribute of the NodeDef to be referenced. - /// @return A shared pointer to the new ShaderRef. - ShaderRefPtr addShaderRef(const string& name = EMPTY_STRING, - const string& node = EMPTY_STRING); - - /// Return the ShaderRef, if any, with the given name. - ShaderRefPtr getShaderRef(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all ShaderRef elements in the material. - vector getShaderRefs() const - { - return getChildrenOfType(); - } - - /// Return a vector of all ShaderRef elements that belong to this material, - /// taking material inheritance into account. - vector getActiveShaderRefs() const; - - /// Remove the ShaderRef, if any, with the given name. - void removeShaderRef(const string& name) - { - removeChildOfType(name); - } - - /// @} /// @name NodeDef References /// @{ @@ -189,365 +128,9 @@ class Material : public Element vector getGeometryBindings(const string& geom = UNIVERSAL_GEOM_NAME) const; /// @} - /// @name Validation - /// @{ - - /// Validate that the given element tree, including all descendants, is - /// consistent with the MaterialX specification. - bool validate(string* message = nullptr) const override; - - /// @} - - public: - static const string CATEGORY; -}; - -/// @class BindParam -/// A bind parameter element within a ShaderRef. -/// -/// A BindParam binds uniform data to a Parameter of a shader NodeDef within -/// the scope of a Material. -class BindParam : public ValueElement -{ - public: - BindParam(ElementPtr parent, const string& name) : - ValueElement(parent, CATEGORY, name) - { - } - virtual ~BindParam() { } - - public: - static const string CATEGORY; -}; - -/// @class BindInput -/// A bind input element within a ShaderRef. -/// -/// A BindInput binds spatially-varying data to an Input of a shader NodeDef -/// within the scope of a material. -class BindInput : public ValueElement -{ - public: - BindInput(ElementPtr parent, const string& name) : - ValueElement(parent, CATEGORY, name) - { - } - virtual ~BindInput() { } - - /// @name NodeGraph String - /// @{ - - /// Set the node graph string of this element. - void setNodeGraphString(const string& graph) - { - setAttribute(NODE_GRAPH_ATTRIBUTE, graph); - } - - /// Return true if this element has a node graph string. - bool hasNodeGraphString() const - { - return hasAttribute(NODE_GRAPH_ATTRIBUTE); - } - - /// Return the node graph string of this element. - const string& getNodeGraphString() const - { - return getAttribute(NODE_GRAPH_ATTRIBUTE); - } - - /// @} - /// @name Output String - /// @{ - - /// Set the output string of this element. - void setOutputString(const string& output) - { - setAttribute(OUTPUT_ATTRIBUTE, output); - } - - /// Return true if this element has an output string. - bool hasOutputString() const - { - return hasAttribute(OUTPUT_ATTRIBUTE); - } - - /// Return the output string of this element. - const string& getOutputString() const - { - return getAttribute(OUTPUT_ATTRIBUTE); - } - - /// @} - /// @name Connections - /// @{ - - /// Set the output to which the BindInput is connected. - void setConnectedOutput(ConstOutputPtr output); - - /// Return the output, if any, to which the BindInput is connected. - OutputPtr getConnectedOutput() const; - - /// @} - /// @name Validation - /// @{ - - /// Validate that the given element tree, including all descendants, is - /// consistent with the MaterialX specification. - bool validate(string* message = nullptr) const override; - - /// @} - - public: - static const string CATEGORY; - static const string NODE_GRAPH_ATTRIBUTE; - static const string OUTPUT_ATTRIBUTE; -}; - -/// @class BindToken -/// A bind token element within a ShaderRef. -/// -/// A BindToken binds a string value to a Token of a shader NodeDef within -/// the scope of a material. -class BindToken : public ValueElement -{ - public: - BindToken(ElementPtr parent, const string& name) : - ValueElement(parent, CATEGORY, name) - { - } - virtual ~BindToken() { } - - /// @name Validation - /// @{ - - /// Validate that the given element tree, including all descendants, is - /// consistent with the MaterialX specification. - bool validate(string* message = nullptr) const override; - - /// @} - - public: - static const string CATEGORY; -}; - -/// @class ShaderRef -/// A shader reference element within a Material. -/// -/// A ShaderRef instantiates a shader NodeDef within the context of a Material. -class ShaderRef : public TypedElement -{ - public: - ShaderRef(ElementPtr parent, const string& name) : - TypedElement(parent, CATEGORY, name) - { - } - virtual ~ShaderRef() { } - - /// @name Node String - /// @{ - - /// Set the node string of the ShaderRef. This attribute declares a - /// ShaderRef as a reference to the first NodeDef with the matching - /// node string. - void setNodeString(const string& node) - { - setAttribute(NODE_ATTRIBUTE, node); - } - - /// Return true if the given ShaderRef has a node string. - bool hasNodeString() const - { - return hasAttribute(NODE_ATTRIBUTE); - } - - /// Return the node string of the ShaderRef. - const string& getNodeString() const - { - return getAttribute(NODE_ATTRIBUTE); - } - - /// @} - /// @name NodeDef String - /// @{ - - /// Set the NodeDef string for the ShaderRef. This attribute declares a - /// ShaderRef as a reference to the unique NodeDef with the given name. - void setNodeDefString(const string& nodeDef) - { - setAttribute(NODE_DEF_ATTRIBUTE, nodeDef); - } - - /// Return true if the given ShaderRef has a NodeDef string. - bool hasNodeDefString() const - { - return hasAttribute(NODE_DEF_ATTRIBUTE); - } - - /// Return the NodeDef string for the ShaderRef. - const string& getNodeDefString() const - { - return getAttribute(NODE_DEF_ATTRIBUTE); - } - - /// @} - /// @name BindParam Elements - /// @{ - - /// Add a BindParam to the ShaderRef. - /// @param name The name of the new BindParam. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @param type An optional type string. - /// @return A shared pointer to the new BindParam. - BindParamPtr addBindParam(const string& name, const string& type = DEFAULT_TYPE_STRING) - { - BindParamPtr child = addChild(name); - child->setType(type); - return child; - } - - /// Return the BindParam, if any, with the given name. - BindParamPtr getBindParam(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all BindParam elements in the ShaderRef. - vector getBindParams() const - { - return getChildrenOfType(); - } - - /// Remove the BindParam, if any, with the given name. - void removeBindParam(const string& name) - { - removeChildOfType(name); - } - - /// @} - /// @name BindInput Elements - /// @{ - - /// Add a BindInput to the ShaderRef. - /// @param name The name of the new BindInput. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @param type An optional type string. - /// @return A shared pointer to the new BindInput. - BindInputPtr addBindInput(const string& name, const string& type = DEFAULT_TYPE_STRING) - { - BindInputPtr child = addChild(name); - child->setType(type); - return child; - } - - /// Return the BindInput, if any, with the given name. - BindInputPtr getBindInput(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all BindInput elements in the ShaderRef. - vector getBindInputs() const - { - return getChildrenOfType(); - } - - /// Remove the BindInput, if any, with the given name. - void removeBindInput(const string& name) - { - removeChildOfType(name); - } - - /// @} - /// @name BindToken Elements - /// @{ - - /// Add a BindToken to the ShaderRef. - /// @param name The name of the new BindToken. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @return A shared pointer to the new BindToken. - BindTokenPtr addBindToken(const string& name) - { - return addChild(name); - } - - /// Return the BindToken, if any, with the given name. - BindTokenPtr getBindToken(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all BindInput elements in the ShaderRef. - vector getBindTokens() const - { - return getChildrenOfType(); - } - - /// Remove the BindToken, if any, with the given name. - void removeBindToken(const string& name) - { - removeChildOfType(name); - } - - /// @} - /// @name NodeDef References - /// @{ - - /// Return the NodeDef, if any, that this element references. - NodeDefPtr getNodeDef() const; - - /// @} - /// @name Output References - /// @{ - - /// Return a vector of all outputs that this element references. - vector getReferencedOutputs() const - { - vector outputVec; - std::set outputSet; - for (BindInputPtr bindInput : getBindInputs()) - { - OutputPtr output = bindInput->getConnectedOutput(); - if (output && !outputSet.count(output)) - { - outputVec.push_back(output); - outputSet.insert(output); - } - } - return outputVec; - } - - /// @} - /// @name Validation - /// @{ - - /// Validate that the given element tree, including all descendants, is - /// consistent with the MaterialX specification. - bool validate(string* message = nullptr) const override; - - /// @} - /// @name Traversal - /// @{ - - /// Return the Edge with the given index that lies directly upstream from - /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; - - /// Return the number of queriable upstream edges for this element. - size_t getUpstreamEdgeCount() const override - { - return getBindInputs().size(); - } - - /// @} public: static const string CATEGORY; - static const string NODE_ATTRIBUTE; - static const string NODE_DEF_ATTRIBUTE; }; } // namespace MaterialX diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index 234b78c2b2..dd18c75b0c 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -128,31 +128,6 @@ OutputPtr Node::getNodeDefOutput(ElementPtr connectingElement) } } } - else - { - const BindInputPtr bindInput = connectingElement->asA(); - if (bindInput) - { - // Handle the case where the edge involves a bindinput. - const OutputPtr output = bindInput->getConnectedOutput(); - if (output) - { - if (output->getParent()->isA()) - { - // The bindinput connects to a graph output, - // so this is the output we're looking for. - outputName = &output->getName(); - } - else - { - // The bindinput connects to a free floating output, - // so we have an extra level of indirection. Hence - // get its connected output. - outputName = &output->getOutputString(); - } - } - } - } if (outputName && !outputName->empty()) { // Find this output on our nodedef. diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index cae6fee253..e9d4a9e960 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -125,7 +125,7 @@ class Node : public InterfaceElement return getInputCount(); } - /// Given a connecting element (Input/Output/BindInput) return the NodeDef output + /// Given a connecting element (Input or Output) return the NodeDef output /// corresponding to the output the element is connected to. This is only valid if /// the NodeDef has explicit outputs defined, e.g. multiple outputs or an explicitly /// named output. If this is not the case, nullptr is returned, which implies the diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 8f48cfb6d4..956da74ed6 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -81,8 +81,7 @@ void ShaderGraph::addOutputSockets(const InterfaceElement& elem) void ShaderGraph::createConnectedNodes(const ElementPtr& downstreamElement, const ElementPtr& upstreamElement, ElementPtr connectingElement, - GenContext& context, - ShaderNode* rootNode) + GenContext& context) { // Create the node if it doesn't exists NodePtr upstreamNode = upstreamElement->asA(); @@ -119,59 +118,40 @@ void ShaderGraph::createConnectedNodes(const ElementPtr& downstreamElement, "' on upstream node '" + upstreamNode->getName() + "'"); } - // First check if this was a bind input connection - // In this case we must have a root node as well - if (rootNode && connectingElement && connectingElement->isA()) + // Check if it was a node downstream + NodePtr downstreamNode = downstreamElement->asA(); + if (downstreamNode) { - // Connect to the corresponding input on the root node - ShaderInput* input = rootNode->getInput(connectingElement->getName()); - if (input) + // We have a node downstream + ShaderNode* downstream = getNode(downstreamNode->getName()); + if (downstream && connectingElement) { - input->breakConnection(); + ShaderInput* input = downstream->getInput(connectingElement->getName()); + if (!input) + { + throw ExceptionShaderGenError("Could not find an input named '" + connectingElement->getName() + + "' on downstream node '" + downstream->getName() + "'"); + } input->makeConnection(output); } + else + { + throw ExceptionShaderGenError("Could not find downstream node ' " + downstreamNode->getName() + "'"); + } } else { - // Check if it was a node downstream - NodePtr downstreamNode = downstreamElement->asA(); - if (downstreamNode) - { - // We have a node downstream - ShaderNode* downstream = getNode(downstreamNode->getName()); - if (downstream && connectingElement) - { - ShaderInput* input = downstream->getInput(connectingElement->getName()); - if (!input) - { - throw ExceptionShaderGenError("Could not find an input named '" + connectingElement->getName() + - "' on downstream node '" + downstream->getName() + "'"); - } - input->makeConnection(output); - } - else - { - throw ExceptionShaderGenError("Could not find downstream node ' " + downstreamNode->getName() + "'"); - } - } - else + // Not a node, then it must be an output + ShaderGraphOutputSocket* outputSocket = getOutputSocket(downstreamElement->getName()); + if (outputSocket) { - // Not a node, then it must be an output - ShaderGraphOutputSocket* outputSocket = getOutputSocket(downstreamElement->getName()); - if (outputSocket) - { - outputSocket->makeConnection(output); - } + outputSocket->makeConnection(output); } } } void ShaderGraph::addUpstreamDependencies(const Element& root, ConstMaterialPtr material, GenContext& context) { - // Keep track of our root node in the graph. - // This is needed when the graph is a shader graph and we need - // to make connections for BindInputs during traversal below. - ShaderNode* rootNode = getNode(root.getName()); std::set processedOutputs; for (Edge edge : root.traverseGraph(material)) @@ -209,8 +189,7 @@ void ShaderGraph::addUpstreamDependencies(const Element& root, ConstMaterialPtr createConnectedNodes(downstreamElement, upstreamElement, edge.getConnectingElement(), - context, - rootNode); + context); } } diff --git a/source/MaterialXGenShader/ShaderGraph.h b/source/MaterialXGenShader/ShaderGraph.h index 2dfd50f179..a061d9868b 100644 --- a/source/MaterialXGenShader/ShaderGraph.h +++ b/source/MaterialXGenShader/ShaderGraph.h @@ -120,12 +120,10 @@ class ShaderGraph : public ShaderNode /// @param upstreamElement Element representing the node to connect from /// @param connectingElement If non-null, specifies the element on on the downstream node to connect to. /// @param context Context for generation. - /// @param rootNode Root node for downstream element. Only required for handing ShaderRef elements. void createConnectedNodes(const ElementPtr& downstreamElement, const ElementPtr& upstreamElement, ElementPtr connectingElement, - GenContext& context, - ShaderNode* rootNode = nullptr); + GenContext& context); /// Add a node to the graph void addNode(ShaderNodePtr node); diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index c4ccc58798..f8ae09a22d 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -455,161 +455,6 @@ bool isTransparentSurface(ElementPtr element, const ShaderGenerator& shadergen) } } - // Handle shader refs - else if (element->isA()) - { - ShaderRefPtr shaderRef = element->asA(); - NodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (!nodeDef) - { - throw ExceptionShaderGenError("Could not find a nodedef for shaderref '" + shaderRef->getName() + "' in material " + shaderRef->getParent()->getName()); - } - if (TypeDesc::get(nodeDef->getType()) != Type::SURFACESHADER) - { - return false; - } - - // Check opacity - BindInputPtr opacity = shaderRef->getBindInput("opacity"); - if (opacity) - { - if (opacity->getConnectedOutput()) - { - return true; - } - else - { - ValuePtr value = opacity->getValue(); - if (value && !isOne(value)) - { - return true; - } - } - } - - // Check existence - BindInputPtr existence = shaderRef->getBindInput("existence"); - if (existence) - { - if (existence->getConnectedOutput()) - { - return true; - } - else - { - ValuePtr value = existence->getValue(); - if (value && !isOne(value)) - { - return true; - } - } - } - - // Check transmission - BindInputPtr transmission = shaderRef->getBindInput("transmission"); - if (transmission) - { - if (transmission->getConnectedOutput()) - { - return true; - } - else - { - ValuePtr value = transmission->getValue(); - if (value && !isZero(value)) - { - return true; - } - } - } - - // Check subsurface - BindInputPtr subsurface = shaderRef->getBindInput("subsurface"); - if (subsurface) - { - if (subsurface->getConnectedOutput()) - { - return true; - } - else - { - ValuePtr value = subsurface->getValue(); - if (value && !isZero(value)) - { - return true; - } - } - } - - // Check for a transparent graph. - InterfaceElementPtr impl = nodeDef->getImplementation(shadergen.getTarget()); - if (!impl) - { - throw ExceptionShaderGenError("Could not find a matching implementation for node '" + nodeDef->getNodeString() + - "' matching target '" + shadergen.getTarget() + "'"); - } - if (impl->isA()) - { - NodeGraphPtr graph = impl->asA(); - - vector outputs = graph->getActiveOutputs(); - if (!outputs.empty()) - { - const OutputPtr& output = outputs[0]; - if (TypeDesc::get(output->getType()) == Type::SURFACESHADER) - { - StringSet opacityInterfaceNames; - StringSet transmissionInterfaceNames; - bool isTransparent = isTransparentShaderGraph(output, shadergen, opacityInterfaceNames, transmissionInterfaceNames); - - if (!isTransparent) - { - for (const string& opacityInterfaceName : opacityInterfaceNames) - { - opacity = shaderRef->getBindInput(opacityInterfaceName); - if (opacity) - { - if (!opacity->getOutputString().empty()) - { - return true; - } - else - { - ValuePtr value = opacity->getValue(); - if (value && !isOne(value)) - { - return true; - } - } - } - } - for (const string& transmissionInterfaceName : transmissionInterfaceNames) - { - transmission = shaderRef->getBindInput(transmissionInterfaceName); - if (transmission) - { - if (!transmission->getOutputString().empty()) - { - return true; - } - else - { - ValuePtr value = transmission->getValue(); - if (value && !isZero(value)) - { - return true; - } - } - } - } - } - - return false; - } - } - } - } - // Handle output nodes else if (element->isA()) { @@ -692,8 +537,7 @@ bool elementRequiresShading(ConstTypedElementPtr element) "surfaceshader", "volumeshader", "lightshader", "BSDF", "EDF", "VDF" }; - return (element->isA() || - colorClosures.count(elementType) > 0); + return colorClosures.count(elementType) > 0; } void findRenderableMaterialNodes(ConstDocumentPtr doc, @@ -730,52 +574,11 @@ void findRenderableMaterialNodes(ConstDocumentPtr doc, } } -void findRenderableShaderRefs(ConstDocumentPtr doc, - vector& elements, - bool includeReferencedGraphs, - std::unordered_set& processedSources) -{ - for (const auto& material : doc->getMaterials()) - { - for (const auto& shaderRef : material->getShaderRefs()) - { - if (!shaderRef->hasSourceUri()) - { - // Add in all shader references which are not part of a node definition library - ConstNodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (!nodeDef) - { - throw ExceptionShaderGenError("Could not find a nodedef for shaderref '" + shaderRef->getName() + - "' in material '" + shaderRef->getParent()->getName() + "'"); - } - if (requiresImplementation(nodeDef)) - { - elements.push_back(shaderRef); - } - - if (!includeReferencedGraphs) - { - // Track outputs already used by the shaderref - for (const auto& bindInput : shaderRef->getBindInputs()) - { - OutputPtr outputPtr = bindInput->getConnectedOutput(); - if (outputPtr && !outputPtr->hasSourceUri() && !processedSources.count(outputPtr)) - { - processedSources.insert(outputPtr); - } - } - } - } - } - } -} - void findRenderableElements(ConstDocumentPtr doc, vector& elements, bool includeReferencedGraphs) { std::unordered_set processedSources; findRenderableMaterialNodes(doc, elements, includeReferencedGraphs, processedSources); - findRenderableShaderRefs(doc, elements, includeReferencedGraphs, processedSources); // Find node graph outputs. Skip any light shaders std::list testOutputs; @@ -856,20 +659,8 @@ ValueElementPtr findNodeDefChild(const string& path, DocumentPtr doc, const stri // Note that we must cast to a specific type derived instance as getNodeDef() is not // a virtual method which is overridden in derived classes. - NodeDefPtr nodeDef = nullptr; - ShaderRefPtr shaderRef = parent->asA(); - if (shaderRef) - { - nodeDef = shaderRef->getNodeDef(); - } - else - { - NodePtr node = parent->asA(); - if (node) - { - nodeDef = node->getNodeDef(target); - } - } + NodePtr node = parent->asA(); + NodeDefPtr nodeDef = node ? node->getNodeDef(target) : nullptr; if (!nodeDef) { return nullptr; diff --git a/source/MaterialXGenShader/Util.h b/source/MaterialXGenShader/Util.h index ed2d9aeee2..35f32b2b9f 100644 --- a/source/MaterialXGenShader/Util.h +++ b/source/MaterialXGenShader/Util.h @@ -65,16 +65,6 @@ void findRenderableMaterialNodes(ConstDocumentPtr doc, bool includeReferencedGraphs, std::unordered_set& processedSources); -/// Find any shaderrefs elements which are renderable -/// @param doc Document to examine -/// @param elements List of renderable elements (returned) -/// @param includeReferencedGraphs Whether to check for outputs on referenced graphs -/// @param processedSources List of elements examined. -void findRenderableShaderRefs(ConstDocumentPtr doc, - vector& elements, - bool includeReferencedGraphs, - std::unordered_set& processedSources); - /// Find any elements which may be renderable from within a document. /// This includes all outputs on node graphs and shader references which are not /// part of any included library. Light shaders are not considered to be renderable. diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index 1d22fdf5d0..27d6d50eca 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -55,26 +55,6 @@ TEST_CASE("Document", "[document]") REQUIRE(!specColor->getIsUniform()); mx::InputPtr roughness = shader->addInput("roughness", "float"); - // Create a material that instantiates the shader. - mx::MaterialPtr material = doc->addMaterial(); - mx::ShaderRefPtr shaderRef = material->addShaderRef("", "simpleSrf"); - - // Bind the diffuse color input to the constant color output. - mx::BindInputPtr bindInput = shaderRef->addBindInput("diffColor"); - bindInput->setConnectedOutput(output); - REQUIRE(diffColor->getUpstreamElement(material) == output); - - // Bind the roughness parameter to a value. - bindInput = shaderRef->addBindInput("roughness"); - bindInput->setValue(0.5f); - REQUIRE(roughness->getBoundValue(material)->asA() == 0.5f); - - // Create and test a type mismatch in a data binding. - bindInput->setValue(5); - REQUIRE(!doc->validate()); - bindInput->setValue(0.5f); - REQUIRE(doc->validate()); - // Create a collection mx::CollectionPtr collection = doc->addCollection(); REQUIRE(doc->getCollections().size() == 1); diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp index e5ac212114..565cd271d1 100644 --- a/source/MaterialXTest/MaterialXCore/Look.cpp +++ b/source/MaterialXTest/MaterialXCore/Look.cpp @@ -15,7 +15,6 @@ TEST_CASE("Look", "[look]") // Create a material and look. mx::MaterialPtr material = doc->addMaterial(); - material->addShaderRef(); mx::LookPtr look = doc->addLook(); REQUIRE(doc->getMaterials().size() == 1); REQUIRE(doc->getLooks().size() == 1); diff --git a/source/MaterialXTest/MaterialXCore/Material.cpp b/source/MaterialXTest/MaterialXCore/Material.cpp index 3c333263f6..a6d27a5a02 100644 --- a/source/MaterialXTest/MaterialXCore/Material.cpp +++ b/source/MaterialXTest/MaterialXCore/Material.cpp @@ -30,80 +30,4 @@ TEST_CASE("Material", "[material]") anisoSrf->setInheritsFrom(simpleSrf); anisoSrf->setInputValue("anisotropy", 0.0f); REQUIRE(anisoSrf->getInheritsFrom() == simpleSrf); - - // Create a material. - mx::MaterialPtr material = doc->addMaterial(); - REQUIRE(material->getPrimaryShaderName().empty()); - - // Add a shader reference. - mx::ShaderRefPtr refAnisoSrf = material->addShaderRef("SR_anisoSrf", "anisoSrf"); - REQUIRE(anisoSrf->getInstantiatingShaderRefs()[0] == refAnisoSrf); - REQUIRE(refAnisoSrf->getNodeDef() == anisoSrf); - REQUIRE(material->getPrimaryShaderName() == refAnisoSrf->getNodeString()); - REQUIRE(material->getPrimaryShaderInputs().size() == 4); - REQUIRE(material->getPrimaryShaderTokens().size() == 1); - - // Set nodedef and shader reference qualifiers. - refAnisoSrf->setVersionString("2.0"); - REQUIRE(refAnisoSrf->getNodeDef() == nullptr); - anisoSrf->setVersionString("2"); - REQUIRE(refAnisoSrf->getNodeDef() == anisoSrf); - refAnisoSrf->setType("volumeshader"); - REQUIRE(refAnisoSrf->getNodeDef() == nullptr); - refAnisoSrf->setType("surfaceshader"); - REQUIRE(refAnisoSrf->getNodeDef() == anisoSrf); - - // Bind a shader parameter to a value. - mx::BindInputPtr bindInput = refAnisoSrf->addBindInput("roughness"); - bindInput->setValue(0.5f); - REQUIRE(roughness->getBoundValue(material)->asA() == 0.5f); - REQUIRE(roughness->getDefaultValue()->asA() == 0.25f); - - // Bind a shader input to a value. - bindInput = refAnisoSrf->addBindInput("specColor"); - bindInput->setValue(mx::Color3(0.5f)); - REQUIRE(specColor->getBoundValue(material)->asA() == mx::Color3(0.5f)); - REQUIRE(specColor->getDefaultValue()->asA() == mx::Color3(0.0f)); - - // Bind a shader token to a value. - mx::BindTokenPtr bindToken = refAnisoSrf->addBindToken("texId"); - bindToken->setValue("02"); - REQUIRE(texId->getBoundValue(material)->asA() == "02"); - REQUIRE(texId->getDefaultValue()->asA() == "01"); - mx::StringResolverPtr resolver = doc->createStringResolver(mx::UNIVERSAL_GEOM_NAME, material); - REQUIRE(resolver->resolve("diffColor_[texId].tif", mx::FILENAME_TYPE_STRING) == "diffColor_02.tif"); - - // Add an invalid shader reference. - material->addShaderRef("SR_invalidSrf", "invalidSrf"); - REQUIRE(!doc->validate()); - material->removeShaderRef("SR_invalidSrf"); - REQUIRE(doc->validate()); - - // Create an inherited material. - mx::MaterialPtr material2 = doc->addMaterial(); - material2->setInheritsFrom(material); - REQUIRE(material2->getPrimaryShaderName() == refAnisoSrf->getNodeString()); - REQUIRE(material2->getPrimaryShaderInputs().size() == 4); - REQUIRE(material2->getPrimaryShaderTokens().size() == 1); - REQUIRE(roughness->getBoundValue(material2)->asA() == 0.5f); - - // Create and detect an inheritance cycle. - material->setInheritsFrom(material2); - REQUIRE(!doc->validate()); - material->setInheritsFrom(nullptr); - REQUIRE(doc->validate()); - - // Disconnect the inherited material. - material2->setInheritsFrom(nullptr); - REQUIRE(material2->getPrimaryShaderName().empty()); - REQUIRE(material2->getPrimaryShaderInputs().empty()); - REQUIRE(material2->getPrimaryShaderTokens().empty()); - REQUIRE(roughness->getBoundValue(material2)->asA() == 0.25f); - - // Remove shader reference. - material->removeShaderRef(refAnisoSrf->getName()); - REQUIRE(anisoSrf->getInstantiatingShaderRefs().empty()); - REQUIRE(material->getPrimaryShaderName().empty()); - REQUIRE(material->getPrimaryShaderInputs().empty()); - REQUIRE(material->getPrimaryShaderTokens().empty()); } diff --git a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp index d508d506c0..a2490790a0 100644 --- a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp +++ b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp @@ -62,23 +62,6 @@ TEST_CASE("Load content", "[xmlio]") } REQUIRE(valueElementCount > 0); - // Traverse the dataflow graph from each shader parameter and input - // to its source nodes. - for (mx::MaterialPtr material : doc->getMaterials()) - { - REQUIRE(material->getPrimaryShaderNodeDef()); - int edgeCount = 0; - for (mx::InputPtr input : material->getPrimaryShaderInputs()) - { - REQUIRE((input->getBoundValue(material) || input->getUpstreamElement(material))); - for (mx::Edge edge : input->traverseGraph(material)) - { - edgeCount++; - } - } - REQUIRE(edgeCount > 0); - } - // Serialize to XML. mx::XmlWriteOptions writeOptions; writeOptions.writeXIncludeEnable = false; diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index 424eb79f16..18fa5e5b43 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -744,7 +744,6 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons { mx::TypedElementPtr targetElement = element; mx::OutputPtr output = targetElement->asA(); - mx::ShaderRefPtr shaderRef = targetElement->asA(); mx::NodePtr outputNode = targetElement->asA(); mx::NodeDefPtr nodeDef = nullptr; if (output) @@ -756,10 +755,6 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons nodeDef = outputNode->getNodeDef(); } } - else if (shaderRef) - { - nodeDef = shaderRef->getNodeDef(); - } // Handle material node checking. For now only check first surface shader if any if (outputNode && outputNode->getType() == mx::MATERIAL_TYPE_STRING) diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index 00409a46c5..61cf93fcad 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -324,7 +324,6 @@ bool ShaderRenderTester::validate(const mx::FilePathVec& testRootPaths, const mx std::vector nodeDefs; mx::OutputPtr output = element->asA(); - mx::ShaderRefPtr shaderRef = element->asA(); mx::NodePtr outputNode = element->asA(); if (output) @@ -341,15 +340,6 @@ bool ShaderRenderTester::validate(const mx::FilePathVec& testRootPaths, const mx } } } - else if (shaderRef) - { - mx::NodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (nodeDef) - { - nodeDefs.push_back(nodeDef); - targetElements.push_back(shaderRef); - } - } // Get connected shader nodes if a material node. if (outputNode && outputNode->getType() == mx::MATERIAL_TYPE_STRING) diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 4ce36a8f30..31c218e51b 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -107,24 +107,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } // Remap references to unimplemented shader nodedefs. - for (mx::MaterialPtr material : doc->getMaterials()) - { - for (mx::ShaderRefPtr shaderRef : material->getShaderRefs()) - { - mx::NodeDefPtr nodeDef = shaderRef->getNodeDef(); - if (nodeDef && !nodeDef->getImplementation()) - { - std::vector altNodeDefs = doc->getMatchingNodeDefs(nodeDef->getNodeString()); - for (mx::NodeDefPtr altNodeDef : altNodeDefs) - { - if (altNodeDef->getImplementation()) - { - shaderRef->setNodeDefString(altNodeDef->getName()); - } - } - } - } - } for (mx::NodePtr materialNode : doc->getMaterialNodes()) { for (mx::NodePtr shader : getShaderNodes(materialNode)) @@ -1131,12 +1113,6 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie } materials.push_back(node); } - else - { - mx::ShaderRefPtr shaderRef = elem->asA(); - mx::TypedElementPtr materialRef = (shaderRef ? shaderRef->getParent()->asA() : nullptr); - materials.push_back(materialRef); - } renderablePaths.push_back(renderableElem->getNamePath()); } @@ -1239,20 +1215,7 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie } // Apply geometric assignments specified in the document, if any. - mx::ShaderRefPtr shaderRef = elem->asA(); - mx::MaterialPtr materialRef = shaderRef ? shaderRef->getParent()->asA() : nullptr; - if (materialRef) - { - for (mx::MeshPartitionPtr part : _geometryList) - { - std::string partGeomName = part->getIdentifier(); - if (!materialRef->getGeometryBindings(partGeomName).empty()) - { - assignMaterial(part, mat); - } - } - } - else if (mat && mat->getMaterialElement()) + if (mat && mat->getMaterialElement()) { mx::NodePtr materialNode = mat->getMaterialElement()->asA(); if (materialNode) @@ -1411,12 +1374,12 @@ void Viewer::saveDotFiles() mx::TypedElementPtr elem = material ? material->getElement() : nullptr; if (elem) { - mx::ShaderRefPtr shaderRef = elem->asA(); - if (shaderRef) + mx::NodePtr shaderNode = elem->asA(); + if (shaderNode && material->getMaterialElement()) { - for (mx::BindInputPtr bindInput : shaderRef->getBindInputs()) + for (mx::InputPtr input : shaderNode->getInputs()) { - mx::OutputPtr output = bindInput->getConnectedOutput(); + mx::OutputPtr output = input->getConnectedOutput(); mx::ConstNodeGraphPtr nodeGraph = output ? output->getAncestorOfType() : nullptr; if (nodeGraph) { @@ -1426,7 +1389,7 @@ void Viewer::saveDotFiles() } } - mx::NodeDefPtr nodeDef = shaderRef->getNodeDef(); + mx::NodeDefPtr nodeDef = shaderNode->getNodeDef(); mx::InterfaceElementPtr implement = nodeDef ? nodeDef->getImplementation() : nullptr; mx::NodeGraphPtr nodeGraph = implement ? implement->asA() : nullptr; if (nodeGraph) @@ -1436,34 +1399,6 @@ void Viewer::saveDotFiles() writeTextFile(dot, baseName + ".dot"); } } - else - { - mx::NodePtr shaderNode = elem->asA(); - if (shaderNode && material->getMaterialElement()) - { - for (mx::InputPtr input : shaderNode->getInputs()) - { - mx::OutputPtr output = input->getConnectedOutput(); - mx::ConstNodeGraphPtr nodeGraph = output ? output->getAncestorOfType() : nullptr; - if (nodeGraph) - { - std::string dot = nodeGraph->asStringDot(); - std::string baseName = _searchPath[0] / nodeGraph->getName(); - writeTextFile(dot, baseName + ".dot"); - } - } - - mx::NodeDefPtr nodeDef = shaderNode->getNodeDef(); - mx::InterfaceElementPtr implement = nodeDef ? nodeDef->getImplementation() : nullptr; - mx::NodeGraphPtr nodeGraph = implement ? implement->asA() : nullptr; - if (nodeGraph) - { - std::string dot = nodeGraph->asStringDot(); - std::string baseName = _searchPath[0] / nodeDef->getName(); - writeTextFile(dot, baseName + ".dot"); - } - } - } } } catch (std::exception& e) diff --git a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp index cf01b497df..d3ab4441b2 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp @@ -23,8 +23,7 @@ void bindPyDefinition(py::module& mod) .def("getNodeGroup", &mx::NodeDef::getNodeGroup) .def("getImplementation", &mx::NodeDef::getImplementation) .def("getImplementation", &mx::NodeDef::getImplementation, - py::arg("target") = mx::EMPTY_STRING) - .def("getInstantiatingShaderRefs", &mx::NodeDef::getInstantiatingShaderRefs) + py::arg("target") = mx::EMPTY_STRING, .def("isVersionCompatible", &mx::NodeDef::isVersionCompatible) .def_readonly_static("CATEGORY", &mx::NodeDef::CATEGORY) .def_readonly_static("NODE_ATTRIBUTE", &mx::NodeDef::NODE_ATTRIBUTE) diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index 6d265c02b0..90e313c41c 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -108,12 +108,9 @@ void bindPyElement(py::module& mod) .def("clearContent", &mx::Element::clearContent) .def("createValidChildName", &mx::Element::createValidChildName) .def("createStringResolver", &mx::Element::createStringResolver, - py::arg("geom") = mx::EMPTY_STRING, py::arg("material") = nullptr, py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) + py::arg("geom") = mx::EMPTY_STRING) .def("asString", &mx::Element::asString) .def("__str__", &mx::Element::asString) - BIND_ELEMENT_FUNC_INSTANCE(BindParam) - BIND_ELEMENT_FUNC_INSTANCE(BindInput) - BIND_ELEMENT_FUNC_INSTANCE(BindToken) BIND_ELEMENT_FUNC_INSTANCE(Collection) BIND_ELEMENT_FUNC_INSTANCE(Document) BIND_ELEMENT_FUNC_INSTANCE(GeomInfo) @@ -128,7 +125,6 @@ void bindPyElement(py::module& mod) BIND_ELEMENT_FUNC_INSTANCE(Property) BIND_ELEMENT_FUNC_INSTANCE(PropertySet) BIND_ELEMENT_FUNC_INSTANCE(PropertySetAssign) - BIND_ELEMENT_FUNC_INSTANCE(ShaderRef) BIND_ELEMENT_FUNC_INSTANCE(Token) BIND_ELEMENT_FUNC_INSTANCE(TypeDef) BIND_ELEMENT_FUNC_INSTANCE(Visibility); @@ -154,7 +150,6 @@ void bindPyElement(py::module& mod) .def("hasImplementationName", &mx::ValueElement::hasImplementationName) .def("getImplementationName", &mx::ValueElement::getImplementationName) .def("_getValue", &mx::ValueElement::getValue) - .def("_getBoundValue", &mx::ValueElement::getBoundValue) .def("_getDefaultValue", &mx::ValueElement::getDefaultValue) .def("setUnit", &mx::ValueElement::setUnit) .def("hasUnit", &mx::ValueElement::hasUnit) diff --git a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp index bd46555b41..e00f0cf94b 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp @@ -15,12 +15,6 @@ namespace mx = MaterialX; void bindPyMaterial(py::module& mod) { py::class_(mod, "Material") - .def("_addShaderRef", &mx::Material::addShaderRef, - py::arg("name") = mx::EMPTY_STRING, py::arg("node") = mx::EMPTY_STRING) - .def("getShaderRef", &mx::Material::getShaderRef) - .def("getShaderRefs", &mx::Material::getShaderRefs) - .def("getActiveShaderRefs", &mx::Material::getActiveShaderRefs) - .def("removeShaderRef", &mx::Material::removeShaderRef) .def("getShaderNodeDefs", &mx::Material::getShaderNodeDefs, py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) .def("getPrimaryShaderNodeDef", &mx::Material::getPrimaryShaderNodeDef, @@ -35,48 +29,6 @@ void bindPyMaterial(py::module& mod) py::arg("geom") = mx::UNIVERSAL_GEOM_NAME) .def_readonly_static("CATEGORY", &mx::Material::CATEGORY); - py::class_(mod, "BindParam") - .def_readonly_static("CATEGORY", &mx::BindParam::CATEGORY); - - py::class_(mod, "BindInput") - .def("setNodeGraphString", &mx::BindInput::setNodeGraphString) - .def("hasNodeGraphString", &mx::BindInput::hasNodeGraphString) - .def("getNodeGraphString", &mx::BindInput::getNodeGraphString) - .def("setOutputString", &mx::BindInput::setOutputString) - .def("hasOutputString", &mx::BindInput::hasOutputString) - .def("getOutputString", &mx::BindInput::getOutputString) - .def("setConnectedOutput", &mx::BindInput::setConnectedOutput) - .def("getConnectedOutput", &mx::BindInput::getConnectedOutput) - .def_readonly_static("CATEGORY", &mx::BindInput::CATEGORY); - - py::class_(mod, "BindToken") - .def_readonly_static("CATEGORY", &mx::BindToken::CATEGORY); - - py::class_(mod, "ShaderRef") - .def("setNodeString", &mx::ShaderRef::setNodeString) - .def("hasNodeString", &mx::ShaderRef::hasNodeString) - .def("getNodeString", &mx::ShaderRef::getNodeString) - .def("setNodeDefString", &mx::ShaderRef::setNodeDefString) - .def("hasNodeDefString", &mx::ShaderRef::hasNodeDefString) - .def("getNodeDefString", &mx::ShaderRef::getNodeDefString) - .def("getNodeDef", &mx::ShaderRef::getNodeDef) - .def("addBindParam", &mx::ShaderRef::addBindParam, - py::arg("name"), py::arg("type") = mx::DEFAULT_TYPE_STRING) - .def("getBindParam", &mx::ShaderRef::getBindParam) - .def("getBindParams", &mx::ShaderRef::getBindParams) - .def("removeBindParam", &mx::ShaderRef::removeBindParam) - .def("addBindInput", &mx::ShaderRef::addBindInput, - py::arg("name"), py::arg("type") = mx::DEFAULT_TYPE_STRING) - .def("getBindInput", &mx::ShaderRef::getBindInput) - .def("getBindInputs", &mx::ShaderRef::getBindInputs) - .def("removeBindInput", &mx::ShaderRef::removeBindInput) - .def("addBindToken", &mx::ShaderRef::addBindToken) - .def("getBindToken", &mx::ShaderRef::getBindToken) - .def("getBindTokens", &mx::ShaderRef::getBindTokens) - .def("removeBindToken", &mx::ShaderRef::removeBindToken) - .def("getReferencedOutputs", &mx::ShaderRef::getReferencedOutputs) - .def_readonly_static("CATEGORY", &mx::ShaderRef::CATEGORY); - mod.def("convertMaterialsToNodes", &mx::convertMaterialsToNodes); mod.def("getShaderNodes", &mx::getShaderNodes); mod.def("getGeometryBindings", &mx::getGeometryBindings); From dcc2826ea9124b3aead104f675a640251beea088 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 28 Nov 2020 06:59:25 -0800 Subject: [PATCH 13/35] Material element class --- python/MaterialX/main.py | 28 +--- source/MaterialXCore/Document.cpp | 12 +- source/MaterialXCore/Document.h | 48 ------ source/MaterialXCore/Element.cpp | 11 +- source/MaterialXCore/Element.h | 14 +- source/MaterialXCore/Interface.cpp | 2 +- source/MaterialXCore/Interface.h | 3 +- source/MaterialXCore/Look.cpp | 33 +++- source/MaterialXCore/Look.h | 12 +- source/MaterialXCore/Material.cpp | 153 +++++++++++++----- source/MaterialXCore/Material.h | 129 ++------------- source/MaterialXCore/Node.cpp | 4 +- source/MaterialXCore/Node.h | 19 ++- source/MaterialXCore/Traversal.cpp | 6 +- source/MaterialXCore/Traversal.h | 5 +- source/MaterialXGenShader/ShaderGraph.cpp | 16 +- source/MaterialXGenShader/ShaderGraph.h | 5 +- .../MaterialXGenShader/ShaderTranslator.cpp | 3 +- source/MaterialXGenShader/Util.cpp | 2 - source/MaterialXRenderGlsl/TextureBaker.cpp | 16 +- source/MaterialXTest/MaterialXCore/Look.cpp | 20 +-- source/MaterialXTest/MaterialXCore/Node.cpp | 2 +- .../MaterialXGenShader/GenShaderUtil.cpp | 3 +- .../MaterialXRender/RenderUtil.cpp | 1 - source/MaterialXView/Viewer.cpp | 1 - .../PyMaterialXCore/PyDocument.cpp | 7 - .../PyMaterialX/PyMaterialXCore/PyElement.cpp | 8 +- source/PyMaterialX/PyMaterialXCore/PyLook.cpp | 3 +- .../PyMaterialXCore/PyMaterial.cpp | 17 -- source/PyMaterialX/PyMaterialXCore/PyNode.cpp | 2 + 30 files changed, 231 insertions(+), 354 deletions(-) diff --git a/python/MaterialX/main.py b/python/MaterialX/main.py index b52022b20d..49365e978f 100644 --- a/python/MaterialX/main.py +++ b/python/MaterialX/main.py @@ -73,21 +73,13 @@ def _getValue(self): value = self._getValue() return value.getData() if value else None -def _getBoundValue(self, material): - """Return the value that is bound to this element within the context of a - given material, taking the entire dataflow graph into account.""" - value = self._getBoundValue(material) - return value.getData() if value else None - def _getDefaultValue(self): - """Return the default value for this element, which will be used as its bound - value when no external binding from a material is present.""" + """Return the default value for this element.""" value = self._getDefaultValue() return value.getData() if value else None ValueElement.setValue = _setValue ValueElement.getValue = _getValue -ValueElement.getBoundValue = _getBoundValue ValueElement.getDefaultValue = _getDefaultValue @@ -158,24 +150,6 @@ def _addNode(self, category, name = '', typeString = DEFAULT_TYPE_STRING): GraphElement.addNode = _addNode -# -# Material -# - -def _addOverride(self, name): - "Add an override to the material." - return self._addOverride(name) - -def _setOverrideValue(self, name, value, typeString = ''): - """Set the value of an override by its name, creating a child element - to hold the override if needed.""" - method = getattr(self.__class__, "_setOverrideValue" + getTypeString(value)) - return method(self, name, value, typeString) - -Material.addOverride = _addOverride -Material.setOverrideValue = _setOverrideValue - - # # PropertySet # diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index e87392127a..0c8aaef5ab 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -534,7 +534,7 @@ void Document::upgradeVersion(bool applyFutureUpdates) } // Assign nodedef names to shaderrefs. - for (MaterialPtr mat : getMaterials()) + for (ElementPtr mat : getChildrenOfType("material")) { for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) { @@ -551,13 +551,14 @@ void Document::upgradeVersion(bool applyFutureUpdates) } // Move connections from nodedef inputs to bindinputs. + vector materials = getChildrenOfType("material"); for (NodeDefPtr nodeDef : getNodeDefs()) { for (InputPtr input : nodeDef->getActiveInputs()) { if (input->hasAttribute("opgraph") && input->hasAttribute("graphoutput")) { - for (MaterialPtr mat : getMaterials()) + for (ElementPtr mat : materials) { for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) { @@ -647,7 +648,6 @@ void Document::upgradeVersion(bool applyFutureUpdates) { for (ElementPtr elem : traverseTree()) { - MaterialPtr material = elem->asA(); LookPtr look = elem->asA(); GeomInfoPtr geomInfo = elem->asA(); @@ -667,9 +667,9 @@ void Document::upgradeVersion(bool applyFutureUpdates) vector origChildren = elem->getChildren(); for (ElementPtr child : origChildren) { - if (material && child->getCategory() == "override") + if (elem->getCategory() == "material" && child->getCategory() == "override") { - for (ElementPtr shaderRef : material->getChildrenOfType("shaderref")) + for (ElementPtr shaderRef : elem->getChildrenOfType("shaderref")) { NodeDefPtr nodeDef = getShaderNodeDef(shaderRef); if (nodeDef) @@ -697,7 +697,7 @@ void Document::upgradeVersion(bool applyFutureUpdates) } elem->removeChild(child->getName()); } - else if (material && child->getCategory() == "materialinherit") + else if (elem->getCategory() == "material" && child->getCategory() == "materialinherit") { elem->setInheritString(child->getAttribute("material")); elem->removeChild(child->getName()); diff --git a/source/MaterialXCore/Document.h b/source/MaterialXCore/Document.h index cf10f623d3..71c1f78b1c 100644 --- a/source/MaterialXCore/Document.h +++ b/source/MaterialXCore/Document.h @@ -99,54 +99,6 @@ class Document : public GraphElement /// nodes, and include both Input and Output elements. vector getMatchingPorts(const string& nodeName) const; - /// @} - /// @name Material Elements - /// @{ - - /// Add a Material to the document. - /// @param name The name of the new Material. - /// If no name is specified, then a unique name will automatically be - /// generated. - /// @return A shared pointer to the new Material. - MaterialPtr addMaterial(const string& name = EMPTY_STRING) - { - return addChild(name); - } - - /// Return the Material, if any, with the given name. - MaterialPtr getMaterial(const string& name) const - { - return getChildOfType(name); - } - - /// Return a vector of all Material elements in the document. - vector getMaterials() const - { - return getChildrenOfType(); - } - - /// Remove the Material, if any, with the given name. - void removeMaterial(const string& name) - { - removeChildOfType(name); - } - - /// @} - /// @name Material Node Utilities - /// @{ - - /// Return the Material node, if any, with the given name. - NodePtr getMaterialNode(const string& name) const - { - return getNode(name); - } - - /// Return a vector of all Material nodes in the document. - vector getMaterialNodes() const - { - return getNodesOfType(MATERIAL_TYPE_STRING); - } - /// @} /// @name GeomInfo Elements /// @{ diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index f5feff16b7..555d70e539 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -341,19 +341,19 @@ TreeIterator Element::traverseTree() const return TreeIterator(getSelfNonConst()); } -GraphIterator Element::traverseGraph(ConstMaterialPtr material) const +GraphIterator Element::traverseGraph() const { - return GraphIterator(getSelfNonConst(), material); + return GraphIterator(getSelfNonConst()); } -Edge Element::getUpstreamEdge(ConstMaterialPtr, size_t) const +Edge Element::getUpstreamEdge(size_t) const { return NULL_EDGE; } -ElementPtr Element::getUpstreamElement(ConstMaterialPtr material, size_t index) const +ElementPtr Element::getUpstreamElement(size_t index) const { - return getUpstreamEdge(material, index).getUpstreamElement(); + return getUpstreamEdge(index).getUpstreamElement(); } InheritanceIterator Element::traverseInheritance() const @@ -705,7 +705,6 @@ INSTANTIATE_CONCRETE_SUBCLASS(Implementation, "implementation") INSTANTIATE_CONCRETE_SUBCLASS(Input, "input") INSTANTIATE_CONCRETE_SUBCLASS(Look, "look") INSTANTIATE_CONCRETE_SUBCLASS(LookGroup, "lookgroup") -INSTANTIATE_CONCRETE_SUBCLASS(Material, "material") INSTANTIATE_CONCRETE_SUBCLASS(MaterialAssign, "materialassign") INSTANTIATE_CONCRETE_SUBCLASS(Member, "member") INSTANTIATE_CONCRETE_SUBCLASS(Node, "node") diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index b543dc5dd3..c91a2330b2 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -24,7 +24,6 @@ class ValueElement; class Token; class StringResolver; class Document; -class Material; /// A shared pointer to an Element using ElementPtr = shared_ptr; @@ -78,7 +77,6 @@ class Element : public std::enable_shared_from_this protected: using DocumentPtr = shared_ptr; using ConstDocumentPtr = shared_ptr; - using ConstMaterialPtr = shared_ptr; template friend class ElementRegistry; @@ -669,8 +667,6 @@ class Element : public std::enable_shared_from_this /// Traverse the dataflow graph from the given element to each of its /// upstream sources in depth-first order, using pre-order visitation. - /// @param material An optional material element, whose data bindings will - /// be applied to the traversal. /// @throws ExceptionFoundCycle if a cycle is encountered. /// @return A GraphIterator object. /// @details Example usage with an implicit iterator: @@ -692,7 +688,7 @@ class Element : public std::enable_shared_from_this /// @endcode /// @sa getUpstreamEdge /// @sa getUpstreamElement - GraphIterator traverseGraph(ConstMaterialPtr material = nullptr) const; + GraphIterator traverseGraph() const; /// Return the Edge with the given index that lies directly upstream from /// this element in the dataflow graph. @@ -701,8 +697,7 @@ class Element : public std::enable_shared_from_this /// @param index An optional index of the edge to be returned, where the /// valid index range may be determined with getUpstreamEdgeCount. /// @return The upstream Edge, if valid, or an empty Edge object. - virtual Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const; + virtual Edge getUpstreamEdge(size_t index = 0) const; /// Return the number of queriable upstream edges for this element. virtual size_t getUpstreamEdgeCount() const @@ -712,13 +707,10 @@ class Element : public std::enable_shared_from_this /// Return the Element with the given index that lies directly upstream /// from this one in the dataflow graph. - /// @param material An optional material element, whose data bindings will - /// be applied to the query. /// @param index An optional index of the element to be returned, where the /// valid index range may be determined with getUpstreamEdgeCount. /// @return The upstream Element, if valid, or an empty ElementPtr. - ElementPtr getUpstreamElement(ConstMaterialPtr material = nullptr, - size_t index = 0) const; + ElementPtr getUpstreamElement(size_t index = 0) const; /// Traverse the inheritance chain from the given element to each element /// from which it inherits. diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index bd5b7c4a2b..bf0a1c7e2d 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -310,7 +310,7 @@ bool Input::validate(string* message) const // Output methods // -Edge Output::getUpstreamEdge(ConstMaterialPtr material, size_t index) const +Edge Output::getUpstreamEdge(size_t index) const { if (index < getUpstreamEdgeCount()) { diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index 23ccab23ae..992fc1e0b7 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -281,8 +281,7 @@ class Output : public PortElement /// Return the Edge with the given index that lies directly upstream from /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; + Edge getUpstreamEdge(size_t index = 0) const override; /// Return the number of queriable upstream edges for this element. size_t getUpstreamEdgeCount() const override diff --git a/source/MaterialXCore/Look.cpp b/source/MaterialXCore/Look.cpp index 1f35525c54..f3517e3152 100644 --- a/source/MaterialXCore/Look.cpp +++ b/source/MaterialXCore/Look.cpp @@ -5,6 +5,8 @@ #include +#include + namespace MaterialX { @@ -19,6 +21,32 @@ const string Visibility::VISIBLE_ATTRIBUTE = "visible"; const string LookGroup::LOOKS_ATTRIBUTE = "looks"; const string LookGroup::ACTIVE_ATTRIBUTE = "active"; +vector getGeometryBindings(const NodePtr& materialNode, const string& geom) +{ + vector matAssigns; + for (LookPtr look : materialNode->getDocument()->getLooks()) + { + for (MaterialAssignPtr matAssign : look->getMaterialAssigns()) + { + if (matAssign->getReferencedMaterialNode() == materialNode) + { + if (geomStringsMatch(geom, matAssign->getActiveGeom())) + { + matAssigns.push_back(matAssign); + continue; + } + CollectionPtr coll = matAssign->getCollection(); + if (coll && coll->matchesGeomString(geom)) + { + matAssigns.push_back(matAssign); + continue; + } + } + } + } + return matAssigns; +} + // // Look methods // @@ -92,11 +120,6 @@ vector Look::getActiveVisibilities() const // MaterialAssign methods // -MaterialPtr MaterialAssign::getReferencedMaterial() const -{ - return resolveRootNameReference(getMaterial()); -} - NodePtr MaterialAssign::getReferencedMaterialNode() const { return resolveRootNameReference(getMaterial()); diff --git a/source/MaterialXCore/Look.h b/source/MaterialXCore/Look.h index b86db682a1..c09ed9aeec 100644 --- a/source/MaterialXCore/Look.h +++ b/source/MaterialXCore/Look.h @@ -333,9 +333,6 @@ class MaterialAssign : public GeomElement /// @name Material References /// @{ - /// Return the Material, if any, referenced by the MaterialAssign. - MaterialPtr getReferencedMaterial() const; - /// Return the Material node, if any, referenced by the MaterialAssign. NodePtr getReferencedMaterialNode() const; @@ -488,6 +485,15 @@ class Visibility : public GeomElement static const string VISIBLE_ATTRIBUTE; }; +/// Return a vector of all MaterialAssign elements that bind this material node +/// to the given geometry string +/// @param materialNode Node to examine +/// @param geom The geometry for which material bindings should be returned. +/// By default, this argument is the universal geometry string "/", +/// and all material bindings are returned. +/// @return Vector of MaterialAssign elements +vector getGeometryBindings(const NodePtr& materialNode, const string& geom); + } // namespace MaterialX #endif diff --git a/source/MaterialXCore/Material.cpp b/source/MaterialXCore/Material.cpp index 1f7a210ef6..5a806f514f 100644 --- a/source/MaterialXCore/Material.cpp +++ b/source/MaterialXCore/Material.cpp @@ -5,72 +5,145 @@ #include -#include - namespace MaterialX { -vector Material::getShaderNodeDefs(const string&, const string&) const +std::unordered_set getShaderNodes(const NodePtr& materialNode, const string& nodeType, const string& target) { - return {}; -} + ElementPtr parent = materialNode->getParent(); + if (!parent) + { + throw Exception("Could not find a parent for material node '" + (materialNode ? materialNode->getNamePath() : EMPTY_STRING) + "'"); + } -vector Material::getGeometryBindings(const string& geom) const -{ - vector matAssigns; - for (LookPtr look : getDocument()->getLooks()) + std::unordered_set shaderNodes; + + std::vector inputs = materialNode->getActiveInputs(); + if (inputs.empty()) { - for (MaterialAssignPtr matAssign : look->getMaterialAssigns()) + // Try to find material nodes in the implementation graph if any. + // If a target is specified the nodedef for the given target is searched for. + NodeDefPtr materialNodeDef = materialNode->getNodeDef(target); + if (materialNodeDef) { - if (matAssign->getReferencedMaterial() == getSelf()) + InterfaceElementPtr impl = materialNodeDef->getImplementation(); + if (impl->isA()) { - if (geomStringsMatch(geom, matAssign->getActiveGeom())) + NodeGraphPtr implGraph = impl->asA(); + for (auto defOutput : materialNodeDef->getOutputs()) { - matAssigns.push_back(matAssign); - continue; + if (defOutput->getType() == MATERIAL_TYPE_STRING) + { + OutputPtr implGraphOutput = implGraph->getOutput(defOutput->getName()); + for (GraphIterator it = implGraphOutput->traverseGraph().begin(); it != GraphIterator::end(); ++it) + { + ElementPtr upstreamElem = it.getUpstreamElement(); + if (!upstreamElem) + { + it.setPruneSubgraph(true); + continue; + } + NodePtr upstreamNode = upstreamElem->asA(); + if (upstreamNode && upstreamNode->getType() == MATERIAL_TYPE_STRING) + { + std::unordered_set newShaderNodes = getShaderNodes(upstreamNode, nodeType, target); + if (!newShaderNodes.empty()) + { + shaderNodes.insert(newShaderNodes.begin(), newShaderNodes.end()); + } + } + } + } } - CollectionPtr coll = matAssign->getCollection(); - if (coll && coll->matchesGeomString(geom)) + } + } + } + + for (const InputPtr& input : inputs) + { + // Scan for a node directly connected to the input. + // + const string& inputShader = input->getNodeName(); + if (!inputShader.empty()) + { + NodePtr shaderNode = parent->getChildOfType(inputShader); + if (shaderNode) + { + if (!nodeType.empty() && shaderNode->getType() != nodeType) { - matAssigns.push_back(matAssign); continue; } + + if (!target.empty()) + { + NodeDefPtr nodeDef = shaderNode->getNodeDef(target); + if (!nodeDef) + { + continue; + } + } + shaderNodes.insert(shaderNode); } } - } - return matAssigns; -} -vector Material::getPrimaryShaderInputs(const string& target, const string& type) const -{ - NodeDefPtr nodeDef = getPrimaryShaderNodeDef(target, type); - vector res; - if (nodeDef) - { - InterfaceElementPtr implement = nodeDef->getImplementation(); - for (InputPtr nodeDefInput : nodeDef->getActiveInputs()) + // Check upstream nodegraph connected to the input. + // If no explicit output name given then scan all outputs on the nodegraph. + // + else { - InputPtr implementInput = implement ? implement->getInput(nodeDefInput->getName()) : nullptr; - res.push_back(implementInput ? implementInput : nodeDefInput); + const string& inputGraph = input->getNodeGraphString(); + if (!inputGraph.empty()) + { + NodeGraphPtr nodeGraph = parent->getChildOfType(inputGraph); + if (nodeGraph) + { + const string& nodeGraphOutput = input->getOutputString(); + std::vector outputs; + if (!nodeGraphOutput.empty()) + { + outputs.push_back(nodeGraph->getOutput(nodeGraphOutput)); + } + else + { + outputs = nodeGraph->getOutputs(); + } + for (OutputPtr output : outputs) + { + NodePtr upstreamNode = output->getConnectedNode(); + if (upstreamNode) + { + if (!target.empty()) + { + NodeDefPtr nodeDef = upstreamNode->getNodeDef(target); + if (!nodeDef) + { + continue; + } + } + shaderNodes.insert(upstreamNode); + } + } + } + } } } - return res; + return shaderNodes; } -vector Material::getPrimaryShaderTokens(const string& target, const string& type) const +vector getConnectedOutputs(const NodePtr& node) { - NodeDefPtr nodeDef = getPrimaryShaderNodeDef(target, type); - vector res; - if (nodeDef) + vector outputVec; + std::set outputSet; + for (InputPtr input : node->getInputs()) { - InterfaceElementPtr implement = nodeDef->getImplementation(); - for (TokenPtr nodeDefToken : nodeDef->getActiveTokens()) + OutputPtr output = input->getConnectedOutput(); + if (output && !outputSet.count(output)) { - TokenPtr implementToken = implement ? implement->getToken(nodeDefToken->getName()) : nullptr; - res.push_back(implementToken ? implementToken : nodeDefToken); + outputVec.push_back(output); + outputSet.insert(output); } } - return res; + return outputVec; } } // namespace MaterialX diff --git a/source/MaterialXCore/Material.h b/source/MaterialXCore/Material.h index fdd38b9ced..9038a5b112 100644 --- a/source/MaterialXCore/Material.h +++ b/source/MaterialXCore/Material.h @@ -15,123 +15,24 @@ #include #include -namespace MaterialX -{ - -class Material; -class MaterialInherit; -class MaterialAssign; -class Collection; - -/// A shared pointer to a Material -using MaterialPtr = shared_ptr; -/// A shared pointer to a const Material -using ConstMaterialPtr = shared_ptr; +#include -/// @class Material -/// A material element within a Document. -/// -/// A Material instantiates one or more shader nodes with a specific set of -/// data bindings. -class Material : public Element +namespace MaterialX { - public: - Material(ElementPtr parent, const string& name) : - Element(parent, CATEGORY, name) - { - } - virtual ~Material() { } - - protected: - using MaterialAssignPtr = shared_ptr; - using CollectionPtr = shared_ptr; - - public: - /// @name NodeDef References - /// @{ - - /// Return a vector of all shader nodedefs referenced by this material, - /// optionally filtered by the given target name and shader type. - /// @param target An optional target name, which will be used to filter - /// the shader nodedefs that are returned. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader nodedefs that are returned. - /// @return A vector of shared pointers to NodeDef elements. - vector getShaderNodeDefs(const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const; - - /// @} - /// @name Primary Shader - /// @{ - - /// Return the nodedef of the first shader referenced by this material, - /// optionally filtered by the given target and shader type. - /// @param target An optional target name, which will be used to filter - /// the shader nodedefs that are considered. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader nodedefs that are considered. - /// @return The nodedef of the first matching shader referenced by this - /// material, or an empty shared pointer if no matching shader was found. - NodeDefPtr getPrimaryShaderNodeDef(const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const - { - vector shaderDefs = getShaderNodeDefs(target, type); - return shaderDefs.empty() ? NodeDefPtr() : shaderDefs[0]; - } - - /// Return the node name of the first shader referenced by this material, - /// optionally filtered by the given target and shader type. - /// @param target An optional target name, which will be used to filter - /// the shader nodedefs that are considered. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader nodedefs that are considered. - /// @return The node name of the first matching shader referenced by this - /// material, or an empty string if no matching shader was found. - string getPrimaryShaderName(const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const - { - NodeDefPtr nodeDef = getPrimaryShaderNodeDef(target, type); - return nodeDef ? nodeDef->getNodeString() : EMPTY_STRING; - } - - /// Return the inputs of the first shader referenced by this material, - /// optionally filtered by the given target and shader type. - /// @param target An optional target name, which will be used to filter - /// the shader nodedefs that are considered. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader nodedefs that are considered. - /// @return The inputs of the first matching shader referenced by this - /// material, or an empty vector if no matching shader was found. - vector getPrimaryShaderInputs(const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const; - - /// Return the tokens of the first shader referenced by this material, - /// optionally filtered by the given target and shader type. - /// @param target An optional target name, which will be used to filter - /// the shader nodedefs that are considered. - /// @param type An optional shader type (e.g. "surfaceshader"), which will - /// be used to filter the shader nodedefs that are considered. - /// @return The tokens of the first matching shader referenced by this - /// material, or an empty vector if no matching shader was found. - vector getPrimaryShaderTokens(const string& target = EMPTY_STRING, - const string& type = EMPTY_STRING) const; - - /// @} - /// @name Geometry Bindings - /// @{ - - /// Return a vector of all MaterialAssign elements that bind this material - /// to the given geometry string. - /// @param geom The geometry for which material bindings should be returned. - /// By default, this argument is the universal geometry string "/", and - /// all material bindings are returned. - vector getGeometryBindings(const string& geom = UNIVERSAL_GEOM_NAME) const; - - /// @} - public: - static const string CATEGORY; -}; +/// Return a vector of all nodes connected to a Material node's inputs. The default behavior +/// is to return connected surface shader nodes. +/// @param materialNode Node to examine. +/// @param nodeType Type of node to return. If an empty string is specified then +/// all node types are returned. The default argument value is to return surface shaders. +/// @param target Target attribute filter for nodes to return. The default argument value is an empty string +/// indicating to include nodes which match any target. +std::unordered_set getShaderNodes(const NodePtr& materialNode, + const string& nodeType = SURFACE_SHADER_TYPE_STRING, + const string& target = EMPTY_STRING); + +/// Return a vector of all outputs that this nodes inputs are connected to. +vector getConnectedOutputs(const NodePtr& node); } // namespace MaterialX diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index dd18c75b0c..a0ad6b6321 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -86,7 +86,7 @@ NodeDefPtr Node::getNodeDef(const string& target) const return NodeDefPtr(); } -Edge Node::getUpstreamEdge(ConstMaterialPtr material, size_t index) const +Edge Node::getUpstreamEdge(size_t index) const { if (index < getUpstreamEdgeCount()) { @@ -314,7 +314,7 @@ vector GraphElement::topologicalSort() const size_t connectionCount = 0; for (size_t i = 0; i < child->getUpstreamEdgeCount(); ++i) { - if (child->getUpstreamEdge(nullptr, i)) + if (child->getUpstreamEdge(i)) { connectionCount++; } diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index e9d4a9e960..3ec879aaa8 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -116,8 +116,7 @@ class Node : public InterfaceElement /// Return the Edge with the given index that lies directly upstream from /// this element in the dataflow graph. - Edge getUpstreamEdge(ConstMaterialPtr material = nullptr, - size_t index = 0) const override; + Edge getUpstreamEdge(size_t index = 0) const override; /// Return the number of queriable upstream edges for this element. size_t getUpstreamEdgeCount() const override @@ -238,6 +237,22 @@ class GraphElement : public InterfaceElement removeChildOfType(name); } + /// @} + /// @name Material Nodes + /// @{ + + /// Return the material node, if any, with the given name. + NodePtr getMaterialNode(const string& name) const + { + return getNode(name); + } + + /// Return a vector of all material nodes. + vector getMaterialNodes() const + { + return getNodesOfType(MATERIAL_TYPE_STRING); + } + /// @} /// @name Backdrop Elements /// @{ diff --git a/source/MaterialXCore/Traversal.cpp b/source/MaterialXCore/Traversal.cpp index dda339bc70..e71bf77e9b 100644 --- a/source/MaterialXCore/Traversal.cpp +++ b/source/MaterialXCore/Traversal.cpp @@ -13,7 +13,7 @@ namespace MaterialX const Edge NULL_EDGE(nullptr, nullptr, nullptr); const TreeIterator NULL_TREE_ITERATOR(nullptr); -const GraphIterator NULL_GRAPH_ITERATOR(nullptr, nullptr); +const GraphIterator NULL_GRAPH_ITERATOR(nullptr); const InheritanceIterator NULL_INHERITANCE_ITERATOR(nullptr); // @@ -113,7 +113,7 @@ GraphIterator& GraphIterator::operator++() { // Traverse to the first upstream edge of this element. _stack.emplace_back(_upstreamElem, 0); - Edge nextEdge = _upstreamElem->getUpstreamEdge(_material, 0); + Edge nextEdge = _upstreamElem->getUpstreamEdge(0); if (nextEdge && nextEdge.getUpstreamElement()) { extendPathUpstream(nextEdge.getUpstreamElement(), nextEdge.getConnectingElement()); @@ -140,7 +140,7 @@ GraphIterator& GraphIterator::operator++() StackFrame& parentFrame = _stack.back(); if (parentFrame.second + 1 < parentFrame.first->getUpstreamEdgeCount()) { - Edge nextEdge = parentFrame.first->getUpstreamEdge(_material, ++parentFrame.second); + Edge nextEdge = parentFrame.first->getUpstreamEdge(++parentFrame.second); if (nextEdge && nextEdge.getUpstreamElement()) { extendPathUpstream(nextEdge.getUpstreamElement(), nextEdge.getConnectingElement()); diff --git a/source/MaterialXCore/Traversal.h b/source/MaterialXCore/Traversal.h index 9353080256..7953d1965c 100644 --- a/source/MaterialXCore/Traversal.h +++ b/source/MaterialXCore/Traversal.h @@ -194,9 +194,8 @@ class TreeIterator class GraphIterator { public: - explicit GraphIterator(ElementPtr elem, ConstMaterialPtr material = nullptr): + explicit GraphIterator(ElementPtr elem): _upstreamElem(elem), - _material(material), _prune(false), _holdCount(0) { @@ -212,7 +211,6 @@ class GraphIterator bool operator==(const GraphIterator& rhs) const { return _upstreamElem == rhs._upstreamElem && - _material == rhs._material && _stack == rhs._stack && _prune == rhs._prune; } @@ -326,7 +324,6 @@ class GraphIterator ElementPtr _upstreamElem; ElementPtr _connectingElem; ElementSet _pathElems; - ConstMaterialPtr _material; vector _stack; bool _prune; size_t _holdCount; diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 956da74ed6..07796211b5 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -150,11 +150,11 @@ void ShaderGraph::createConnectedNodes(const ElementPtr& downstreamElement, } } -void ShaderGraph::addUpstreamDependencies(const Element& root, ConstMaterialPtr material, GenContext& context) +void ShaderGraph::addUpstreamDependencies(const Element& root, GenContext& context) { std::set processedOutputs; - for (Edge edge : root.traverseGraph(material)) + for (Edge edge : root.traverseGraph()) { ElementPtr upstreamElement = edge.getUpstreamElement(); if (!upstreamElement) @@ -418,7 +418,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const NodeGraph& n // Traverse all outputs and create all internal nodes for (OutputPtr graphOutput : nodeGraph.getActiveOutputs()) { - graph->addUpstreamDependencies(*graphOutput, nullptr, context); + graph->addUpstreamDependencies(*graphOutput, context); } // Add classification according to last node @@ -437,8 +437,7 @@ ShaderGraphPtr ShaderGraph::createSurfaceShader( const ShaderGraph* parent, NodePtr node, GenContext& context, - ElementPtr& root, - MaterialPtr& material) + ElementPtr& root) { NodeDefPtr nodeDef = node->getNodeDef(); if (!nodeDef) @@ -575,7 +574,6 @@ ShaderGraphPtr ShaderGraph::createSurfaceShader( // Start traversal from this shader node root = node; - material = nullptr; // node->getParent()->asA(); -- send over material node instead? return graph; } @@ -584,7 +582,6 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name { ShaderGraphPtr graph; ElementPtr root; - MaterialPtr material; if (element->isA()) { @@ -646,8 +643,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name // Handle shader nodes different from other nodes if (node->getType() == SURFACE_SHADER_TYPE_STRING) { - graph = createSurfaceShader(name, parent, node, context, - root, material); + graph = createSurfaceShader(name, parent, node, context, root); } else { @@ -743,7 +739,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name // Traverse and create all dependencies upstream if (root && context.getOptions().addUpstreamDependencies) { - graph->addUpstreamDependencies(*root, material, context); + graph->addUpstreamDependencies(*root, context); } // Add classification according to root node diff --git a/source/MaterialXGenShader/ShaderGraph.h b/source/MaterialXGenShader/ShaderGraph.h index a061d9868b..79a63855e6 100644 --- a/source/MaterialXGenShader/ShaderGraph.h +++ b/source/MaterialXGenShader/ShaderGraph.h @@ -112,8 +112,7 @@ class ShaderGraph : public ShaderNode const ShaderGraph* parent, NodePtr node, GenContext& context, - ElementPtr& root, - MaterialPtr& material); + ElementPtr& root); /// Create node connections corresponding to the connection between a pair of elements. /// @param downstreamElement Element representing the node to connect to. @@ -137,7 +136,7 @@ class ShaderGraph : public ShaderNode /// Traverse from the given root element and add all dependencies upstream. /// The traversal is done in the context of a material, if given, to include /// bind input elements in the traversal. - void addUpstreamDependencies(const Element& root, ConstMaterialPtr material, GenContext& context); + void addUpstreamDependencies(const Element& root, GenContext& context); /// Add a default geometric node and connect to the given input. void addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geomprop, GenContext& context); diff --git a/source/MaterialXGenShader/ShaderTranslator.cpp b/source/MaterialXGenShader/ShaderTranslator.cpp index 5a4294015b..a4e02a7066 100644 --- a/source/MaterialXGenShader/ShaderTranslator.cpp +++ b/source/MaterialXGenShader/ShaderTranslator.cpp @@ -5,9 +5,8 @@ #include +#include #include -#include - namespace MaterialX { diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index f8ae09a22d..9c89081a69 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -5,8 +5,6 @@ #include -#include - #include #include #include diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index c469f91209..630f2784de 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -4,7 +4,6 @@ // #include -#include #include #include @@ -437,17 +436,14 @@ ListofBakedDocuments TextureBaker::bakeAllMaterials(DocumentPtr doc, const FileS for (const string& renderablePath : renderablePaths) { ElementPtr elem = doc->getDescendant(renderablePath); - if (!elem) + if (!elem || !elem->isA()) { continue; } - NodePtr materialPtr = elem->asA(); - NodePtr shaderNode = nullptr; - if (materialPtr) - { - std::unordered_set shaderNodes = getShaderNodes(materialPtr); - shaderNode = shaderNodes.empty() ? nullptr : *shaderNodes.begin(); - } + NodePtr materialNode = elem->asA(); + + std::unordered_set shaderNodes = getShaderNodes(materialNode); + NodePtr shaderNode = shaderNodes.empty() ? nullptr : *shaderNodes.begin(); if (!shaderNode) { continue; @@ -483,7 +479,7 @@ ListofBakedDocuments TextureBaker::bakeAllMaterials(DocumentPtr doc, const FileS resolver->setUdimString(tag); imageHandler->setFilenameResolver(resolver); setImageHandler(imageHandler); - bakeShaderInputs(materialPtr, shaderNode, genContext, tag); + bakeShaderInputs(materialNode, shaderNode, genContext, tag); // Optimize baked textures. optimizeBakedTextures(shaderNode); diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp index 565cd271d1..d6fc383074 100644 --- a/source/MaterialXTest/MaterialXCore/Look.cpp +++ b/source/MaterialXTest/MaterialXCore/Look.cpp @@ -13,28 +13,14 @@ TEST_CASE("Look", "[look]") { mx::DocumentPtr doc = mx::createDocument(); - // Create a material and look. - mx::MaterialPtr material = doc->addMaterial(); + // Create a look. mx::LookPtr look = doc->addLook(); - REQUIRE(doc->getMaterials().size() == 1); REQUIRE(doc->getLooks().size() == 1); - // Bind the material to a geometry string. - mx::MaterialAssignPtr matAssign1 = look->addMaterialAssign("matAssign1", material->getName()); - matAssign1->setGeom("/robot1"); - REQUIRE(matAssign1->getReferencedMaterial() == material); - REQUIRE(material->getGeometryBindings("/robot1").size() == 1); - REQUIRE(material->getGeometryBindings("/robot2").size() == 0); - - // Bind the material to a geometric collection. - mx::MaterialAssignPtr matAssign2 = look->addMaterialAssign("matAssign2", material->getName()); + // Create a geometric collection. mx::CollectionPtr collection = doc->addCollection(); collection->setIncludeGeom("/robot2"); collection->setExcludeGeom("/robot2/left_arm"); - matAssign2->setCollection(collection); - REQUIRE(material->getGeometryBindings("/robot2").size() == 1); - REQUIRE(material->getGeometryBindings("/robot2/right_arm").size() == 1); - REQUIRE(material->getGeometryBindings("/robot2/left_arm").size() == 0); // Create a property assignment. mx::PropertyAssignPtr propertyAssign = look->addPropertyAssign(); @@ -76,7 +62,6 @@ TEST_CASE("Look", "[look]") // Create an inherited look. mx::LookPtr look2 = doc->addLook(); look2->setInheritsFrom(look); - REQUIRE(look2->getActiveMaterialAssigns().size() == 2); REQUIRE(look2->getActivePropertySetAssigns().size() == 1); REQUIRE(look2->getActiveVisibilities().size() == 1); @@ -88,7 +73,6 @@ TEST_CASE("Look", "[look]") // Disconnect the inherited look. look2->setInheritsFrom(nullptr); - REQUIRE(look2->getActiveMaterialAssigns().empty()); REQUIRE(look2->getActivePropertySetAssigns().empty()); REQUIRE(look2->getActiveVisibilities().empty()); } diff --git a/source/MaterialXTest/MaterialXCore/Node.cpp b/source/MaterialXTest/MaterialXCore/Node.cpp index e3dca0cd33..1e25534a44 100644 --- a/source/MaterialXTest/MaterialXCore/Node.cpp +++ b/source/MaterialXTest/MaterialXCore/Node.cpp @@ -23,7 +23,7 @@ bool isTopologicalOrder(const std::vector& elems) { for (size_t i = 0; i < elem->getUpstreamEdgeCount(); i++) { - mx::ElementPtr upstreamElem = elem->getUpstreamElement(nullptr, i); + mx::ElementPtr upstreamElem = elem->getUpstreamElement(i); if (upstreamElem && !prevElems.count(upstreamElem)) { return false; diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index 18fa5e5b43..10b55ddb6d 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -6,8 +6,7 @@ #include #include -#include -//#include +#include #include #include diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index 61cf93fcad..4e7e377b96 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -7,7 +7,6 @@ #include #include -#include #include diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 31c218e51b..3fd6666224 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index c376fb8b1b..c98748826f 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -25,13 +25,6 @@ void bindPyDocument(py::module& mod) .def("getNodeGraphs", &mx::Document::getNodeGraphs) .def("removeNodeGraph", &mx::Document::removeNodeGraph) .def("getMatchingPorts", &mx::Document::getMatchingPorts) - .def("addMaterial", &mx::Document::addMaterial, - py::arg("name") = mx::EMPTY_STRING) - .def("getMaterial", &mx::Document::getMaterial) - .def("getMaterials", &mx::Document::getMaterials) - .def("removeMaterial", &mx::Document::removeMaterial) - .def("getMaterialNode", &mx::Document::getMaterialNode) - .def("getMaterialNodes", &mx::Document::getMaterialNodes) .def("addGeomInfo", &mx::Document::addGeomInfo, py::arg("name") = mx::EMPTY_STRING, py::arg("geom") = mx::UNIVERSAL_GEOM_NAME) .def("getGeomInfo", &mx::Document::getGeomInfo) diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index 90e313c41c..40fd5be775 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -86,13 +86,12 @@ void bindPyElement(py::module& mod) .def("getRoot", static_cast(&mx::Element::getRoot)) .def("getDocument", static_cast(&mx::Element::getDocument)) .def("traverseTree", &mx::Element::traverseTree) - .def("traverseGraph", &mx::Element::traverseGraph, - py::arg("material") = nullptr) + .def("traverseGraph", &mx::Element::traverseGraph) .def("getUpstreamEdge", &mx::Element::getUpstreamEdge, - py::arg("material") = nullptr, py::arg("index") = 0) + py::arg("index") = 0) .def("getUpstreamEdgeCount", &mx::Element::getUpstreamEdgeCount) .def("getUpstreamElement", &mx::Element::getUpstreamElement, - py::arg("material") = nullptr, py::arg("index") = 0) + py::arg("index") = 0) .def("traverseInheritance", &mx::Element::traverseInheritance) .def("setSourceUri", &mx::Element::setSourceUri) .def("hasSourceUri", &mx::Element::hasSourceUri) @@ -117,7 +116,6 @@ void bindPyElement(py::module& mod) BIND_ELEMENT_FUNC_INSTANCE(GeomProp) BIND_ELEMENT_FUNC_INSTANCE(Implementation) BIND_ELEMENT_FUNC_INSTANCE(Look) - BIND_ELEMENT_FUNC_INSTANCE(Material) BIND_ELEMENT_FUNC_INSTANCE(MaterialAssign) BIND_ELEMENT_FUNC_INSTANCE(Node) BIND_ELEMENT_FUNC_INSTANCE(NodeDef) diff --git a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp index 3275a62948..8d2e64e988 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp @@ -63,7 +63,6 @@ void bindPyLook(py::module& mod) .def("getMaterial", &mx::MaterialAssign::getMaterial) .def("setExclusive", &mx::MaterialAssign::setExclusive) .def("getExclusive", &mx::MaterialAssign::getExclusive) - .def("getReferencedMaterial", &mx::MaterialAssign::getReferencedMaterial) .def("getReferencedMaterialNode", &mx::MaterialAssign::getReferencedMaterialNode) .def_readonly_static("CATEGORY", &mx::MaterialAssign::CATEGORY); @@ -80,4 +79,6 @@ void bindPyLook(py::module& mod) .def("setVisible", &mx::Visibility::setVisible) .def("getVisible", &mx::Visibility::getVisible) .def_readonly_static("CATEGORY", &mx::Visibility::CATEGORY); + + mod.def("getGeometryBindings", &mx::getGeometryBindings); } diff --git a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp index e00f0cf94b..5a56f169a7 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp @@ -6,7 +6,6 @@ #include #include -#include #include namespace py = pybind11; @@ -14,24 +13,8 @@ namespace mx = MaterialX; void bindPyMaterial(py::module& mod) { - py::class_(mod, "Material") - .def("getShaderNodeDefs", &mx::Material::getShaderNodeDefs, - py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) - .def("getPrimaryShaderNodeDef", &mx::Material::getPrimaryShaderNodeDef, - py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) - .def("getPrimaryShaderName", &mx::Material::getPrimaryShaderName, - py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) - .def("getPrimaryShaderInputs", &mx::Material::getPrimaryShaderInputs, - py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) - .def("getPrimaryShaderTokens", &mx::Material::getPrimaryShaderTokens, - py::arg("target") = mx::EMPTY_STRING, py::arg("type") = mx::EMPTY_STRING) - .def("getGeometryBindings", &mx::Material::getGeometryBindings, - py::arg("geom") = mx::UNIVERSAL_GEOM_NAME) - .def_readonly_static("CATEGORY", &mx::Material::CATEGORY); - mod.def("convertMaterialsToNodes", &mx::convertMaterialsToNodes); mod.def("getShaderNodes", &mx::getShaderNodes); - mod.def("getGeometryBindings", &mx::getGeometryBindings); mod.def("getConnectedOutputs", &mx::getConnectedOutputs); } diff --git a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp index c5ac923639..115c967b2d 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp @@ -35,6 +35,8 @@ void bindPyNode(py::module& mod) .def("getNodes", &mx::GraphElement::getNodes, py::arg("category") = mx::EMPTY_STRING) .def("removeNode", &mx::GraphElement::removeNode) + .def("getMaterialNode", &mx::GraphElement::getMaterialNode) + .def("getMaterialNodes", &mx::GraphElement::getMaterialNodes) .def("addBackdrop", &mx::GraphElement::addBackdrop, py::arg("name") = mx::EMPTY_STRING) .def("getBackdrop", &mx::GraphElement::getBackdrop) From 340d957b106227b37174ac6ffa01f9a7f220a3cc Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 28 Nov 2020 15:59:15 -0800 Subject: [PATCH 14/35] Additional material unit tests --- source/MaterialXCore/Element.cpp | 6 --- source/MaterialXCore/Element.h | 3 +- source/MaterialXCore/Node.cpp | 43 +++++++++++++++++++ source/MaterialXCore/Node.h | 17 +++++--- .../MaterialXTest/MaterialXCore/Document.cpp | 30 +++++++++---- .../MaterialXTest/MaterialXCore/Material.cpp | 6 +-- source/PyMaterialX/PyMaterialXCore/PyNode.cpp | 4 +- 7 files changed, 85 insertions(+), 24 deletions(-) diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 555d70e539..917baa1e0c 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -496,12 +496,6 @@ string ValueElement::getResolvedValueString(StringResolverPtr resolver) const ValuePtr ValueElement::getDefaultValue() const { - if (hasValue()) - { - return getValue(); - } - - // Return the value, if any, stored in our declaration. ConstElementPtr parent = getParent(); ConstInterfaceElementPtr interface = parent ? parent->asA() : nullptr; if (interface) diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index c91a2330b2..0dc2579f43 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -1070,7 +1070,8 @@ class ValueElement : public TypedElement return Value::createValueFromStrings(getResolvedValueString(resolver), getType()); } - /// Return the default value for this element. + /// Return the default value for this element as a generic value object, which + /// may be queried to access its data. /// /// @return A shared pointer to a typed value, or an empty shared pointer if /// no default value was found. diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index a0ad6b6321..45e8494481 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -65,6 +65,30 @@ string Node::getConnectedNodeName(const string& inputName) const return input->getNodeName(); } +void Node::setConnectedOutput(const string& inputName, OutputPtr output) +{ + InputPtr input = getInput(inputName); + if (!input) + { + input = addInput(inputName, DEFAULT_TYPE_STRING); + } + if (output) + { + input->setType(output->getType()); + } + input->setConnectedOutput(output); +} + +OutputPtr Node::getConnectedOutput(const string& inputName) const +{ + InputPtr input = getInput(inputName); + if (!input) + { + return OutputPtr(); + } + return input->getConnectedOutput(); +} + NodeDefPtr Node::getNodeDef(const string& target) const { if (hasNodeDefString()) @@ -169,6 +193,25 @@ bool Node::validate(string* message) const // GraphElement methods // +NodePtr GraphElement::addMaterialNode(const string& name, ConstNodePtr shaderNode) +{ + string category = SURFACE_MATERIAL_NODE_STRING; + if (shaderNode) + { + if (shaderNode->getType() == VOLUME_MATERIAL_NODE_STRING) + { + category = VOLUME_SHADER_TYPE_STRING; + } + } + NodePtr materialNode = addNode(category, name, MATERIAL_TYPE_STRING); + if (shaderNode) + { + InputPtr input = materialNode->addInput(shaderNode->getType(), shaderNode->getType()); + input->setNodeName(shaderNode->getName()); + } + return materialNode; +} + void GraphElement::flattenSubgraphs(const string& target, NodePredicate filter) { vector processNodeVec = getNodes(); diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index 3ec879aaa8..a31fba6c5e 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -79,6 +79,15 @@ class Node : public InterfaceElement /// input is not present, then an empty string is returned. string getConnectedNodeName(const string& inputName) const; + /// Set the output to which the given input is connected, creating a + /// child input if needed. If the node argument is null, then any + /// existing output connection on the input will be cleared. + void setConnectedOutput(const string& inputName, OutputPtr output); + + /// Return the output connected to the given input. If the given input is + /// not present, then an empty OutputPtr is returned. + OutputPtr getConnectedOutput(const string& inputName) const; + /// @} /// @name NodeDef References /// @{ @@ -241,11 +250,9 @@ class GraphElement : public InterfaceElement /// @name Material Nodes /// @{ - /// Return the material node, if any, with the given name. - NodePtr getMaterialNode(const string& name) const - { - return getNode(name); - } + /// Add a material node to the graph, optionally connecting it to the given + /// shader node. + NodePtr addMaterialNode(const string& name = EMPTY_STRING, ConstNodePtr shaderNode = nullptr); /// Return a vector of all material nodes. vector getMaterialNodes() const diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index 27d6d50eca..fccfa1193c 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -46,14 +46,28 @@ TEST_CASE("Document", "[document]") REQUIRE(nodeGraph->getDescendant("missingNode") == mx::ElementPtr()); // Create a simple shader interface. - mx::NodeDefPtr shader = doc->addNodeDef("", "surfaceshader", "simpleSrf"); - mx::InputPtr diffColor = shader->addInput("diffColor", "color3"); - REQUIRE(!diffColor->getIsUniform()); - mx::InputPtr specColor = shader->addInput("specColor", "color3", true); - REQUIRE(specColor->getIsUniform()); - specColor->setIsUniform(false); - REQUIRE(!specColor->getIsUniform()); - mx::InputPtr roughness = shader->addInput("roughness", "float"); + mx::NodeDefPtr simpleSrf = doc->addNodeDef("", "surfaceshader", "simpleSrf"); + simpleSrf->setInputValue("diffColor", mx::Color3(1.0f)); + simpleSrf->setInputValue("specColor", mx::Color3(0.0f)); + mx::InputPtr roughness = simpleSrf->setInputValue("roughness", 0.25f); + REQUIRE(!roughness->getIsUniform()); + roughness->setIsUniform(true); + REQUIRE(roughness->getIsUniform()); + + // Instantiate the interface as shader and material nodes. + mx::NodePtr shaderNode = doc->addNodeInstance(simpleSrf); + mx::NodePtr materialNode = doc->addMaterialNode("", shaderNode); + REQUIRE(materialNode->getUpstreamElement() == shaderNode); + + // Bind the diffuse color input to the constant color output. + shaderNode->setConnectedOutput("diffColor", output); + REQUIRE(shaderNode->getUpstreamElement() == constant); + REQUIRE(doc->validate()); + + // Bind the roughness input to a value. + mx::InputPtr instanceRoughness = shaderNode->setInputValue("roughness", 0.5f); + REQUIRE(instanceRoughness->getValue()->asA() == 0.5f); + REQUIRE(instanceRoughness->getDefaultValue()->asA() == 0.25f); // Create a collection mx::CollectionPtr collection = doc->addCollection(); diff --git a/source/MaterialXTest/MaterialXCore/Material.cpp b/source/MaterialXTest/MaterialXCore/Material.cpp index a6d27a5a02..b8606db801 100644 --- a/source/MaterialXTest/MaterialXCore/Material.cpp +++ b/source/MaterialXTest/MaterialXCore/Material.cpp @@ -17,9 +17,9 @@ TEST_CASE("Material", "[material]") // Create a base shader nodedef. mx::NodeDefPtr simpleSrf = doc->addNodeDef("ND_simpleSrf", "surfaceshader", "simpleSrf"); simpleSrf->setInputValue("diffColor", mx::Color3(1.0f)); - mx::InputPtr specColor = simpleSrf->setInputValue("specColor", mx::Color3(0.0f)); - mx::InputPtr roughness = simpleSrf->setInputValue("roughness", 0.25f); - mx::TokenPtr texId = simpleSrf->setTokenValue("texId", "01"); + simpleSrf->setInputValue("specColor", mx::Color3(0.0f)); + simpleSrf->setInputValue("roughness", 0.25f); + simpleSrf->setTokenValue("texId", "01"); REQUIRE(simpleSrf->getInputValue("diffColor")->asA() == mx::Color3(1.0f)); REQUIRE(simpleSrf->getInputValue("specColor")->asA() == mx::Color3(0.0f)); REQUIRE(simpleSrf->getInputValue("roughness")->asA() == 0.25f); diff --git a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp index 115c967b2d..7c3652e95e 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp @@ -19,6 +19,8 @@ void bindPyNode(py::module& mod) .def("getConnectedNode", &mx::Node::getConnectedNode) .def("setConnectedNodeName", &mx::Node::setConnectedNodeName) .def("getConnectedNodeName", &mx::Node::getConnectedNodeName) + .def("setConnectedOutput", &mx::Node::setConnectedOutput) + .def("getConnectedOutput", &mx::Node::getConnectedOutput) .def("getNodeDef", &mx::Node::getNodeDef, py::arg("target") = mx::EMPTY_STRING) .def("getImplementation", &mx::Node::getImplementation, @@ -35,7 +37,7 @@ void bindPyNode(py::module& mod) .def("getNodes", &mx::GraphElement::getNodes, py::arg("category") = mx::EMPTY_STRING) .def("removeNode", &mx::GraphElement::removeNode) - .def("getMaterialNode", &mx::GraphElement::getMaterialNode) + .def("addMaterialNode", &mx::GraphElement::addMaterialNode) .def("getMaterialNodes", &mx::GraphElement::getMaterialNodes) .def("addBackdrop", &mx::GraphElement::addBackdrop, py::arg("name") = mx::EMPTY_STRING) From 9c5dc54ad677ea041d065fd786681578600babb2 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sun, 29 Nov 2020 13:23:40 -0800 Subject: [PATCH 15/35] Initial look unit tests - Add initial C++ unit tests for looks and material assignments. - Extend material and look unit tests to Python. - Rename Look::getReferencedMaterialNode to Look::getReferencedMaterial for simplicity. --- python/MaterialXTest/main.py | 50 +++++++++++++++---- source/MaterialXCore/Look.cpp | 4 +- source/MaterialXCore/Look.h | 6 +-- .../MaterialXTest/MaterialXCore/Document.cpp | 1 - source/MaterialXTest/MaterialXCore/Look.cpp | 19 +++++-- source/PyMaterialX/PyMaterialXCore/PyLook.cpp | 2 +- 6 files changed, 61 insertions(+), 21 deletions(-) diff --git a/python/MaterialXTest/main.py b/python/MaterialXTest/main.py index 9b7943f55f..d68759e466 100644 --- a/python/MaterialXTest/main.py +++ b/python/MaterialXTest/main.py @@ -221,10 +221,6 @@ def test_BuildDocument(self): custom.setInputValue('octaves', 5) self.assertTrue(custom.getInputValue('octaves') == 5) - # Validate the document. - valid, message = doc.validate() - self.assertTrue(valid, 'Document returned validation warnings: ' + message) - # Test scoped attributes. nodeGraph.setFilePrefix('folder/') nodeGraph.setColorSpace('lin_rec709') @@ -232,20 +228,48 @@ def test_BuildDocument(self): self.assertTrue(constant.getActiveColorSpace() == 'lin_rec709') # Create a simple shader interface. - shaderDef = doc.addNodeDef('shader1', 'surfaceshader', 'simpleSrf') - diffColor = shaderDef.setInputValue('diffColor', mx.Color3(1.0)) - specColor = shaderDef.setInputValue('specColor', mx.Color3(0.0)) - roughness = shaderDef.setInputValue('roughness', 0.25) - texId = shaderDef.setTokenValue('texId', '01') - self.assertTrue(roughness.getValue() == 0.25) + simpleSrf = doc.addNodeDef('', 'surfaceshader', 'simpleSrf') + simpleSrf.setInputValue('diffColor', mx.Color3(1.0)) + simpleSrf.setInputValue('specColor', mx.Color3(0.0)) + roughness = simpleSrf.setInputValue('roughness', 0.25) self.assertTrue(roughness.getIsUniform() == False) roughness.setIsUniform(True); self.assertTrue(roughness.getIsUniform() == True) - # Create a look. + # Instantiate shader and material nodes. + shaderNode = doc.addNodeInstance(simpleSrf) + materialNode = doc.addMaterialNode('', shaderNode) + + # Bind the diffuse color input to the constant color output. + shaderNode.setConnectedOutput('diffColor', output1) + self.assertTrue(shaderNode.getUpstreamElement() == constant) + + # Bind the roughness input to a value. + instanceRoughness = shaderNode.setInputValue('roughness', 0.5) + self.assertTrue(instanceRoughness.getValue() == 0.5) + self.assertTrue(instanceRoughness.getDefaultValue() == 0.25) + + # Create a look for the material. look = doc.addLook() self.assertTrue(len(doc.getLooks()) == 1) + # Bind the material to a geometry string. + matAssign1 = look.addMaterialAssign("matAssign1", materialNode.getName()) + matAssign1.setGeom("/robot1") + self.assertTrue(matAssign1.getReferencedMaterial() == materialNode) + self.assertTrue(len(mx.getGeometryBindings(materialNode, "/robot1")) == 1) + self.assertTrue(len(mx.getGeometryBindings(materialNode, "/robot2")) == 0) + + # Bind the material to a collection. + matAssign2 = look.addMaterialAssign("matAssign2", materialNode.getName()) + collection = doc.addCollection() + collection.setIncludeGeom("/robot2") + collection.setExcludeGeom("/robot2/left_arm") + matAssign2.setCollection(collection) + self.assertTrue(len(mx.getGeometryBindings(materialNode, "/robot2")) == 1) + self.assertTrue(len(mx.getGeometryBindings(materialNode, "/robot2/right_arm")) == 1) + self.assertTrue(len(mx.getGeometryBindings(materialNode, "/robot2/left_arm")) == 0) + # Create a property assignment. propertyAssign = look.addPropertyAssign() propertyAssign.setProperty("twosided") @@ -271,6 +295,10 @@ def test_BuildDocument(self): variantSet.addVariant("damaged") self.assertTrue(len(variantSet.getVariants()) == 2) + # Validate the document. + valid, message = doc.validate() + self.assertTrue(valid, 'Document returned validation warnings: ' + message) + # Disconnect outputs from sources. output1.setConnectedNode(None) output2.setConnectedNode(None) diff --git a/source/MaterialXCore/Look.cpp b/source/MaterialXCore/Look.cpp index f3517e3152..ae0e272a6c 100644 --- a/source/MaterialXCore/Look.cpp +++ b/source/MaterialXCore/Look.cpp @@ -28,7 +28,7 @@ vector getGeometryBindings(const NodePtr& materialNode, const { for (MaterialAssignPtr matAssign : look->getMaterialAssigns()) { - if (matAssign->getReferencedMaterialNode() == materialNode) + if (matAssign->getReferencedMaterial() == materialNode) { if (geomStringsMatch(geom, matAssign->getActiveGeom())) { @@ -120,7 +120,7 @@ vector Look::getActiveVisibilities() const // MaterialAssign methods // -NodePtr MaterialAssign::getReferencedMaterialNode() const +NodePtr MaterialAssign::getReferencedMaterial() const { return resolveRootNameReference(getMaterial()); } diff --git a/source/MaterialXCore/Look.h b/source/MaterialXCore/Look.h index c09ed9aeec..1a32a95e63 100644 --- a/source/MaterialXCore/Look.h +++ b/source/MaterialXCore/Look.h @@ -63,7 +63,7 @@ class Look : public Element /// If no name is specified, then a unique name will automatically be /// generated. /// @param material An optional material string, which should match the - /// name of the Material element to be assigned. + /// name of the material node to be assigned. /// @return A shared pointer to the new MaterialAssign. MaterialAssignPtr addMaterialAssign(const string& name = EMPTY_STRING, const string& material = EMPTY_STRING); @@ -333,8 +333,8 @@ class MaterialAssign : public GeomElement /// @name Material References /// @{ - /// Return the Material node, if any, referenced by the MaterialAssign. - NodePtr getReferencedMaterialNode() const; + /// Return the material node, if any, referenced by the MaterialAssign. + NodePtr getReferencedMaterial() const; /// @} /// @name VariantAssign Elements diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index fccfa1193c..f80fb59893 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -62,7 +62,6 @@ TEST_CASE("Document", "[document]") // Bind the diffuse color input to the constant color output. shaderNode->setConnectedOutput("diffColor", output); REQUIRE(shaderNode->getUpstreamElement() == constant); - REQUIRE(doc->validate()); // Bind the roughness input to a value. mx::InputPtr instanceRoughness = shaderNode->setInputValue("roughness", 0.5f); diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp index d6fc383074..5afbf49f11 100644 --- a/source/MaterialXTest/MaterialXCore/Look.cpp +++ b/source/MaterialXTest/MaterialXCore/Look.cpp @@ -13,14 +13,27 @@ TEST_CASE("Look", "[look]") { mx::DocumentPtr doc = mx::createDocument(); - // Create a look. + // Create a material and look. + mx::NodePtr shaderNode = doc->addNode("standard_surface", "", "surfaceshader"); + mx::NodePtr materialNode = doc->addMaterialNode("", shaderNode); mx::LookPtr look = doc->addLook(); - REQUIRE(doc->getLooks().size() == 1); - // Create a geometric collection. + // Bind the material to a geometry string. + mx::MaterialAssignPtr matAssign1 = look->addMaterialAssign("matAssign1", materialNode->getName()); + matAssign1->setGeom("/robot1"); + REQUIRE(matAssign1->getReferencedMaterial() == materialNode); + REQUIRE(getGeometryBindings(materialNode, "/robot1").size() == 1); + REQUIRE(getGeometryBindings(materialNode, "/robot2").size() == 0); + + // Bind the material to a geometric collection. + mx::MaterialAssignPtr matAssign2 = look->addMaterialAssign("matAssign2", materialNode->getName()); mx::CollectionPtr collection = doc->addCollection(); collection->setIncludeGeom("/robot2"); collection->setExcludeGeom("/robot2/left_arm"); + matAssign2->setCollection(collection); + REQUIRE(getGeometryBindings(materialNode, "/robot2").size() == 1); + REQUIRE(getGeometryBindings(materialNode, "/robot2/right_arm").size() == 1); + REQUIRE(getGeometryBindings(materialNode, "/robot2/left_arm").size() == 0); // Create a property assignment. mx::PropertyAssignPtr propertyAssign = look->addPropertyAssign(); diff --git a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp index 8d2e64e988..e0dd3b12ba 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp @@ -63,7 +63,7 @@ void bindPyLook(py::module& mod) .def("getMaterial", &mx::MaterialAssign::getMaterial) .def("setExclusive", &mx::MaterialAssign::setExclusive) .def("getExclusive", &mx::MaterialAssign::getExclusive) - .def("getReferencedMaterialNode", &mx::MaterialAssign::getReferencedMaterialNode) + .def("getReferencedMaterial", &mx::MaterialAssign::getReferencedMaterial) .def_readonly_static("CATEGORY", &mx::MaterialAssign::CATEGORY); py::class_(mod, "Visibility") From bfa2a8cda136774e9a128a22c9f31ac4f59c105e Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 2 Dec 2020 21:06:04 -0800 Subject: [PATCH 16/35] Add shared library build This changelist adds a Linux shared-library build to GitHub Actions CI. --- .github/workflows/build_linux.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 9a31ea6a4a..0c6f68ed12 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -20,7 +20,7 @@ jobs: compiler: gcc compiler_version: "5" python: 2.7 - cmake_config: -DMATERIALX_PYTHON_VERSION=2 + cmake_config: -DMATERIALX_PYTHON_VERSION=2 -DMATERIALX_BUILD_SHARED_LIBS=ON - name: Linux_GCC_6_Python37 os: ubuntu-latest @@ -77,6 +77,10 @@ jobs: run: cmake --build . --target install --config ${{env.config}} working-directory: build + - name: Update Library Path + if: runner.os == 'Linux' || runner.os == 'macOS' + run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/installed/lib" >> $GITHUB_ENV + - name: Upload Installed Package uses: actions/upload-artifact@v2 with: @@ -108,6 +112,6 @@ jobs: - name: Python Tests run: | - cmake -E chdir ../python/MaterialXTest python main.py - cmake -E chdir ../python/MaterialXTest python genshader.py - working-directory: build + python main.py + python genshader.py + working-directory: python/MaterialXTest From 16693d691deb93f33c697dc103c4276bcb5f3d76 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sun, 6 Dec 2020 20:06:43 -0800 Subject: [PATCH 17/35] Update development build to 1.37.4 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb134585d9..e9fe33a7f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Change Log +<<<<<<< HEAD ## [1.38] - Development ### Highlights ("v1.37.3_parameters_as_inputs" to "v1.38_adsk_development1") @@ -17,7 +18,9 @@ - Github actions support. - Plus changes up to 1.37.3. -## [1.37.3] - Development +## [1.37.4] - Development + +## [1.37.3] - 2020-11-24 ### Added - Added Render Transparency and Render Double-Sided options to the Advanced Settings panel of the viewer. From f5eccbcf87e3500da9813c4511bbbfc99aab45ff Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sun, 6 Dec 2020 21:19:22 -0800 Subject: [PATCH 18/35] OpenGL improvements for software rendering --- source/MaterialXRenderGlsl/CMakeLists.txt | 2 +- .../{GLUtilityContext.cpp => GLContext.cpp} | 18 +++---- .../{GLUtilityContext.h => GLContext.h} | 20 ++++---- source/MaterialXRenderGlsl/GLUtil.cpp | 23 +++++++++ source/MaterialXRenderGlsl/GLUtil.h | 21 ++++++++ source/MaterialXRenderGlsl/GlslProgram.cpp | 30 +++--------- source/MaterialXRenderGlsl/GlslProgram.h | 5 -- source/MaterialXRenderGlsl/GlslRenderer.cpp | 48 +++++++------------ source/MaterialXRenderGlsl/GlslRenderer.h | 7 +-- source/MaterialXView/Viewer.cpp | 13 ++--- source/MaterialXView/Viewer.h | 3 -- 11 files changed, 93 insertions(+), 97 deletions(-) rename source/MaterialXRenderGlsl/{GLUtilityContext.cpp => GLContext.cpp} (92%) rename source/MaterialXRenderGlsl/{GLUtilityContext.h => GLContext.h} (81%) create mode 100644 source/MaterialXRenderGlsl/GLUtil.cpp create mode 100644 source/MaterialXRenderGlsl/GLUtil.h diff --git a/source/MaterialXRenderGlsl/CMakeLists.txt b/source/MaterialXRenderGlsl/CMakeLists.txt index 4dbcfb9c37..8ad3300f31 100644 --- a/source/MaterialXRenderGlsl/CMakeLists.txt +++ b/source/MaterialXRenderGlsl/CMakeLists.txt @@ -5,7 +5,7 @@ assign_source_group("Source Files" ${materialx_source}) assign_source_group("Header Files" ${materialx_headers}) if(POLICY CMP0072) - cmake_policy(SET CMP0072 OLD) + cmake_policy(SET CMP0072 NEW) endif() if(APPLE) diff --git a/source/MaterialXRenderGlsl/GLUtilityContext.cpp b/source/MaterialXRenderGlsl/GLContext.cpp similarity index 92% rename from source/MaterialXRenderGlsl/GLUtilityContext.cpp rename to source/MaterialXRenderGlsl/GLContext.cpp index b85bcdfa13..9a34cdf503 100644 --- a/source/MaterialXRenderGlsl/GLUtilityContext.cpp +++ b/source/MaterialXRenderGlsl/GLContext.cpp @@ -18,7 +18,7 @@ #endif #include -#include +#include namespace MaterialX { @@ -26,7 +26,7 @@ namespace MaterialX // // Windows implementation // -GLUtilityContext::GLUtilityContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) : +GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) : _contextHandle(nullptr), _isValid(false) { @@ -74,7 +74,7 @@ GLUtilityContext::GLUtilityContext(const WindowWrapper& /*windowWrapper*/, Hardw } } -void GLUtilityContext::shareLists(HardwareContextHandle context) +void GLContext::shareLists(HardwareContextHandle context) { if (_isValid) { @@ -86,7 +86,7 @@ void GLUtilityContext::shareLists(HardwareContextHandle context) // // Linux context implementation // -GLUtilityContext::GLUtilityContext(const WindowWrapper& windowWrapper, +GLContext::GLContext(const WindowWrapper& windowWrapper, HardwareContextHandle sharedWithContext) { _isValid = false; @@ -230,7 +230,7 @@ GLUtilityContext::GLUtilityContext(const WindowWrapper& windowWrapper, // #elif defined(__APPLE__) -GLUtilityContext::GLUtilityContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) +GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) { _isValid = false; @@ -253,7 +253,7 @@ GLUtilityContext::GLUtilityContext(const WindowWrapper& /*windowWrapper*/, Hardw #endif // Destroy the startup context. -GLUtilityContext::~GLUtilityContext() +GLContext::~GLContext() { // Only do this portion if the context is valid if (_isValid) @@ -287,7 +287,7 @@ GLUtilityContext::~GLUtilityContext() } } -int GLUtilityContext::makeCurrent() +int GLContext::makeCurrent() { if (!_isValid) { @@ -314,9 +314,9 @@ int GLUtilityContext::makeCurrent() // // Creator // -GLUtilityContextPtr GLUtilityContext::create(const WindowWrapper& windowWrapper, HardwareContextHandle context) +GLContextPtr GLContext::create(const WindowWrapper& windowWrapper, HardwareContextHandle context) { - return std::shared_ptr(new GLUtilityContext(windowWrapper, context)); + return std::shared_ptr(new GLContext(windowWrapper, context)); } } diff --git a/source/MaterialXRenderGlsl/GLUtilityContext.h b/source/MaterialXRenderGlsl/GLContext.h similarity index 81% rename from source/MaterialXRenderGlsl/GLUtilityContext.h rename to source/MaterialXRenderGlsl/GLContext.h index 3f408b6f59..47349289a1 100644 --- a/source/MaterialXRenderGlsl/GLUtilityContext.h +++ b/source/MaterialXRenderGlsl/GLContext.h @@ -3,11 +3,11 @@ // All rights reserved. See LICENSE.txt for license. // -#ifndef MATERIALX_GLUTILITYCONTEXT_H -#define MATERIALX_GLUTILITYCONTEXT_H +#ifndef MATERIALX_GLCONTEXT_H +#define MATERIALX_GLCONTEXT_H /// @file -/// OpenGL utility context +/// OpenGL context class #include #include @@ -33,23 +33,23 @@ using HardwareContextHandle = void*; using HardwareContextHandle = void*; #endif -/// GLUtilityContext shared pointer -using GLUtilityContextPtr = std::shared_ptr; +/// GLContext shared pointer +using GLContextPtr = std::shared_ptr; -/// @class GLUtilityContext +/// @class GLContext /// Base OpenGL context singleton. /// Used as a utility context to perform OpenGL operations from, /// and context for resource sharing between contexts. /// -class GLUtilityContext +class GLContext { public: /// Create a utility context - static GLUtilityContextPtr create(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); + static GLContextPtr create(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); /// Default destructor - virtual ~GLUtilityContext(); + virtual ~GLContext(); /// Return OpenGL context handle HardwareContextHandle contextHandle() const @@ -78,7 +78,7 @@ class GLUtilityContext protected: /// Create the base context. A OpenGL context to share with can be passed in. - GLUtilityContext(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); + GLContext(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); #if defined(_WIN32) /// Offscreen window required for context operations diff --git a/source/MaterialXRenderGlsl/GLUtil.cpp b/source/MaterialXRenderGlsl/GLUtil.cpp new file mode 100644 index 0000000000..e082fe533b --- /dev/null +++ b/source/MaterialXRenderGlsl/GLUtil.cpp @@ -0,0 +1,23 @@ +// +// TM & (c) 2020 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd. +// All rights reserved. See LICENSE.txt for license. +// + +#include + +#include + +#include + +namespace MaterialX +{ + +void checkGlErrors(const string& context) +{ + for (GLenum error = glGetError(); error; error = glGetError()) + { + std::cerr << "OpenGL error " << context << ": " << std::to_string(error) << std::endl; + } +} + +} // namespace MaterialX diff --git a/source/MaterialXRenderGlsl/GLUtil.h b/source/MaterialXRenderGlsl/GLUtil.h new file mode 100644 index 0000000000..8f30ae77c0 --- /dev/null +++ b/source/MaterialXRenderGlsl/GLUtil.h @@ -0,0 +1,21 @@ +// +// TM & (c) 2020 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd. +// All rights reserved. See LICENSE.txt for license. +// + +#ifndef MATERIALX_GLUTIL_H +#define MATERIALX_GLUTIL_H + +/// @file +/// OpenGL utilities + +#include + +namespace MaterialX +{ + +void checkGlErrors(const string& context); + +} // namespace MaterialX + +#endif diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index a21a025f6e..5a129ef095 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -248,7 +249,7 @@ bool GlslProgram::bind() if (_programId > UNDEFINED_OPENGL_RESOURCE_ID) { glUseProgram(_programId); - checkErrors(); + checkGlErrors("after program bind"); return true; } return false; @@ -268,7 +269,7 @@ void GlslProgram::bindInputs(ViewHandlerPtr viewHandler, throw ExceptionShaderRenderError(errorType, errors); } - checkErrors(); + checkGlErrors("after program bind inputs"); // Parse for uniforms and attributes getUniformsList(); @@ -502,7 +503,7 @@ void GlslProgram::bindStreams(MeshPtr mesh) } } - checkErrors(); + checkGlErrors("after program bind streams"); } void GlslProgram::unbindGeometry() @@ -544,7 +545,7 @@ void GlslProgram::unbindGeometry() glDeleteVertexArrays(1, &_vertexArray); _vertexArray = GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID; - checkErrors(); + checkGlErrors("after program unbind geometry"); } ImagePtr GlslProgram::bindTexture(unsigned int uniformType, int uniformLocation, const FilePath& filePath, @@ -566,7 +567,7 @@ ImagePtr GlslProgram::bindTexture(unsigned int uniformType, int uniformLocation, glUniform1i(uniformLocation, textureLocation); } } - checkErrors(); + checkGlErrors("after program bind texture"); return image; } @@ -628,10 +629,8 @@ void GlslProgram::bindTextures(ImageHandlerPtr imageHandler) } } } - checkErrors(); } - void GlslProgram::bindLighting(LightHandlerPtr lightHandler, ImageHandlerPtr imageHandler) { if (!lightHandler) @@ -1039,8 +1038,6 @@ void GlslProgram::bindViewInformation(ViewHandlerPtr viewHandler) glUniformMatrix4fv(location, 1, false, viewProjWorld.data()); } } - - checkErrors(); } void GlslProgram::bindTimeAndFrame() @@ -1496,19 +1493,4 @@ void GlslProgram::printAttributes(std::ostream& outputStream) } } -void GlslProgram::checkErrors() -{ - StringVec errors; - - GLenum error; - while ((error = glGetError()) != GL_NO_ERROR) - { - errors.push_back("OpenGL error: " + std::to_string(error)); - } - if (!errors.empty()) - { - throw ExceptionShaderRenderError("OpenGL context error.", errors); - } -} - } // namespace MaterialX diff --git a/source/MaterialXRenderGlsl/GlslProgram.h b/source/MaterialXRenderGlsl/GlslProgram.h index 6ee150602a..7b779d0c7e 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.h +++ b/source/MaterialXRenderGlsl/GlslProgram.h @@ -234,11 +234,6 @@ class GlslProgram ImagePtr bindTexture(unsigned int uniformType, int uniformLocation, const FilePath& filePath, ImageHandlerPtr imageHandler, bool generateMipMaps, const ImageSamplingProperties& imageProperties); - /// Utility to check for OpenGL context errors. - /// Will throw an ExceptionShaderRenderError exception which will list of the errors found - /// if any errors encountered. - void checkErrors(); - /// Delete any currently created shader program void deleteProgram(); diff --git a/source/MaterialXRenderGlsl/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp index 5f0a6262a8..acd7a29e99 100644 --- a/source/MaterialXRenderGlsl/GlslRenderer.cpp +++ b/source/MaterialXRenderGlsl/GlslRenderer.cpp @@ -5,7 +5,8 @@ #include #include -#include +#include +#include #include #include @@ -107,7 +108,7 @@ void GlslRenderer::initialize() } // Create offscreen context - _context = GLUtilityContext::create(_window->windowWrapper(), nullptr); + _context = GLContext::create(_window->windowWrapper(), nullptr); if (!_context) { errors.push_back("Failed to create OpenGL context for testing."); @@ -297,7 +298,6 @@ void GlslRenderer::render() glDrawElements(GL_TRIANGLES, (GLsizei)indexData.size(), GL_UNSIGNED_INT, (void*)0); } } - checkErrors(); // Unbind resources _program->unbind(); @@ -326,18 +326,7 @@ ImagePtr GlslRenderer::captureImage() throw ExceptionShaderRenderError(errorType, errors); } - ImagePtr result = _frameBuffer->createColorImage(); - try - { - checkErrors(); - } - catch (ExceptionShaderRenderError& e) - { - errors.push_back("Failed to read color buffer back."); - errors.insert(std::end(errors), std::begin(e.errorLog()), std::end(e.errorLog())); - throw ExceptionShaderRenderError(errorType, errors); - } - return result; + return _frameBuffer->createColorImage(); } void GlslRenderer::saveImage(const FilePath& filePath, ConstImagePtr image, bool verticalFlip) @@ -352,21 +341,6 @@ void GlslRenderer::saveImage(const FilePath& filePath, ConstImagePtr image, bool } } -void GlslRenderer::checkErrors() -{ - StringVec errors; - - GLenum error; - while ((error = glGetError()) != GL_NO_ERROR) - { - errors.push_back("OpenGL error: " + std::to_string(error)); - } - if (errors.size()) - { - throw ExceptionShaderRenderError("OpenGL context error.", errors); - } -} - void GlslRenderer::drawScreenSpaceQuad() { const float QUAD_VERTICES[] = @@ -382,6 +356,10 @@ void GlslRenderer::drawScreenSpaceQuad() 1, 2, 3 }; + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); @@ -399,6 +377,16 @@ void GlslRenderer::drawScreenSpaceQuad() glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(QUAD_INDICES), QUAD_INDICES, GL_STATIC_DRAW); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + glBindVertexArray(GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID); + glBindBuffer(GL_ARRAY_BUFFER, GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID); + + glDeleteBuffers(1, &ebo); + glDeleteBuffers(1, &vbo); + glDeleteVertexArrays(1, &vao); + + checkGlErrors("after draw screen-space quad"); } void GlslRenderer::setClearColor(const Color4& clearColor) diff --git a/source/MaterialXRenderGlsl/GlslRenderer.h b/source/MaterialXRenderGlsl/GlslRenderer.h index ed9f91f4d8..722f878e85 100644 --- a/source/MaterialXRenderGlsl/GlslRenderer.h +++ b/source/MaterialXRenderGlsl/GlslRenderer.h @@ -17,7 +17,7 @@ namespace MaterialX { -using GLUtilityContextPtr = std::shared_ptr; +using GLContextPtr = std::shared_ptr; using SimpleWindowPtr = std::shared_ptr; /// Shared pointer to a GlslRenderer @@ -116,9 +116,6 @@ class GlslRenderer : public ShaderRenderer virtual void updateViewInformation(); virtual void updateWorldInformation(); - private: - void checkErrors(); - private: GlslProgramPtr _program; @@ -132,7 +129,7 @@ class GlslRenderer : public ShaderRenderer float _objectScale; SimpleWindowPtr _window; - GLUtilityContextPtr _context; + GLContextPtr _context; Color4 _clearColor; }; diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 3fd6666224..ecd0c19059 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -2024,7 +2025,7 @@ void Viewer::drawContents() updateViewHandlers(); - checkGlErrors("before viewer render"); + mx::checkGlErrors("before viewer render"); // Render a wedge for the current material. if (_wedgeRequested) @@ -2060,7 +2061,7 @@ void Viewer::drawContents() bakeTextures(); } - checkGlErrors("after viewer render"); + mx::checkGlErrors("after viewer render"); } bool Viewer::scrollEvent(const ng::Vector2i& p, const ng::Vector2f& rel) @@ -2462,11 +2463,3 @@ void Viewer::updateAlbedoTable() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDrawBuffer(GL_BACK); } - -void Viewer::checkGlErrors(const std::string& context) -{ - for (GLenum error = glGetError(); error; error = glGetError()) - { - std::cerr << "OpenGL error " << context << ": " << std::to_string(error) << std::endl; - } -} diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h index 0bb1c01183..799127e157 100644 --- a/source/MaterialXView/Viewer.h +++ b/source/MaterialXView/Viewer.h @@ -141,9 +141,6 @@ class Viewer : public ng::Screen /// Update the directional albedo table. void updateAlbedoTable(); - /// Check for any OpenGL errors that have been encountered. - void checkGlErrors(const std::string& context); - private: ng::Window* _window; ng::Arcball _arcball; From da83fa9cfe7888f96590badfb236b9d6379a4afa Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Mon, 7 Dec 2020 10:41:02 -0800 Subject: [PATCH 19/35] Add material baking to GitHub Actions CI --- .github/workflows/build_linux.yml | 56 +++++++++++++++++++++---------- python/Scripts/baketextures.py | 2 ++ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 0c6f68ed12..09ba849c7d 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -16,23 +16,24 @@ jobs: matrix: include: - name: Linux_GCC_5_Python27 - os: ubuntu-latest + os: ubuntu-18.04 compiler: gcc compiler_version: "5" python: 2.7 cmake_config: -DMATERIALX_PYTHON_VERSION=2 -DMATERIALX_BUILD_SHARED_LIBS=ON - name: Linux_GCC_6_Python37 - os: ubuntu-latest + os: ubuntu-18.04 compiler: gcc compiler_version: "6" python: 3.7 - name: Linux_GCC_10_Python37 - os: ubuntu-latest + os: ubuntu-18.04 compiler: gcc compiler_version: "10" python: 3.7 + test_render: ON runs-on: ${{matrix.os}} @@ -59,6 +60,12 @@ jobs: echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV fi + if [ "${{ matrix.test_render }}" = "ON" ]; then + sudo apt-get install xvfb + echo "MESA_GL_VERSION_OVERRIDE=4.0FC" >> $GITHUB_ENV + echo "MESA_GLSL_VERSION_OVERRIDE=400" >> $GITHUB_ENV + echo "GALLIUM_DRIVER=softpipe" >> $GITHUB_ENV + fi - name: Install Python ${{ matrix.python }} uses: actions/setup-python@v2 @@ -81,37 +88,50 @@ jobs: if: runner.os == 'Linux' || runner.os == 'macOS' run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/build/installed/lib" >> $GITHUB_ENV - - name: Upload Installed Package - uses: actions/upload-artifact@v2 - with: - name: MaterialX_${{matrix.name}} - path: build/installed/ - - name: CMake Unit Tests run: ctest -VV --output-on-failure --build-config ${{env.config}} working-directory: build + - name: Python Tests + run: | + python main.py + python genshader.py + working-directory: python/MaterialXTest + + - name: Material Baking Tests + if: matrix.test_render == 'ON' + run: | + mkdir build/baked + xvfb-run python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx build/baked/brass_tiled_baked.mtlx --path . + - name: Generate Test HTML - if: ${{matrix.generate_html == 'ON'}} + if: matrix.generate_html == 'ON' run: cmake -E chdir ../python/MaterialXTest python tests_to_html.py working-directory: build + - name: Upload Installed Package + uses: actions/upload-artifact@v2 + with: + name: MaterialX_${{matrix.name}} + path: build/installed/ + + - name: Upload Baked Materials + uses: actions/upload-artifact@v2 + if: matrix.test_render == 'ON' + with: + name: BakedMaterials + path: build/baked/ + - name: Upload Test HTML uses: actions/upload-artifact@v2 - if: ${{matrix.generate_html == 'ON'}} + if: matrix.generate_html == 'ON' with: name: MaterialX_${{matrix.name}}_test_html path: build/source/MaterialXTest/tests.html - name: Upload Test Images uses: actions/upload-artifact@v2 - if: ${{matrix.generate_html == 'ON'}} + if: matrix.generate_html == 'ON' with: name: MaterialX_${{matrix.name}}_test_images path: build/source/MaterialXTest/**/*.png - - - name: Python Tests - run: | - python main.py - python genshader.py - working-directory: python/MaterialXTest diff --git a/python/Scripts/baketextures.py b/python/Scripts/baketextures.py index 3691e59683..1df6c19138 100644 --- a/python/Scripts/baketextures.py +++ b/python/Scripts/baketextures.py @@ -5,6 +5,8 @@ import sys, os, argparse import MaterialX as mx +from MaterialX import PyMaterialXGenShader +from MaterialX import PyMaterialXGenGlsl from MaterialX import PyMaterialXRender as mx_render from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl From 1b381a411b8ae63395aa91cf1557625df13cd0d7 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 9 Dec 2020 12:42:38 -0800 Subject: [PATCH 20/35] Improved robustness in MaterialXRenderGlsl - Clarify the lifetime and ownership of WindowWrapper objects using shared pointers. - Improve alignment of OpenGL context management between platforms. - Minor formatting and comment updates for consistency and clarity. --- .github/workflows/build_linux.yml | 6 +- source/MaterialXRenderGlsl/GLContext.cpp | 115 ++++++++---------- source/MaterialXRenderGlsl/GLContext.h | 60 ++++----- source/MaterialXRenderGlsl/GlslRenderer.cpp | 5 +- source/MaterialXRenderHw/SimpleWindow.h | 40 +++--- .../MaterialXRenderHw/SimpleWindowLinux.cpp | 6 +- source/MaterialXRenderHw/SimpleWindowMac.cpp | 6 +- .../MaterialXRenderHw/SimpleWindowWindows.cpp | 10 +- .../MaterialXRenderHw/WindowCocoaWrappers.h | 2 +- .../MaterialXRenderHw/WindowCocoaWrappers.m | 2 +- source/MaterialXRenderHw/WindowWrapper.cpp | 113 +++-------------- source/MaterialXRenderHw/WindowWrapper.h | 66 ++++------ 12 files changed, 151 insertions(+), 280 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 09ba849c7d..5a3a649cbe 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -50,7 +50,7 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install libgl-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libx11-dev + sudo apt-get install libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev if [ "${{ matrix.compiler }}" = "gcc" ]; then sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV @@ -61,10 +61,10 @@ jobs: echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV fi if [ "${{ matrix.test_render }}" = "ON" ]; then - sudo apt-get install xvfb echo "MESA_GL_VERSION_OVERRIDE=4.0FC" >> $GITHUB_ENV echo "MESA_GLSL_VERSION_OVERRIDE=400" >> $GITHUB_ENV echo "GALLIUM_DRIVER=softpipe" >> $GITHUB_ENV + echo "RENDER_ENVIRONMENT=xvfb-run" >> $GITHUB_ENV fi - name: Install Python ${{ matrix.python }} @@ -102,7 +102,7 @@ jobs: if: matrix.test_render == 'ON' run: | mkdir build/baked - xvfb-run python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx build/baked/brass_tiled_baked.mtlx --path . + $RENDER_ENVIRONMENT python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx build/baked/brass_tiled_baked.mtlx --path . - name: Generate Test HTML if: matrix.generate_html == 'ON' diff --git a/source/MaterialXRenderGlsl/GLContext.cpp b/source/MaterialXRenderGlsl/GLContext.cpp index 9a34cdf503..7f3b16b240 100644 --- a/source/MaterialXRenderGlsl/GLContext.cpp +++ b/source/MaterialXRenderGlsl/GLContext.cpp @@ -22,20 +22,21 @@ namespace MaterialX { + #if defined(_WIN32) -// -// Windows implementation -// -GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) : + +GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedWithContext) : + _window(window), _contextHandle(nullptr), _isValid(false) { // For windows, we need a HDC to create an OpenGL context. - // Create a dummy 1x1 window and use it' HDC. - _dummyWindow.initialize("__GL_BASE_CONTEXT_DUMMY_WINDOW__", 1, 1, nullptr); - WindowWrapper dummyWindowWrapper = _dummyWindow.windowWrapper(); + // Create a dummy 1x1 window and use its HDC. + _window = SimpleWindow::create(); + _window->initialize("__GL_BASE_CONTEXT_DUMMY_WINDOW__", 1, 1, nullptr); + WindowWrapperPtr windowWrapper = _window->getWindowWrapper(); - if (dummyWindowWrapper.isValid()) + if (windowWrapper->isValid()) { // Use a generic pixel format to create the context static PIXELFORMATDESCRIPTOR pfd = @@ -50,12 +51,12 @@ GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHand 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; - int chosenPixelFormat = ChoosePixelFormat(dummyWindowWrapper.internalHandle(), &pfd); + int chosenPixelFormat = ChoosePixelFormat(windowWrapper->internalHandle(), &pfd); if (chosenPixelFormat) { - if (SetPixelFormat(dummyWindowWrapper.internalHandle(), chosenPixelFormat, &pfd)) + if (SetPixelFormat(windowWrapper->internalHandle(), chosenPixelFormat, &pfd)) { - _contextHandle = wglCreateContext(dummyWindowWrapper.internalHandle()); + _contextHandle = wglCreateContext(windowWrapper->internalHandle()); if (_contextHandle) { if (sharedWithContext) @@ -63,7 +64,7 @@ GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHand shareLists(sharedWithContext); } - int makeCurrentOk = wglMakeCurrent(dummyWindowWrapper.internalHandle(), _contextHandle); + int makeCurrentOk = wglMakeCurrent(windowWrapper->internalHandle(), _contextHandle); if (makeCurrentOk) { _isValid = true; @@ -83,21 +84,14 @@ void GLContext::shareLists(HardwareContextHandle context) } #elif defined(__linux__) -// -// Linux context implementation -// -GLContext::GLContext(const WindowWrapper& windowWrapper, - HardwareContextHandle sharedWithContext) -{ - _isValid = false; - - // - // Unix implementation - // - _windowWrapper = windowWrapper; +GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedWithContext) : + _window(window), + _contextHandle(nullptr), + _isValid(false) +{ // Get connection to X Server - _display = windowWrapper.getDisplay(); + _xDisplay = _window->getWindowWrapper()->getXDisplay(); // Load in OpenGL library void *libHandle = dlopen("libGL.so", RTLD_LAZY); @@ -161,7 +155,7 @@ GLContext::GLContext(const WindowWrapper& windowWrapper, list[i++] = GLX_STENCIL_SIZE; list[i++] = 8; list[i++] = None; - XVisualInfo *vinfo = ChooseVisualFuncPtr(_display, DefaultScreen(_display), list); + XVisualInfo *vinfo = ChooseVisualFuncPtr(_xDisplay, DefaultScreen(_xDisplay), list); if (vinfo == 0) { _contextHandle = 0; @@ -171,11 +165,11 @@ GLContext::GLContext(const WindowWrapper& windowWrapper, // Create context that shares display lists and texture objects across contexts if (sharedWithContext) { - _contextHandle = CreateContextFuncPtr(_display, vinfo, sharedWithContext, GL_TRUE); + _contextHandle = CreateContextFuncPtr(_xDisplay, vinfo, sharedWithContext, GL_TRUE); } else { - _contextHandle = CreateContextFuncPtr(_display, vinfo, 0, GL_TRUE); + _contextHandle = CreateContextFuncPtr(_xDisplay, vinfo, 0, GL_TRUE); } if (_contextHandle == 0) @@ -185,9 +179,8 @@ GLContext::GLContext(const WindowWrapper& windowWrapper, // For glX need a window to make the context created above current, creating // minimal requirements for an OpenGL window - - Window root = RootWindow(_display, DefaultScreen(_display)); - Colormap cmap = XCreateColormap(_display, root, vinfo->visual, AllocNone); + Window root = RootWindow(_xDisplay, DefaultScreen(_xDisplay)); + Colormap cmap = XCreateColormap(_xDisplay, root, vinfo->visual, AllocNone); XSetWindowAttributes wa; unsigned long attribMask; attribMask = CWBackPixmap | CWBorderPixel | CWColormap; @@ -196,9 +189,9 @@ GLContext::GLContext(const WindowWrapper& windowWrapper, wa.colormap = cmap; // Create an X window with the visual requested above - _dummyWindow = XCreateWindow(_display, root, 0, 0, 10, 10, 0, vinfo->depth, InputOutput, + _xWindow = XCreateWindow(_xDisplay, root, 0, 0, 10, 10, 0, vinfo->depth, InputOutput, vinfo->visual, attribMask, &wa); - if (_dummyWindow == 0) + if (_xWindow == 0) { _contextHandle = 0; return; @@ -210,30 +203,27 @@ GLContext::GLContext(const WindowWrapper& windowWrapper, bool haveOldContext = (NULL != oldContext); bool haveOldDrawable = (None != oldDrawable); - MakeCurrentFuncPtr(_display, _dummyWindow, _contextHandle); + MakeCurrentFuncPtr(_xDisplay, _xWindow, _contextHandle); - if (_display) + if (_xDisplay) { _isValid = true; - // Restore the previous context + // Restore the previous context. if (haveOldContext && haveOldDrawable) { - MakeCurrentFuncPtr(_display, oldDrawable, oldContext); - + MakeCurrentFuncPtr(_xDisplay, oldDrawable, oldContext); } } } -// -// OSX implementation -// #elif defined(__APPLE__) -GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHandle sharedWithContext) +GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedWithContext) : + _window(window), + _contextHandle(nullptr), + _isValid(false) { - _isValid = false; - void* pixelFormat = NSOpenGLChoosePixelFormatWrapper(true, 0, 32, 24, 8, 0, 0, false, false, false, false, false); if (!pixelFormat) @@ -243,46 +233,49 @@ GLContext::GLContext(const WindowWrapper& /*windowWrapper*/, HardwareContextHand // Create the context, but do not share against other contexts. // (Instead, all other contexts will share against this one.) - // _contextHandle = NSOpenGLCreateContextWrapper(pixelFormat, sharedWithContext); NSOpenGLReleasePixelFormat(pixelFormat); NSOpenGLMakeCurrent(_contextHandle); _isValid = true; } + #endif -// Destroy the startup context. GLContext::~GLContext() { // Only do this portion if the context is valid if (_isValid) { #if defined(_WIN32) + // Release the dummy context. wglDeleteContext(_contextHandle); #elif defined(__linux__) - glXMakeCurrent(_display, None, NULL); + + glXMakeCurrent(_xDisplay, None, NULL); // This needs to be done after all the GL object // created with this context are destroyed. if (_contextHandle != 0) { - glXDestroyContext(_display, _contextHandle); + glXDestroyContext(_xDisplay, _contextHandle); } - if (_dummyWindow != 0) + if (_xWindow != 0) { - XDestroyWindow(_display, _dummyWindow); + XDestroyWindow(_xDisplay, _xWindow); } #elif defined(__APPLE__) - // This needs to be done after all the GL object - // created with this context are destroyed. + + // This needs to be done after all the GL objects created with this + // context are destroyed. if (_contextHandle != 0) { NSOpenGLDestroyCurrentContext(&_contextHandle); } + #endif } } @@ -295,28 +288,20 @@ int GLContext::makeCurrent() } int makeCurrentOk = 0; + #if defined(_WIN32) - makeCurrentOk = wglMakeCurrent(_dummyWindow.windowWrapper().internalHandle(), _contextHandle); + makeCurrentOk = wglMakeCurrent(_window->getWindowWrapper()->internalHandle(), _contextHandle); #elif defined(__linux__) - makeCurrentOk = glXMakeCurrent(_display, _dummyWindow, _contextHandle); + makeCurrentOk = glXMakeCurrent(_xDisplay, _xWindow, _contextHandle); #elif defined(__APPLE__) NSOpenGLMakeCurrent(_contextHandle); if (NSOpenGLGetCurrentContextWrapper() == _contextHandle) { makeCurrentOk = 1; } -#else - ; #endif - return makeCurrentOk; -} -// -// Creator -// -GLContextPtr GLContext::create(const WindowWrapper& windowWrapper, HardwareContextHandle context) -{ - return std::shared_ptr(new GLContext(windowWrapper, context)); + return makeCurrentOk; } -} +} // namespace MaterialX diff --git a/source/MaterialXRenderGlsl/GLContext.h b/source/MaterialXRenderGlsl/GLContext.h index 47349289a1..fcad920dc6 100644 --- a/source/MaterialXRenderGlsl/GLContext.h +++ b/source/MaterialXRenderGlsl/GLContext.h @@ -9,12 +9,9 @@ /// @file /// OpenGL context class -#include -#include - -#if defined(_WIN32) #include -#elif defined(__APPLE__) + +#if defined(__APPLE__) #include #elif defined(__linux__) #include @@ -22,31 +19,32 @@ namespace MaterialX { + /// Platform dependent definition of a hardware context #if defined(_WIN32) using HardwareContextHandle = HGLRC; #elif defined(__linux__) using HardwareContextHandle = GLXContext; -#elif defined(__APPLE__) -using HardwareContextHandle = void*; #else using HardwareContextHandle = void*; #endif +/// SimpleWindow shared pointer +using SimpleWindowPtr = std::shared_ptr; + /// GLContext shared pointer using GLContextPtr = std::shared_ptr; /// @class GLContext -/// Base OpenGL context singleton. -/// Used as a utility context to perform OpenGL operations from, -/// and context for resource sharing between contexts. -/// +/// An OpenGL context singleton class GLContext { public: - - /// Create a utility context - static GLContextPtr create(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); + /// Create a new context + static GLContextPtr create(SimpleWindowPtr window, HardwareContextHandle context = {}) + { + return GLContextPtr(new GLContext(window, context)); + } /// Default destructor virtual ~GLContext(); @@ -57,11 +55,6 @@ class GLContext return _contextHandle; } -#if defined(__linux__) - /// Return X display associated with context - Display *display() const { return _display; } -#endif - /// Return if context is valid bool isValid() const { @@ -77,26 +70,25 @@ class GLContext #endif protected: - /// Create the base context. A OpenGL context to share with can be passed in. - GLContext(const WindowWrapper& windowWrapper, HardwareContextHandle context = 0); + // Create the base context. A OpenGL context to share with can be passed in. + GLContext(SimpleWindowPtr window, HardwareContextHandle context = 0); -#if defined(_WIN32) - /// Offscreen window required for context operations - SimpleWindow _dummyWindow; -#elif defined(__linux__) - /// Offscreen window required for context operations - Window _dummyWindow; - /// X Display used by context operations - Display *_display; - /// Window wrapper used by context operations - WindowWrapper _windowWrapper; -#endif + // Simple window + SimpleWindowPtr _window; - /// Context handle + // Context handle HardwareContextHandle _contextHandle; - /// Flag to indicate validity + // Flag to indicate validity bool _isValid; + +#if defined(__linux__) + // An X window used by context operations + Window _xWindow; + + // An X display used by context operations + Display* _xDisplay; +#endif }; } // namespace MaterialX diff --git a/source/MaterialXRenderGlsl/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp index acd7a29e99..9b25b581dd 100644 --- a/source/MaterialXRenderGlsl/GlslRenderer.cpp +++ b/source/MaterialXRenderGlsl/GlslRenderer.cpp @@ -100,15 +100,14 @@ void GlslRenderer::initialize() // Create window _window = SimpleWindow::create(); - const char* windowName = "Renderer Window"; - if (!_window->initialize(const_cast(windowName), _width, _height, nullptr)) + if (!_window->initialize("Renderer Window", _width, _height, nullptr)) { errors.push_back("Failed to create window for testing."); throw ExceptionShaderRenderError(errorType, errors); } // Create offscreen context - _context = GLContext::create(_window->windowWrapper(), nullptr); + _context = GLContext::create(_window); if (!_context) { errors.push_back("Failed to create OpenGL context for testing."); diff --git a/source/MaterialXRenderHw/SimpleWindow.h b/source/MaterialXRenderHw/SimpleWindow.h index 4a7ec45c41..4b028e9450 100644 --- a/source/MaterialXRenderHw/SimpleWindow.h +++ b/source/MaterialXRenderHw/SimpleWindow.h @@ -8,37 +8,30 @@ #include -#include - namespace MaterialX { /// SimpleWindow shared pointer using SimpleWindowPtr = std::shared_ptr; -/// /// @class SimpleWindow -/// A platform independent window class. Plaform specific resources -/// are encapsulated using a WindowWrapper instance. -/// +/// A platform-independent window class. +/// +/// Plaform-specific resources are encapsulated by a WindowWrapper instance. class SimpleWindow { public: /// Static instance create function - static SimpleWindowPtr create() { return std::make_shared(); } - - /// Default constructor - SimpleWindow(); + static SimpleWindowPtr create() { return SimpleWindowPtr(new SimpleWindow); } /// Default destructor virtual ~SimpleWindow(); /// Window initialization - bool initialize(char* title, unsigned int width, unsigned int height, - void *applicationShell); + bool initialize(const char* title, unsigned int width, unsigned int height, void *applicationShell); - /// Return windowing information for the window - const WindowWrapper& windowWrapper() + /// Return our platform-specific resource wrapper + WindowWrapperPtr getWindowWrapper() { return _windowWrapper; } @@ -58,33 +51,34 @@ class SimpleWindow /// Check for validity bool isValid() const { - return _windowWrapper.isValid(); + return _windowWrapper && _windowWrapper->isValid(); } protected: - /// Clear internal state information + // Default constructor + SimpleWindow(); + + // Clear internal state information void clearInternalState() { _width = _height = 0; _id = 0; } - /// Wrapper for platform specific window resources - WindowWrapper _windowWrapper; + // Wrapper for platform specific window resources + WindowWrapperPtr _windowWrapper; - /// Width of the window + // Window dimensions unsigned int _width; - /// Height of the window unsigned int _height; - /// Unique window identifier generated dynamically at creation time. + // Unique window identifier generated dynamically at creation time. unsigned int _id; #if defined(_WIN32) - /// Window class name for window generated at creation time. + // Window class name for window generated at creation time. char _windowClassName[128]; #endif - }; } // namespace MaterialX diff --git a/source/MaterialXRenderHw/SimpleWindowLinux.cpp b/source/MaterialXRenderHw/SimpleWindowLinux.cpp index f5d743e802..3e50c5b42a 100644 --- a/source/MaterialXRenderHw/SimpleWindowLinux.cpp +++ b/source/MaterialXRenderHw/SimpleWindowLinux.cpp @@ -26,7 +26,7 @@ SimpleWindow::SimpleWindow() windowCount++; } -bool SimpleWindow::initialize(char* title, +bool SimpleWindow::initialize(const char* title, unsigned int width, unsigned int height, void *applicationShell) { @@ -74,14 +74,14 @@ bool SimpleWindow::initialize(char* title, } XtRealizeWidget(widget); - _windowWrapper = WindowWrapper(widget, XtWindow(widget), XtDisplay(widget)); + _windowWrapper = WindowWrapper::create(widget, XtWindow(widget), XtDisplay(widget)); return true; } SimpleWindow::~SimpleWindow() { - Widget widget = _windowWrapper.externalHandle(); + Widget widget = _windowWrapper->externalHandle(); if (widget) { // Unrealize the widget first to avoid X calls to it diff --git a/source/MaterialXRenderHw/SimpleWindowMac.cpp b/source/MaterialXRenderHw/SimpleWindowMac.cpp index 708071b84b..8cc524c149 100644 --- a/source/MaterialXRenderHw/SimpleWindowMac.cpp +++ b/source/MaterialXRenderHw/SimpleWindowMac.cpp @@ -21,7 +21,7 @@ SimpleWindow::SimpleWindow() windowCount++; } -bool SimpleWindow::initialize(char* title, +bool SimpleWindow::initialize(const char* title, unsigned int width, unsigned int height, void* /*applicationShell*/) { @@ -30,13 +30,13 @@ bool SimpleWindow::initialize(char* title, { return false; } - _windowWrapper = WindowWrapper(win); + _windowWrapper = WindowWrapper::create(win); return true; } SimpleWindow::~SimpleWindow() { - void* hWnd = _windowWrapper.externalHandle(); + void* hWnd = _windowWrapper->externalHandle(); NSUtilDisposeWindow(hWnd); } diff --git a/source/MaterialXRenderHw/SimpleWindowWindows.cpp b/source/MaterialXRenderHw/SimpleWindowWindows.cpp index 298b712d55..ec9f68d7bc 100644 --- a/source/MaterialXRenderHw/SimpleWindowWindows.cpp +++ b/source/MaterialXRenderHw/SimpleWindowWindows.cpp @@ -41,7 +41,7 @@ LRESULT CALLBACK NoOpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } -bool SimpleWindow::initialize(char* title, +bool SimpleWindow::initialize(const char* title, unsigned int width, unsigned int height, void * /*applicationShell*/) { @@ -101,16 +101,18 @@ bool SimpleWindow::initialize(char* title, return false; } - _windowWrapper = WindowWrapper(hWnd, nullptr, nullptr); + _windowWrapper = WindowWrapper::create(hWnd); return true; } SimpleWindow::~SimpleWindow() { - HWND hWnd = _windowWrapper.externalHandle(); + HWND hWnd = _windowWrapper->externalHandle(); if (hWnd) - _windowWrapper.release(); + { + _windowWrapper->release(); + } DestroyWindow(hWnd); UnregisterClass(_windowClassName, GetModuleHandle(NULL)); diff --git a/source/MaterialXRenderHw/WindowCocoaWrappers.h b/source/MaterialXRenderHw/WindowCocoaWrappers.h index 975d80c49a..6de5c2b46e 100644 --- a/source/MaterialXRenderHw/WindowCocoaWrappers.h +++ b/source/MaterialXRenderHw/WindowCocoaWrappers.h @@ -14,7 +14,7 @@ extern "C" { #endif void* NSUtilGetView(void* pWindow); -void* NSUtilCreateWindow(unsigned int width, unsigned int height, char* title, bool batchMode); +void* NSUtilCreateWindow(unsigned int width, unsigned int height, const char* title, bool batchMode); void NSUtilShowWindow(void* pWindow); void NSUtilHideWindow(void* pWindow); void NSUtilSetFocus(void* pWindow); diff --git a/source/MaterialXRenderHw/WindowCocoaWrappers.m b/source/MaterialXRenderHw/WindowCocoaWrappers.m index 1e247541f6..b4e7676aae 100644 --- a/source/MaterialXRenderHw/WindowCocoaWrappers.m +++ b/source/MaterialXRenderHw/WindowCocoaWrappers.m @@ -16,7 +16,7 @@ return (void*)view; } -void* NSUtilCreateWindow(unsigned int width, unsigned int height, char* title, bool batchMode) +void* NSUtilCreateWindow(unsigned int width, unsigned int height, const char* title, bool batchMode) { // In batch mode, ensure that Cocoa is initialized if (batchMode) diff --git a/source/MaterialXRenderHw/WindowWrapper.cpp b/source/MaterialXRenderHw/WindowWrapper.cpp index 68ca565ffe..93aa31e1bb 100644 --- a/source/MaterialXRenderHw/WindowWrapper.cpp +++ b/source/MaterialXRenderHw/WindowWrapper.cpp @@ -15,15 +15,6 @@ namespace MaterialX { #if defined(_WIN32) -// -// Window platform code -// - -WindowWrapper::WindowWrapper() : - _externalHandle(0), - _internalHandle(0) -{ -} WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, InternalWindowHandle internalHandle, @@ -41,43 +32,6 @@ WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, } } -WindowWrapper::WindowWrapper(const WindowWrapper& other) -{ - _externalHandle = other._externalHandle; - if (_externalHandle && !other._internalHandle) - { - // Cache a HDC that corresponds to the window handle - _internalHandle = GetDC(_externalHandle); - } - else - { - _internalHandle = other._internalHandle; - } -} - -const WindowWrapper& WindowWrapper::operator=(const WindowWrapper& other) -{ - if (this == &other) - { - return *this; - } - - release(); - - _externalHandle = other._externalHandle; - if (_externalHandle && !other._internalHandle) - { - // Cache a HDC that corresponds to the window handle - _internalHandle = GetDC(_externalHandle); - } - else - { - _internalHandle = other._internalHandle; - } - - return *this; -} - WindowWrapper::~WindowWrapper() { release(); @@ -95,24 +49,12 @@ void WindowWrapper::release() } #elif defined(__linux__) -// -// Linux (X-specific) code -// - -// Default constructor. -WindowWrapper::WindowWrapper() : - _externalHandle(0), - _internalHandle(0), - _framebufferWindow(0), - _display(0) -{ -} WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, InternalWindowHandle internalHandle, DisplayHandle display) { - _display = display; + _xDisplay = display; _framebufferWindow = 0; _externalHandle = externalHandle; // Cache a pointer to the window. @@ -122,23 +64,6 @@ WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, _internalHandle = XtWindow(externalHandle); } -WindowWrapper::WindowWrapper(const WindowWrapper& other) -{ - _framebufferWindow = other._framebufferWindow; - _externalHandle = other._externalHandle; - _internalHandle = other._internalHandle; - _display = other._display; -} - -const WindowWrapper& WindowWrapper::operator=(const WindowWrapper& other) -{ - _framebufferWindow = other._framebufferWindow; - _externalHandle = other._externalHandle; - _internalHandle = other._internalHandle; - _display = other._display; - return *this; -} - WindowWrapper::~WindowWrapper() { release(); @@ -150,19 +75,10 @@ void WindowWrapper::release() _externalHandle = 0; _internalHandle = 0; _framebufferWindow = 0; - _display = 0; + _xDisplay = 0; } #elif defined(__APPLE__) -// -// OSX (Apple) specific code -// - -WindowWrapper::WindowWrapper() : - _externalHandle(0), - _internalHandle(0) -{ -} WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, InternalWindowHandle internalHandle, @@ -173,19 +89,6 @@ WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle, _internalHandle = NSUtilGetView(externalHandle); } -WindowWrapper::WindowWrapper(const WindowWrapper& other) -{ - _externalHandle = other._externalHandle; - _internalHandle = NSUtilGetView(_externalHandle); -} - -const WindowWrapper& WindowWrapper::operator=(const WindowWrapper& other) -{ - _externalHandle = other._externalHandle; - _internalHandle = NSUtilGetView(_externalHandle); - return *this; -} - WindowWrapper::~WindowWrapper() { release(); @@ -197,6 +100,18 @@ void WindowWrapper::release() _externalHandle = 0; _internalHandle = 0; } + #endif +// +// Creator +// + +WindowWrapperPtr WindowWrapper::create(ExternalWindowHandle externalHandle, + InternalWindowHandle internalHandle, + DisplayHandle display) +{ + return std::shared_ptr(new WindowWrapper(externalHandle, internalHandle, display)); +} + } // namespace MaterialX diff --git a/source/MaterialXRenderHw/WindowWrapper.h b/source/MaterialXRenderHw/WindowWrapper.h index 198a86a990..6dc1b7db0f 100644 --- a/source/MaterialXRenderHw/WindowWrapper.h +++ b/source/MaterialXRenderHw/WindowWrapper.h @@ -15,6 +15,8 @@ using Widget = struct _WidgetRec*; #endif +#include + namespace MaterialX { /// OS specific type windowing definitions @@ -48,35 +50,24 @@ using InternalWindowHandle = void*; using DisplayHandle = void*; #endif -/// +/// WindowWrapper shared pointer +using WindowWrapperPtr = std::shared_ptr; + /// @class WindowWrapper -/// Generic wrapper for encapsulating a "window" construct. -/// Each supported platform will have specific storage and management logic. +/// Generic wrapper for encapsulating a "window" construct /// +/// Each supported platform will have specific storage and management logic. class WindowWrapper { public: - /// Default constructor - WindowWrapper(); + /// Create a new WindowWrapper + static WindowWrapperPtr create(ExternalWindowHandle externalHandle = {}, + InternalWindowHandle internalHandle = {}, + DisplayHandle display = {}); - /// Default destructor + // Default destructor virtual ~WindowWrapper(); - /// Construct a wrapper using windowing information -#if defined(__linux__) - WindowWrapper(ExternalWindowHandle externalHandle, InternalWindowHandle internalHandle = 0, - DisplayHandle display = 0); -#else - WindowWrapper(ExternalWindowHandle externalHandle, InternalWindowHandle internalHandle = nullptr, - DisplayHandle display = 0); -#endif - - /// Copy constructor - WindowWrapper(const WindowWrapper& other); - - /// Assignment operator - const WindowWrapper& operator=(const WindowWrapper& other); - /// Return "external" handle ExternalWindowHandle externalHandle() const { @@ -90,33 +81,27 @@ class WindowWrapper } /// Check that there is a valid OS handle set. - /// It is sufficient to just check the internal handle + /// It is sufficient to just check the internal handle. bool isValid() const { return _internalHandle != 0; } -#if defined(__linux__) - /// Return frame buffer X window - Window getFrameBufferWindow() const - { - return _framebufferWindow; - } - - /// Set frame buffer X window - void setFrameBufferWindow(Window window) - { - _framebufferWindow = window; - } + /// Release resources stored in wrapper + void release(); - /// Rreturn X display - Display* getDisplay() const +#if defined(__linux__) + /// Return X display + Display* getXDisplay() const { - return _display; + return _xDisplay; } #endif - /// Release resources stored in wrapper - void release(); + + protected: + WindowWrapper(ExternalWindowHandle externalHandle, + InternalWindowHandle internalHandle, + DisplayHandle display); protected: ExternalWindowHandle _externalHandle; @@ -126,9 +111,8 @@ class WindowWrapper /// Window ID of framebuffer instance created in the wrapper Window _framebufferWindow; /// X Display - Display* _display; + Display* _xDisplay; #endif - }; } // namespace MaterialX From 9258b8dc9633d25a282f14e5543573d026d4f03a Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Thu, 10 Dec 2020 21:47:28 -0800 Subject: [PATCH 21/35] Make strings local to module This changelist makes two strings local to the ConvolutionNode module, in order to work around a compiler issue on Linux. --- source/MaterialXGenShader/Nodes/ConvolutionNode.cpp | 10 +++++++--- source/MaterialXGenShader/Nodes/ConvolutionNode.h | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp index 48eff80478..bc3240dd88 100644 --- a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp +++ b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp @@ -13,6 +13,13 @@ namespace MaterialX { +namespace { + +const string SAMPLE2D_INPUT = "texcoord"; +const string SAMPLE3D_INPUT = "position"; + +} // anonymous namespace + const std::array GAUSSIAN_KERNEL_3 = { 0.27901f, 0.44198f, 0.27901f // Sigma 1 @@ -26,9 +33,6 @@ const std::array GAUSSIAN_KERNEL_7 = 0.00598f, 0.060626f, 0.241843f, 0.383103f, 0.241843f, 0.060626f, 0.00598f // Sigma 1 }; -const string ConvolutionNode::SAMPLE2D_INPUT = "texcoord"; -const string ConvolutionNode::SAMPLE3D_INPUT = "position"; - ConvolutionNode::ConvolutionNode() { } diff --git a/source/MaterialXGenShader/Nodes/ConvolutionNode.h b/source/MaterialXGenShader/Nodes/ConvolutionNode.h index c8ca3847c2..e360ea71e4 100644 --- a/source/MaterialXGenShader/Nodes/ConvolutionNode.h +++ b/source/MaterialXGenShader/Nodes/ConvolutionNode.h @@ -48,9 +48,6 @@ class ConvolutionNode : public ShaderNodeImpl const string& sampleSizeFunctionUV, GenContext& context, ShaderStage& stage, StringVec& sampleStrings) const; - - static const string SAMPLE2D_INPUT; - static const string SAMPLE3D_INPUT; }; } // namespace MaterialX From 97da53fea35d62f6182cbbd5d5ed9410cd442181 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Thu, 10 Dec 2020 23:13:34 -0800 Subject: [PATCH 22/35] Additional improvements to MaterialXRenderGlsl - Simplify platform-specific logic in GLContext. - Add a null check to the Linux SimpleWindow destructor. - Remove a context-changing call from the GlslRenderer destructor. - Remove an unused header from the glew library. - Clarify an initializer in the GlslProgram constructor. --- .../External/GLew/OpenGL.h | 11 - source/MaterialXRenderGlsl/GLContext.cpp | 224 +++++------------- source/MaterialXRenderGlsl/GLContext.h | 5 - source/MaterialXRenderGlsl/GlslProgram.cpp | 8 +- source/MaterialXRenderGlsl/GlslProgram.h | 5 +- source/MaterialXRenderGlsl/GlslRenderer.cpp | 54 ++--- .../MaterialXRenderHw/SimpleWindowLinux.cpp | 6 +- 7 files changed, 91 insertions(+), 222 deletions(-) delete mode 100644 source/MaterialXRenderGlsl/External/GLew/OpenGL.h diff --git a/source/MaterialXRenderGlsl/External/GLew/OpenGL.h b/source/MaterialXRenderGlsl/External/GLew/OpenGL.h deleted file mode 100644 index 495441e6d6..0000000000 --- a/source/MaterialXRenderGlsl/External/GLew/OpenGL.h +++ /dev/null @@ -1,11 +0,0 @@ -#if defined(__APPLE__) - #include - #include -#elif defined(_WIN32) - #include - #include - #include -#else - #include - #include -#endif diff --git a/source/MaterialXRenderGlsl/GLContext.cpp b/source/MaterialXRenderGlsl/GLContext.cpp index 7f3b16b240..3bdcc9a906 100644 --- a/source/MaterialXRenderGlsl/GLContext.cpp +++ b/source/MaterialXRenderGlsl/GLContext.cpp @@ -4,16 +4,11 @@ // #if defined(_WIN32) -#include // For Windows calls - +#include #elif defined(__linux__) -#include // For dlopen -#include #include - #elif defined(__APPLE__) #include -#include #include #endif @@ -30,59 +25,49 @@ GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedW _contextHandle(nullptr), _isValid(false) { - // For windows, we need a HDC to create an OpenGL context. - // Create a dummy 1x1 window and use its HDC. - _window = SimpleWindow::create(); - _window->initialize("__GL_BASE_CONTEXT_DUMMY_WINDOW__", 1, 1, nullptr); + // Get the existing window wrapper. WindowWrapperPtr windowWrapper = _window->getWindowWrapper(); + if (!windowWrapper->isValid()) + { + return; + } - if (windowWrapper->isValid()) + // Use a generic pixel format to create the context + static PIXELFORMATDESCRIPTOR pfd = { - // Use a generic pixel format to create the context - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, - 32, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 - }; - - int chosenPixelFormat = ChoosePixelFormat(windowWrapper->internalHandle(), &pfd); - if (chosenPixelFormat) + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 + }; + + int chosenPixelFormat = ChoosePixelFormat(windowWrapper->internalHandle(), &pfd); + if (chosenPixelFormat) + { + if (SetPixelFormat(windowWrapper->internalHandle(), chosenPixelFormat, &pfd)) { - if (SetPixelFormat(windowWrapper->internalHandle(), chosenPixelFormat, &pfd)) + _contextHandle = wglCreateContext(windowWrapper->internalHandle()); + if (_contextHandle) { - _contextHandle = wglCreateContext(windowWrapper->internalHandle()); - if (_contextHandle) + if (sharedWithContext) + { + wglShareLists(_contextHandle, sharedWithContext); + } + + int makeCurrentOk = wglMakeCurrent(windowWrapper->internalHandle(), _contextHandle); + if (makeCurrentOk) { - if (sharedWithContext) - { - shareLists(sharedWithContext); - } - - int makeCurrentOk = wglMakeCurrent(windowWrapper->internalHandle(), _contextHandle); - if (makeCurrentOk) - { - _isValid = true; - } + _isValid = true; } } } } } -void GLContext::shareLists(HardwareContextHandle context) -{ - if (_isValid) - { - wglShareLists(_contextHandle, context); - } -} - #elif defined(__linux__) GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedWithContext) : @@ -90,131 +75,52 @@ GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedW _contextHandle(nullptr), _isValid(false) { - // Get connection to X Server - _xDisplay = _window->getWindowWrapper()->getXDisplay(); - - // Load in OpenGL library - void *libHandle = dlopen("libGL.so", RTLD_LAZY); - - // - // Get X required functions - // - XVisualInfo * (*ChooseVisualFuncPtr)(Display *, int, int *); - ChooseVisualFuncPtr = (XVisualInfo *(*)(Display *, int, int *)) - dlsym(libHandle, "glXChooseVisual"); - if ((dlerror()) != 0) - { - return; - } - - GLXContext(*CreateContextFuncPtr)(Display *, XVisualInfo *, GLXContext, Bool); - CreateContextFuncPtr = (GLXContext(*)(Display *, XVisualInfo *, GLXContext, Bool)) - dlsym(libHandle, "glXCreateContext"); - if ((dlerror()) != 0) - { - return; - } - - Bool(*MakeCurrentFuncPtr)(Display *, GLXDrawable, GLXContext); - MakeCurrentFuncPtr = (Bool(*)(Display *, GLXDrawable, GLXContext)) - dlsym(libHandle, "glXMakeCurrent"); - if ((dlerror()) != 0) - { - return; - } - - GLXDrawable(*GetDrawableFuncPtr)(); - GetDrawableFuncPtr = (GLXDrawable(*)())dlsym(libHandle, "glXGetCurrentDrawable"); - if ((dlerror()) != 0) - { - return; - } - - GLXContext(*GetContextFuncPtr)(); - GetContextFuncPtr = (GLXContext(*)())dlsym(libHandle, "glXGetCurrentContext"); - if ((dlerror()) != 0) - { - return; - } - - if (ChooseVisualFuncPtr == 0 || CreateContextFuncPtr == 0 || MakeCurrentFuncPtr == 0 || GetDrawableFuncPtr == 0 || GetContextFuncPtr == 0) + // Get the existing window wrapper and X display. + WindowWrapperPtr windowWrapper = _window->getWindowWrapper(); + if (!windowWrapper->isValid()) { return; } + _xDisplay = windowWrapper->getXDisplay(); - int list[30]; - int i = 0; - - list[i++] = GLX_RGBA; - list[i++] = GLX_DOUBLEBUFFER; - list[i++] = GLX_RED_SIZE; list[i++] = 8; - list[i++] = GLX_GREEN_SIZE; list[i++] = 8; - list[i++] = GLX_BLUE_SIZE; list[i++] = 8; - list[i++] = GLX_ALPHA_SIZE; list[i++] = 8; - list[i++] = GLX_DEPTH_SIZE; list[i++] = 24; - list[i++] = GLX_STENCIL_SIZE; list[i++] = 8; - - list[i++] = None; - XVisualInfo *vinfo = ChooseVisualFuncPtr(_xDisplay, DefaultScreen(_xDisplay), list); - if (vinfo == 0) + // Find an appropriate OpenGL-capable visual. + static int attr[] = { GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + None }; + XVisualInfo* vi = glXChooseVisual(_xDisplay, DefaultScreen(_xDisplay), attr); + if (!vi) { - _contextHandle = 0; return; } - // Create context that shares display lists and texture objects across contexts - if (sharedWithContext) - { - _contextHandle = CreateContextFuncPtr(_xDisplay, vinfo, sharedWithContext, GL_TRUE); - } - else - { - _contextHandle = CreateContextFuncPtr(_xDisplay, vinfo, 0, GL_TRUE); - } - - if (_contextHandle == 0) + // Create an OpenGL rendering context. + _contextHandle = glXCreateContext(_xDisplay, vi, sharedWithContext, GL_TRUE); + if (!_contextHandle) { return; } - // For glX need a window to make the context created above current, creating - // minimal requirements for an OpenGL window - Window root = RootWindow(_xDisplay, DefaultScreen(_xDisplay)); - Colormap cmap = XCreateColormap(_xDisplay, root, vinfo->visual, AllocNone); - XSetWindowAttributes wa; - unsigned long attribMask; - attribMask = CWBackPixmap | CWBorderPixel | CWColormap; - wa.background_pixmap = None; - wa.border_pixel = 0; - wa.colormap = cmap; - - // Create an X window with the visual requested above - _xWindow = XCreateWindow(_xDisplay, root, 0, 0, 10, 10, 0, vinfo->depth, InputOutput, - vinfo->visual, attribMask, &wa); - if (_xWindow == 0) + // Create an X colormap and window. + Colormap cmap = XCreateColormap(_xDisplay, RootWindow(_xDisplay, vi->screen), vi->visual, AllocNone); + XSetWindowAttributes swa; + swa.colormap = cmap; + swa.border_pixel = 0; + swa.background_pixmap = None; + _xWindow = XCreateWindow(_xDisplay, RootWindow(_xDisplay, vi->screen), + 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, + CWBackPixmap | CWBorderPixel | CWColormap, &swa); + if (!_xWindow) { - _contextHandle = 0; return; } - // Save the current context. - GLXDrawable oldDrawable = GetDrawableFuncPtr(); - GLXContext oldContext = GetContextFuncPtr(); - bool haveOldContext = (NULL != oldContext); - bool haveOldDrawable = (None != oldDrawable); - - MakeCurrentFuncPtr(_xDisplay, _xWindow, _contextHandle); - - if (_xDisplay) - { - _isValid = true; - - // Restore the previous context. - if (haveOldContext && haveOldDrawable) - { - MakeCurrentFuncPtr(_xDisplay, oldDrawable, oldContext); - } - } + glXMakeCurrent(_xDisplay, _xWindow, _contextHandle); + _isValid = true; } #elif defined(__APPLE__) @@ -244,20 +150,16 @@ GLContext::GLContext(const SimpleWindowPtr window, HardwareContextHandle sharedW GLContext::~GLContext() { - // Only do this portion if the context is valid if (_isValid) { #if defined(_WIN32) - // Release the dummy context. wglDeleteContext(_contextHandle); #elif defined(__linux__) glXMakeCurrent(_xDisplay, None, NULL); - // This needs to be done after all the GL object - // created with this context are destroyed. if (_contextHandle != 0) { glXDestroyContext(_xDisplay, _contextHandle); @@ -269,8 +171,6 @@ GLContext::~GLContext() #elif defined(__APPLE__) - // This needs to be done after all the GL objects created with this - // context are destroyed. if (_contextHandle != 0) { NSOpenGLDestroyCurrentContext(&_contextHandle); diff --git a/source/MaterialXRenderGlsl/GLContext.h b/source/MaterialXRenderGlsl/GLContext.h index fcad920dc6..ddeee93c39 100644 --- a/source/MaterialXRenderGlsl/GLContext.h +++ b/source/MaterialXRenderGlsl/GLContext.h @@ -64,11 +64,6 @@ class GLContext /// Make the context "current" before execution of OpenGL operations int makeCurrent(); -#if defined(_WIN32) - /// Share this context with an external one - void shareLists(HardwareContextHandle context); -#endif - protected: // Create the base context. A OpenGL context to share with can be passed in. GLContext(SimpleWindowPtr window, HardwareContextHandle context = 0); diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 5a129ef095..fcb4a1f40d 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -27,22 +27,16 @@ int GlslProgram::Input::INVALID_OPENGL_TYPE = -1; // GlslProgram methods // -GlslProgramPtr GlslProgram::create() -{ - return std::shared_ptr(new GlslProgram()); -} - GlslProgram::GlslProgram() : _programId(UNDEFINED_OPENGL_RESOURCE_ID), _shader(nullptr), - _vertexArray(0), + _vertexArray(UNDEFINED_OPENGL_RESOURCE_ID), _lastGeometryName(EMPTY_STRING) { } GlslProgram::~GlslProgram() { - // Clean up the program and offscreen target deleteProgram(); } diff --git a/source/MaterialXRenderGlsl/GlslProgram.h b/source/MaterialXRenderGlsl/GlslProgram.h index 7b779d0c7e..5bd1254d5c 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.h +++ b/source/MaterialXRenderGlsl/GlslProgram.h @@ -36,7 +36,10 @@ class GlslProgram { public: /// Create a GLSL program instance - static GlslProgramPtr create(); + static GlslProgramPtr create() + { + return GlslProgramPtr(new GlslProgram()); + } /// Destructor virtual ~GlslProgram(); diff --git a/source/MaterialXRenderGlsl/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp index 9b25b581dd..57981666d2 100644 --- a/source/MaterialXRenderGlsl/GlslRenderer.cpp +++ b/source/MaterialXRenderGlsl/GlslRenderer.cpp @@ -43,9 +43,8 @@ GlslRenderer::GlslRenderer(unsigned int width, unsigned int height, Image::BaseT _program = GlslProgram::create(); - TinyObjLoaderPtr loader = TinyObjLoader::create(); _geometryHandler = GeometryHandler::create(); - _geometryHandler->addLoader(loader); + _geometryHandler->addLoader(TinyObjLoader::create()); _viewHandler = ViewHandler::create(); } @@ -54,39 +53,7 @@ GlslRenderer::~GlslRenderer() { if (_program->geometryBound()) { - if (_context->makeCurrent()) - { - _program->unbindGeometry(); - } - } - - // Clean up the program - _program = nullptr; - - // Clean up frame buffer - _frameBuffer = nullptr; - - // Clean up the context - _context = nullptr; - - // Clean up the window - _window = nullptr; -} - -void GlslRenderer::setSize(unsigned int width, unsigned int height) -{ - if (_context->makeCurrent()) - { - if (_frameBuffer) - { - _frameBuffer->resize(width, height); - } - else - { - _frameBuffer = GLFramebuffer::create(width, height, 4, Image::BaseType::UINT8); - } - _width = width; - _height = height; + _program->unbindGeometry(); } } @@ -212,6 +179,23 @@ void GlslRenderer::validateInputs() _program->getAttributesList(); } +void GlslRenderer::setSize(unsigned int width, unsigned int height) +{ + if (_context->makeCurrent()) + { + if (_frameBuffer) + { + _frameBuffer->resize(width, height); + } + else + { + _frameBuffer = GLFramebuffer::create(width, height, 4, Image::BaseType::UINT8); + } + _width = width; + _height = height; + } +} + void GlslRenderer::updateViewInformation() { float fH = std::tan(FOV_PERSP / 360.0f * PI) * NEAR_PLANE_PERSP; diff --git a/source/MaterialXRenderHw/SimpleWindowLinux.cpp b/source/MaterialXRenderHw/SimpleWindowLinux.cpp index 3e50c5b42a..09a09c248b 100644 --- a/source/MaterialXRenderHw/SimpleWindowLinux.cpp +++ b/source/MaterialXRenderHw/SimpleWindowLinux.cpp @@ -20,7 +20,6 @@ SimpleWindow::SimpleWindow() clearInternalState(); // Give a unique ID to this window. - // static unsigned int windowCount = 1; _id = windowCount; windowCount++; @@ -81,6 +80,11 @@ bool SimpleWindow::initialize(const char* title, SimpleWindow::~SimpleWindow() { + if (!_windowWrapper) + { + return; + } + Widget widget = _windowWrapper->externalHandle(); if (widget) { From 2e8e67ab0aa24a99a03564d831dbd41044bd6cb7 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Fri, 11 Dec 2020 12:12:09 -0800 Subject: [PATCH 23/35] 82d3d170 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae168948b3..ab763dc4c9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MaterialX [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/materialx/MaterialX/blob/master/LICENSE.txt) -[![Version](https://badge.fury.io/gh/materialx%2FMaterialX.svg)](https://github.com/materialx/MaterialX/releases/latest) +[![Version](https://img.shields.io/github/v/release/materialx/MaterialX)](https://github.com/materialx/MaterialX/releases/latest) [![Build Status](https://github.com/MaterialX/MaterialX/workflows/build/badge.svg?branch=master)](https://github.com/MaterialX/MaterialX/actions?query=branch%3Amaster) MaterialX is an open standard for transfer of rich material and look-development content between applications and renderers. Originated at Lucasfilm in 2012, MaterialX has been used by Industrial Light & Magic (ILM) in feature films such as _Star Wars: The Force Awakens_ and real-time experiences such as _Trials on Tatooine_, and it remains the central material format for new ILM productions. From 6a887a4b6135bc6ecfaab9918c91b2dfc2b5ff09 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 12 Dec 2020 12:27:00 -0800 Subject: [PATCH 24/35] Improved color space handling in MaterialXRenderGlsl --- .github/workflows/build_linux.yml | 20 +++++++++++-------- .../standard_surface_carpaint.mtlx | 1 - ...andard_surface_greysphere_calibration.mtlx | 4 ++-- source/MaterialXGenShader/ShaderGraph.cpp | 8 +++++++- source/MaterialXRenderGlsl/TextureBaker.cpp | 5 ++++- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 5a3a649cbe..0408484e9c 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -60,12 +60,6 @@ jobs: echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV fi - if [ "${{ matrix.test_render }}" = "ON" ]; then - echo "MESA_GL_VERSION_OVERRIDE=4.0FC" >> $GITHUB_ENV - echo "MESA_GLSL_VERSION_OVERRIDE=400" >> $GITHUB_ENV - echo "GALLIUM_DRIVER=softpipe" >> $GITHUB_ENV - echo "RENDER_ENVIRONMENT=xvfb-run" >> $GITHUB_ENV - fi - name: Install Python ${{ matrix.python }} uses: actions/setup-python@v2 @@ -98,11 +92,21 @@ jobs: python genshader.py working-directory: python/MaterialXTest + - name: Initialize Virtual Framebuffer + if: matrix.test_render == 'ON' && runner.os == 'Linux' + run: | + Xvfb :99 -screen 0 1280x960x24 & + echo "DISPLAY=:99" >> $GITHUB_ENV + echo "MESA_GL_VERSION_OVERRIDE=4.0FC" >> $GITHUB_ENV + echo "MESA_GLSL_VERSION_OVERRIDE=400" >> $GITHUB_ENV + echo "GALLIUM_DRIVER=softpipe" >> $GITHUB_ENV + - name: Material Baking Tests if: matrix.test_render == 'ON' run: | mkdir build/baked - $RENDER_ENVIRONMENT python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx build/baked/brass_tiled_baked.mtlx --path . + python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx build/baked/brass_tiled_baked.mtlx --path . + python python/Scripts/baketextures.py resources/Materials/Examples/StandardSurface/standard_surface_carpaint.mtlx build/baked/carpaint_baked.mtlx --path . - name: Generate Test HTML if: matrix.generate_html == 'ON' @@ -119,7 +123,7 @@ jobs: uses: actions/upload-artifact@v2 if: matrix.test_render == 'ON' with: - name: BakedMaterials + name: BakedMaterials_${{matrix.name}} path: build/baked/ - name: Upload Test HTML diff --git a/resources/Materials/Examples/StandardSurface/standard_surface_carpaint.mtlx b/resources/Materials/Examples/StandardSurface/standard_surface_carpaint.mtlx index 3ab62d77ff..6acb3028d5 100644 --- a/resources/Materials/Examples/StandardSurface/standard_surface_carpaint.mtlx +++ b/resources/Materials/Examples/StandardSurface/standard_surface_carpaint.mtlx @@ -8,7 +8,6 @@ - diff --git a/resources/Materials/Examples/StandardSurface/standard_surface_greysphere_calibration.mtlx b/resources/Materials/Examples/StandardSurface/standard_surface_greysphere_calibration.mtlx index a51ae525b3..e29be8130e 100644 --- a/resources/Materials/Examples/StandardSurface/standard_surface_greysphere_calibration.mtlx +++ b/resources/Materials/Examples/StandardSurface/standard_surface_greysphere_calibration.mtlx @@ -1,6 +1,6 @@ - - + + diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 07796211b5..f9512c4296 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -13,6 +13,7 @@ #include +#include #include namespace MaterialX @@ -1343,7 +1344,7 @@ void ShaderGraph::populateColorTransformMap(ColorManagementSystemPtr colorManage const string& sourceColorSpace = input->getActiveColorSpace(); if (shaderPort && !sourceColorSpace.empty()) { - if(shaderPort->getType() == Type::COLOR3 || shaderPort->getType() == Type::COLOR4) + if (shaderPort->getType() == Type::COLOR3 || shaderPort->getType() == Type::COLOR4) { // If we're converting between two identical color spaces than we have no work to do. if (sourceColorSpace != targetColorSpace) @@ -1360,6 +1361,11 @@ void ShaderGraph::populateColorTransformMap(ColorManagementSystemPtr colorManage _outputColorTransformMap.emplace(static_cast(shaderPort), transform); } } + else + { + std::cerr << "Unsupported color space transform from " << + sourceColorSpace << " to " << targetColorSpace << std::endl; + } } } } diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index 630f2784de..941d2c5ebe 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -252,7 +252,10 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim // Create document. DocumentPtr bakedTextureDoc = createDocument(); - bakedTextureDoc->setColorSpace(_colorSpace); + if (_shaderRef->getDocument()->hasColorSpace()) + { + bakedTextureDoc->setColorSpace(_shaderRef->getDocument()->getColorSpace()); + } // Create top-level elements. Note that the child names may not be what // was requested so member names must be updated here to reflect that. From 902616598541f9a814a0f50124c100c216040b4f Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 12 Dec 2020 17:33:16 -0800 Subject: [PATCH 25/35] Disable software render tests in v1.38 --- .github/workflows/build_linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 0408484e9c..ec2e507a62 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -33,7 +33,6 @@ jobs: compiler: gcc compiler_version: "10" python: 3.7 - test_render: ON runs-on: ${{matrix.os}} From 8087988989b779716c598942e2263f0234dc667f Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 16:31:39 -0500 Subject: [PATCH 26/35] Patch. --- source/MaterialXRenderGlsl/TextureBaker.cpp | 4 ++-- source/PyMaterialX/PyMaterialXCore/PyDocument.cpp | 2 ++ source/PyMaterialX/PyMaterialXCore/PyLook.cpp | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index 941d2c5ebe..124a27204a 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -252,9 +252,9 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim // Create document. DocumentPtr bakedTextureDoc = createDocument(); - if (_shaderRef->getDocument()->hasColorSpace()) + if (shader->getDocument()->hasColorSpace()) { - bakedTextureDoc->setColorSpace(_shaderRef->getDocument()->getColorSpace()); + bakedTextureDoc->setColorSpace(shader->getDocument()->getColorSpace()); } // Create top-level elements. Note that the child names may not be what diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index c98748826f..904a589140 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -25,6 +25,8 @@ void bindPyDocument(py::module& mod) .def("getNodeGraphs", &mx::Document::getNodeGraphs) .def("removeNodeGraph", &mx::Document::removeNodeGraph) .def("getMatchingPorts", &mx::Document::getMatchingPorts) + .def("getMaterialNode", &mx::Document::getMaterialNode) + .def("getMaterialNodes", &mx::Document::getMaterialNodes) .def("addGeomInfo", &mx::Document::addGeomInfo, py::arg("name") = mx::EMPTY_STRING, py::arg("geom") = mx::UNIVERSAL_GEOM_NAME) .def("getGeomInfo", &mx::Document::getGeomInfo) diff --git a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp index e0dd3b12ba..16e1e91447 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp @@ -64,6 +64,7 @@ void bindPyLook(py::module& mod) .def("setExclusive", &mx::MaterialAssign::setExclusive) .def("getExclusive", &mx::MaterialAssign::getExclusive) .def("getReferencedMaterial", &mx::MaterialAssign::getReferencedMaterial) + .def("getReferencedMaterialNode", &mx::MaterialAssign::getReferencedMaterialNode) .def_readonly_static("CATEGORY", &mx::MaterialAssign::CATEGORY); py::class_(mod, "Visibility") From ad320a359bea8a5f5e7b1343999034f0bdc2ad3f Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 17:02:46 -0500 Subject: [PATCH 27/35] Patch. --- .../MaterialXMaya/CreateMaterialXNodeCmd.cpp | 1 - source/MaterialXCore/Document.cpp | 181 ++++++++-- source/MaterialXCore/Document.h | 3 - source/MaterialXCore/Element.cpp | 2 +- source/MaterialXCore/MaterialNode.cpp | 308 ------------------ source/MaterialXCore/MaterialNode.h | 54 --- source/MaterialXGenOgsXml/OgsFragment.cpp | 1 - source/MaterialXRuntime/RtFileIo.cpp | 44 +-- source/MaterialXRuntime/RtFileIo.h | 3 - .../MaterialXTest/MaterialXCore/Document.cpp | 13 - .../PyMaterialXCore/PyDefinition.cpp | 2 +- .../PyMaterialXCore/PyDocument.cpp | 4 +- source/PyMaterialX/PyMaterialXCore/PyLook.cpp | 1 - .../PyMaterialXCore/PyMaterial.cpp | 1 - 14 files changed, 163 insertions(+), 455 deletions(-) delete mode 100644 source/MaterialXCore/MaterialNode.cpp delete mode 100644 source/MaterialXCore/MaterialNode.h diff --git a/source/MaterialXContrib/MaterialXMaya/CreateMaterialXNodeCmd.cpp b/source/MaterialXContrib/MaterialXMaya/CreateMaterialXNodeCmd.cpp index 248be676f0..89e2a117c1 100644 --- a/source/MaterialXContrib/MaterialXMaya/CreateMaterialXNodeCmd.cpp +++ b/source/MaterialXContrib/MaterialXMaya/CreateMaterialXNodeCmd.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 0c8aaef5ab..0eb82d0d35 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -6,7 +6,6 @@ #include #include -#include #include @@ -21,6 +20,159 @@ namespace { const string DOCUMENT_VERSION_STRING = std::to_string(MATERIALX_MAJOR_VERSION) + "." + std::to_string(MATERIALX_MINOR_VERSION); +template shared_ptr updateChildSubclass(ElementPtr parent, ElementPtr origChild) +{ + string childName = origChild->getName(); + int childIndex = parent->getChildIndex(childName); + parent->removeChild(childName); + shared_ptr newChild = parent->addChild(childName); + parent->setChildIndex(childName, childIndex); + newChild->copyContentFrom(origChild); + return newChild; +} + +NodeDefPtr getShaderNodeDef(ElementPtr shaderRef) +{ + if (shaderRef->hasAttribute(NodeDef::NODE_DEF_ATTRIBUTE)) + { + string nodeDefString = shaderRef->getAttribute(NodeDef::NODE_DEF_ATTRIBUTE); + return shaderRef->resolveRootNameReference(nodeDefString); + } + if (shaderRef->hasAttribute(NodeDef::NODE_ATTRIBUTE)) + { + string nodeString = shaderRef->getAttribute(NodeDef::NODE_ATTRIBUTE); + string type = shaderRef->getAttribute(TypedElement::TYPE_ATTRIBUTE); + vector nodeDefs = shaderRef->getDocument()->getMatchingNodeDefs(shaderRef->getQualifiedName(nodeString)); + vector secondary = shaderRef->getDocument()->getMatchingNodeDefs(nodeString); + nodeDefs.insert(nodeDefs.end(), secondary.begin(), secondary.end()); + for (NodeDefPtr nodeDef : nodeDefs) + { + if (targetStringsMatch(nodeDef->getTarget(), shaderRef->getTarget()) && + nodeDef->isVersionCompatible(shaderRef) && + (type.empty() || nodeDef->getType() == type)) + { + return nodeDef; + } + } + } + return NodeDefPtr(); +} + +void convertMaterialsToNodes(DocumentPtr doc) +{ + for (ElementPtr mat : doc->getChildrenOfType("material")) + { + string materialName = mat->getName(); + + // Create a temporary name for the material element + // so the new node can reuse the existing name. + string validName = doc->createValidChildName(materialName + "1"); + mat->setName(validName); + + // Create a new material node + NodePtr materialNode = nullptr; + + // Only include the shader refs explicitly specified on the material instance + for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) + { + // See if shader has been created already. + // Should not occur as the shaderref is a uniquely named + // child of a uniquely named material element, but the two combined + // may have been used for another node instance which not a shader node. + string shaderNodeName = materialName + "_" + shaderRef->getName(); + NodePtr existingShaderNode = doc->getNode(shaderNodeName); + if (existingShaderNode) + { + const string& existingType = existingShaderNode->getType(); + if (existingType == VOLUME_SHADER_TYPE_STRING || + existingType == SURFACE_SHADER_TYPE_STRING || + existingType == DISPLACEMENT_SHADER_TYPE_STRING) + { + throw Exception("Shader node already exists: " + shaderNodeName); + } + else + { + shaderNodeName = doc->createValidChildName(shaderNodeName); + } + } + + // Find the shader type if defined + string shaderNodeType = SURFACE_SHADER_TYPE_STRING; + NodeDefPtr nodeDef = getShaderNodeDef(shaderRef); + if (nodeDef) + { + shaderNodeType = nodeDef->getType(); + } + + // Add in a new shader node + const string shaderNodeCategory = shaderRef->getAttribute("node"); + NodePtr shaderNode = doc->addNode(shaderNodeCategory, shaderNodeName, shaderNodeType); + shaderNode->setSourceUri(shaderRef->getSourceUri()); + + for (ElementPtr child : shaderRef->getChildren()) + { + ElementPtr port = nullptr; + + // Copy over bindinputs as inputs, and bindparams as params + if (child->getCategory() == "bindinput") + { + port = shaderNode->addInput(child->getName(), child->getAttribute(TypedElement::TYPE_ATTRIBUTE)); + } + else if (child->getCategory() == "bindparam") + { + port = shaderNode->addChildOfCategory("parameter", child->getName()); + port->setAttribute(TypedElement::TYPE_ATTRIBUTE, child->getAttribute(TypedElement::TYPE_ATTRIBUTE)); + } + else if (child->getCategory() == "bindtoken") + { + TokenPtr token = shaderNode->addToken(child->getName()); + token->copyContentFrom(child); + } + if (port) + { + // Copy over attributes. + // Note: We preserve inputs which have nodegraph connections, + // as well as top level output connections. + port->copyContentFrom(child); + } + } + + // Create a new material node if not already created and + // add a reference from the material node to the new shader node + if (!materialNode) + { + materialNode = doc->addMaterialNode(materialName, shaderNode); + materialNode->setSourceUri(mat->getSourceUri()); + // Note: Inheritance does not get transfered to the node we do + // not perform the following: + // - materialNode->setInheritString(mat->getInheritString()); + } + + // Create input to replace each shaderref. Use shaderref name as unique + // input name. + InputPtr shaderInput = materialNode->getInput(shaderNodeType); + if (!shaderInput) + { + shaderInput = materialNode->addInput(shaderNodeType, shaderNodeType); + shaderInput->setNodeName(shaderNode->getName()); + } + // Make sure to copy over any target and version information from the shaderref. + if (!shaderRef->getTarget().empty()) + { + shaderInput->setTarget(shaderRef->getTarget()); + } + if (!shaderRef->getVersionString().empty()) + { + shaderInput->setVersionString(shaderRef->getVersionString()); + } + } + + // Remove the original material element + doc->removeChild(mat->getName()); + } +} + + } // anonymous namespace // @@ -358,33 +510,6 @@ bool Document::convertParametersToInputs() return anyConverted; } -bool Document::convertUniformInputsToParameters() -{ - bool anyConverted = false; - - const StringSet uniformTypes = { FILENAME_TYPE_STRING, STRING_TYPE_STRING }; - for (ElementPtr e : traverseTree()) - { - InterfaceElementPtr elem = e->asA(); - if (!elem) - { - continue; - } - vector children = elem->getChildren(); - for (ElementPtr child : children) - { - InputPtr input = child->asA(); - if (input && input->getIsUniform()) - { - ParameterPtr newParameter = changeChildCategory(elem, child, Parameter::CATEGORY)->asA(); - newParameter->removeAttribute(ValueElement::UNIFORM_ATTRIBUTE); - anyConverted = true; - } - } - } - return anyConverted; -} - void Document::upgradeVersion(bool applyFutureUpdates) { std::pair versions = getVersionIntegers(); diff --git a/source/MaterialXCore/Document.h b/source/MaterialXCore/Document.h index 71c1f78b1c..4e92bdfd4e 100644 --- a/source/MaterialXCore/Document.h +++ b/source/MaterialXCore/Document.h @@ -663,9 +663,6 @@ class Document : public GraphElement /// Convert Parameter Elements to Input Elements bool convertParametersToInputs(); - /// Convert Input Elements which are uniform to Parameter Elements - bool convertUniformInputsToParameters(); - /// @} /// @name Utility /// @{ diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 917baa1e0c..35fd3fd31b 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -709,7 +709,7 @@ INSTANTIATE_CONCRETE_SUBCLASS(Property, "property") INSTANTIATE_CONCRETE_SUBCLASS(PropertyAssign, "propertyassign") INSTANTIATE_CONCRETE_SUBCLASS(PropertySet, "propertyset") INSTANTIATE_CONCRETE_SUBCLASS(PropertySetAssign, "propertysetassign") - - -namespace MaterialX -{ -bool convertMaterialsToNodes(DocumentPtr doc) -{ - bool modified = false; - - vector materials = doc->getMaterials(); - for (auto m : materials) - { - // See if a node of this name has already been created. - // Should not occur otherwise there are duplicate existing - // Material elements. - string materialName = m->getName(); - if (doc->getNode(materialName)) - { - throw Exception("Material node already exists: " + materialName); - } - - // Create a temporary name for the material element - // so the new node can reuse the existing name. - string validName = doc->createValidChildName(materialName + "1"); - m->setName(validName); - - // Create a new material node - NodePtr materialNode = nullptr; - - ShaderRefPtr sr; - // Only include the shader refs explicitly specified on the material instance - vector srs = m->getShaderRefs(); - for (size_t i = 0; i < srs.size(); i++) - { - sr = srs[i]; - - // See if shader has been created already. - // Should not occur as the shaderref is a uniquely named - // child of a uniquely named material element, but the two combined - // may have been used for another node instance which not a shader node. - string shaderNodeName = materialName + "_" + sr->getName(); - NodePtr existingShaderNode = doc->getNode(shaderNodeName); - if (existingShaderNode) - { - const string& existingType = existingShaderNode->getType(); - if (existingType == VOLUME_SHADER_TYPE_STRING || - existingType == SURFACE_SHADER_TYPE_STRING || - existingType == DISPLACEMENT_SHADER_TYPE_STRING) - { - throw Exception("Shader node already exists: " + shaderNodeName); - } - else - { - shaderNodeName = doc->createValidChildName(shaderNodeName); - } - } - - modified = true; - - // Find the shader type if defined - string shaderNodeType = SURFACE_SHADER_TYPE_STRING; - NodeDefPtr nodeDef = sr->getNodeDef(); - if (nodeDef) - { - shaderNodeType = nodeDef->getType(); - } - - // Add in a new shader node - const string shaderNodeCategory = sr->getNodeString(); - NodePtr shaderNode = doc->addNode(shaderNodeCategory, shaderNodeName, shaderNodeType); - shaderNode->setSourceUri(sr->getSourceUri()); - - for (auto valueElement : sr->getChildrenOfType()) - { - ElementPtr portChild = nullptr; - - // Copy over bindinputs as inputs, and bindparams as params - if (valueElement->isA()) - { - portChild = shaderNode->addInput(valueElement->getName(), valueElement->getType()); - } - else if (valueElement->isA()) - { - portChild = shaderNode->addInput(valueElement->getName(), valueElement->getType()); - } - if (portChild) - { - // Copy over attributes. - // Note: We preserve inputs which have nodegraph connections, - // as well as top level output connections. - portChild->copyContentFrom(valueElement); - } - } - - // Copy over any bindtokens as tokens - for (auto bt : sr->getBindTokens()) - { - TokenPtr token = shaderNode->addToken(bt->getName()); - token->copyContentFrom(bt); - } - - // Create a new material node if not already created and - // add a reference from the material node to the new shader node - if (!materialNode) - { - // Set the type of material based on current assumption that - // surfaceshaders + displacementshaders result in a surfacematerial - // while a volumeshader means a volumematerial needs to be created. - string materialNodeCategory = - (shaderNodeType != VOLUME_SHADER_TYPE_STRING) ? SURFACE_MATERIAL_NODE_STRING - : VOLUME_MATERIAL_NODE_STRING; - materialNode = doc->addNode(materialNodeCategory, materialName, MATERIAL_TYPE_STRING); - materialNode->setSourceUri(m->getSourceUri()); - // Note: Inheritance does not get transfered to the node we do - // not perform the following: - // - materialNode->setInheritString(m->getInheritString()); - } - // Create input to replace each shaderref. Use shaderref name as unique - // input name. - InputPtr shaderInput = materialNode->addInput(shaderNodeType, shaderNodeType); - shaderInput->setNodeName(shaderNode->getName()); - // Make sure to copy over any target and version information from the shaderref. - if (!sr->getTarget().empty()) - { - shaderInput->setTarget(sr->getTarget()); - } - if (!sr->getVersionString().empty()) - { - shaderInput->setVersionString(sr->getVersionString()); - } - } - - // Remove existing material element - doc->removeChild(m->getName()); - } - return modified; -} - - -std::unordered_set getShaderNodes(const NodePtr& materialNode, const string& nodeType, const string& target) -{ - ElementPtr parent = materialNode->getParent(); - if (!parent) - { - throw Exception("Could not find a parent for material node '" + (materialNode ? materialNode->getNamePath() : EMPTY_STRING) + "'"); - } - - std::unordered_set shaderNodes; - - std::vector inputs = materialNode->getActiveInputs(); - if (inputs.empty()) - { - // Try to find material nodes in the implementation graph if any. - // If a target is specified the nodedef for the given target is searched for. - NodeDefPtr materialNodeDef = materialNode->getNodeDef(target); - if (materialNodeDef) - { - InterfaceElementPtr impl = materialNodeDef->getImplementation(target); - if (impl && impl->isA()) - { - NodeGraphPtr implGraph = impl->asA(); - for (auto defOutput : materialNodeDef->getOutputs()) - { - if (defOutput->getType() == MATERIAL_TYPE_STRING) - { - OutputPtr implGraphOutput = implGraph->getOutput(defOutput->getName()); - for (GraphIterator it = implGraphOutput->traverseGraph().begin(); it != GraphIterator::end(); ++it) - { - ElementPtr upstreamElem = it.getUpstreamElement(); - if (!upstreamElem) - { - it.setPruneSubgraph(true); - continue; - } - NodePtr upstreamNode = upstreamElem->asA(); - if (upstreamNode && upstreamNode->getType() == MATERIAL_TYPE_STRING) - { - std::unordered_set newShaderNodes = getShaderNodes(upstreamNode, nodeType, target); - if (!newShaderNodes.empty()) - { - shaderNodes.insert(newShaderNodes.begin(), newShaderNodes.end()); - } - } - } - } - } - } - } - } - - for (const InputPtr& input : inputs) - { - // Scan for a node directly connected to the input. - // - const string& inputShader = input->getNodeName(); - if (!inputShader.empty()) - { - NodePtr shaderNode = parent->getChildOfType(inputShader); - if (shaderNode) - { - if (!nodeType.empty() && shaderNode->getType() != nodeType) - { - continue; - } - - if (!target.empty()) - { - NodeDefPtr nodeDef = shaderNode->getNodeDef(target); - if (!nodeDef) - { - continue; - } - } - shaderNodes.insert(shaderNode); - } - } - - // Check upstream nodegraph connected to the input. - // If no explicit output name given then scan all outputs on the nodegraph. - // - else - { - const string& inputGraph = input->getNodeGraphString(); - if (!inputGraph.empty()) - { - NodeGraphPtr nodeGraph = parent->getChildOfType(inputGraph); - if (nodeGraph) - { - const string& nodeGraphOutput = input->getOutputString(); - std::vector outputs; - if (!nodeGraphOutput.empty()) - { - outputs.push_back(nodeGraph->getOutput(nodeGraphOutput)); - } - else - { - outputs = nodeGraph->getOutputs(); - } - for (OutputPtr output : outputs) - { - NodePtr upstreamNode = output->getConnectedNode(); - if (upstreamNode) - { - if (!target.empty()) - { - NodeDefPtr nodeDef = upstreamNode->getNodeDef(target); - if (!nodeDef) - { - continue; - } - } - shaderNodes.insert(upstreamNode); - } - } - } - } - } - } - return shaderNodes; -} - -vector getGeometryBindings(const NodePtr& materialNode, const string& geom) -{ - vector matAssigns; - for (LookPtr look : materialNode->getDocument()->getLooks()) - { - for (MaterialAssignPtr matAssign : look->getMaterialAssigns()) - { - if (matAssign->getReferencedMaterialNode() == materialNode) - { - if (geomStringsMatch(geom, matAssign->getActiveGeom())) - { - matAssigns.push_back(matAssign); - continue; - } - CollectionPtr coll = matAssign->getCollection(); - if (coll && coll->matchesGeomString(geom)) - { - matAssigns.push_back(matAssign); - continue; - } - } - } - } - return matAssigns; -} - -vector getConnectedOutputs(const NodePtr& node) -{ - vector outputVec; - std::set outputSet; - for (InputPtr input : node->getInputs()) - { - OutputPtr output = input->getConnectedOutput(); - if (output && !outputSet.count(output)) - { - outputVec.push_back(output); - outputSet.insert(output); - } - } - return outputVec; -} - -} // namespace MaterialX diff --git a/source/MaterialXCore/MaterialNode.h b/source/MaterialXCore/MaterialNode.h deleted file mode 100644 index f9d76a9074..0000000000 --- a/source/MaterialXCore/MaterialNode.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// TM & (c) 2020 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd. -// All rights reserved. See LICENSE.txt for license. -// - -#ifndef MATERIALX_MATERIALNODE_H -#define MATERIALX_MATERIALNODE_H - -/// @file -/// Material node utilities - -#include - -#include -#include -#include - -#include - -namespace MaterialX -{ - -/// Convert usage of Material Elements to Material nodes -/// @param doc Document to convert -/// @return If any conversion occurred. -bool convertMaterialsToNodes(DocumentPtr doc); - -/// Return a vector of all nodes connected to a Material node's inputs. The default behavior -/// is to return connected surface shader nodes. -/// @param materialNode Node to examine. -/// @param nodeType Type of node to return. If an empty string is specified then -/// all node types are returned. The default argument value is to return surface shaders. -/// @param target Target attribute filter for nodes to return. The default argument value is an empty string -/// indicating to include nodes which match any target. -std::unordered_set getShaderNodes(const NodePtr& materialNode, - const string& nodeType = SURFACE_SHADER_TYPE_STRING, - const string& target = EMPTY_STRING); - -/// Return a vector of all MaterialAssign elements that bind this material node -/// to the given geometry string -/// @param materialNode Node to examine -/// @param geom The geometry for which material bindings should be returned. -/// By default, this argument is the universal geometry string "/", -/// and all material bindings are returned. -/// @return Vector of MaterialAssign elements -vector getGeometryBindings(const NodePtr& materialNode, const string& geom); - - -/// Return a vector of all outputs that this nodes inputs are connected to. -vector getConnectedOutputs(const NodePtr& node); - -} // namespace MaterialX - -#endif diff --git a/source/MaterialXGenOgsXml/OgsFragment.cpp b/source/MaterialXGenOgsXml/OgsFragment.cpp index 9b501fbd2a..363ef2844b 100644 --- a/source/MaterialXGenOgsXml/OgsFragment.cpp +++ b/source/MaterialXGenOgsXml/OgsFragment.cpp @@ -1,6 +1,5 @@ #include "OgsFragment.h" -#include #include #include #include diff --git a/source/MaterialXRuntime/RtFileIo.cpp b/source/MaterialXRuntime/RtFileIo.cpp index b49a503f5b..f7e95a52fd 100644 --- a/source/MaterialXRuntime/RtFileIo.cpp +++ b/source/MaterialXRuntime/RtFileIo.cpp @@ -744,7 +744,6 @@ namespace NodeDefPtr destNodeDef = dest->addNodeDef(nodedef.getName(), EMPTY_STRING, nodedef.getNode()); writeMetadata(src, destNodeDef, nodedefMetadata, options); - bool writeUniformsAsParameters = options ? options->writeUniformsAsParameters : false; for (const PvtDataHandle attrH : src->getAllAttributes()) { const PvtAttribute* attr = attrH->asA(); @@ -753,21 +752,10 @@ namespace if (attr->isA()) { const PvtInput* input = attr->asA(); + destPort = destNodeDef->addInput(attr->getName(), attr->getType().str()); if (input->isUniform()) { - if (writeUniformsAsParameters) - { - destPort = destNodeDef->addParameter(attr->getName(), attr->getType().str()); - } - else - { - destPort = destNodeDef->addInput(attr->getName(), attr->getType().str()); - destPort->setIsUniform(true); - } - } - else - { - destPort = destNodeDef->addInput(attr->getName(), attr->getType().str()); + destPort->setIsUniform(true); } } else @@ -800,7 +788,6 @@ namespace } bool writeDefaultValues = options ? options->writeDefaultValues : false; - bool writeUniformsAsParameters = options ? options->writeUniformsAsParameters : false; NodePtr destNode = dest->addNode(nodedef.getNamespacedNode(), node.getName(), numOutputs > 1 ? "multioutput" : outputType); @@ -824,15 +811,8 @@ namespace ValueElementPtr valueElem; if (input.isUniform()) { - if (writeUniformsAsParameters) - { - valueElem = destNode->addParameter(input.getName(), input.getType()); - } - else - { - valueElem = destNode->addInput(input.getName(), input.getType()); - valueElem->setIsUniform(true); - } + valueElem = destNode->addInput(input.getName(), input.getType()); + valueElem->setIsUniform(true); if (input.isConnected()) { RtOutput source = input.getConnection(); @@ -917,8 +897,6 @@ namespace if (!options || options->writeNodeGraphInputs) { - bool writeUniformsAsParameters = options ? options->writeUniformsAsParameters : false; - // Write inputs/parameters. RtObjTypePredicate inputsFilter; for (RtAttribute attr : src->getAttributes(inputsFilter)) @@ -927,15 +905,8 @@ namespace ValueElementPtr v = nullptr; if (nodegraphInput.isUniform()) { - if (writeUniformsAsParameters) - { - v = destNodeGraph->addParameter(nodegraphInput.getName(), nodegraphInput.getType()); - } - else - { - v = destNodeGraph->addInput(nodegraphInput.getName(), nodegraphInput.getType()); - v->setIsUniform(true); - } + v = destNodeGraph->addInput(nodegraphInput.getName(), nodegraphInput.getType()); + v->setIsUniform(true); } else { @@ -1278,8 +1249,7 @@ RtWriteOptions::RtWriteOptions() : objectFilter(nullptr), metadataFilter(nullptr), desiredMajorVersion(MATERIALX_MAJOR_VERSION), - desiredMinorVersion(MATERIALX_MINOR_VERSION), - writeUniformsAsParameters(false) + desiredMinorVersion(MATERIALX_MINOR_VERSION) { } diff --git a/source/MaterialXRuntime/RtFileIo.h b/source/MaterialXRuntime/RtFileIo.h index a28b5a38b1..8ba6459178 100644 --- a/source/MaterialXRuntime/RtFileIo.h +++ b/source/MaterialXRuntime/RtFileIo.h @@ -79,9 +79,6 @@ class RtWriteOptions /// The desired minor version unsigned int desiredMinorVersion; - - /// Write uniforms as parameters - bool writeUniformsAsParameters; }; /// API for read and write of data from MaterialX files diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index f80fb59893..ea5d5eeb5e 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -210,19 +210,6 @@ TEST_CASE("Version", "[document]") REQUIRE(testNodeGraph->getNode("add2")); REQUIRE(testNodeGraph->getNode("add2")->getInput("in1")->getInterfaceName() == "add"); REQUIRE(testNodeGraph->getNode("add1")->getInput("in1")->getNodeName() == "add2"); - - // Convert back and forth between parameters and inputs - REQUIRE(doc2->convertUniformInputsToParameters()); - REQUIRE(doc2->validate()); - mx::writeToXmlFile(doc2, "1_38_to_1_37_parameters.mtlx", &writeOptions); - mx::DocumentPtr doc3 = mx::createDocument(); - mx::XmlReadOptions noParamUpdateOptions; - noParamUpdateOptions.applyFutureUpdates = false; - mx::readFromXmlFile(doc3, "1_38_to_1_37_parameters.mtlx", mx::FileSearchPath(), &noParamUpdateOptions); - REQUIRE(doc3->validate()); - REQUIRE(doc3->convertParametersToInputs()); - std::string doc3String = mx::writeToXmlString(doc3); - REQUIRE(doc2String == doc3String); } } diff --git a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp index d3ab4441b2..909d69f311 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp @@ -23,7 +23,7 @@ void bindPyDefinition(py::module& mod) .def("getNodeGroup", &mx::NodeDef::getNodeGroup) .def("getImplementation", &mx::NodeDef::getImplementation) .def("getImplementation", &mx::NodeDef::getImplementation, - py::arg("target") = mx::EMPTY_STRING, + py::arg("target") = mx::EMPTY_STRING) .def("isVersionCompatible", &mx::NodeDef::isVersionCompatible) .def_readonly_static("CATEGORY", &mx::NodeDef::CATEGORY) .def_readonly_static("NODE_ATTRIBUTE", &mx::NodeDef::NODE_ATTRIBUTE) diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index 904a589140..1a6c898cd2 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -25,7 +25,6 @@ void bindPyDocument(py::module& mod) .def("getNodeGraphs", &mx::Document::getNodeGraphs) .def("removeNodeGraph", &mx::Document::removeNodeGraph) .def("getMatchingPorts", &mx::Document::getMatchingPorts) - .def("getMaterialNode", &mx::Document::getMaterialNode) .def("getMaterialNodes", &mx::Document::getMaterialNodes) .def("addGeomInfo", &mx::Document::addGeomInfo, py::arg("name") = mx::EMPTY_STRING, py::arg("geom") = mx::UNIVERSAL_GEOM_NAME) @@ -97,6 +96,5 @@ void bindPyDocument(py::module& mod) .def("setColorManagementConfig", &mx::Document::setColorManagementConfig) .def("hasColorManagementConfig", &mx::Document::hasColorManagementConfig) .def("getColorManagementConfig", &mx::Document::getColorManagementConfig) - .def("convertParametersToInputs", &mx::Document::convertParametersToInputs) - .def("convertUniformInputsToParameters", &mx::Document::convertUniformInputsToParameters); + .def("convertParametersToInputs", &mx::Document::convertParametersToInputs); } diff --git a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp index 16e1e91447..e0dd3b12ba 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp @@ -64,7 +64,6 @@ void bindPyLook(py::module& mod) .def("setExclusive", &mx::MaterialAssign::setExclusive) .def("getExclusive", &mx::MaterialAssign::getExclusive) .def("getReferencedMaterial", &mx::MaterialAssign::getReferencedMaterial) - .def("getReferencedMaterialNode", &mx::MaterialAssign::getReferencedMaterialNode) .def_readonly_static("CATEGORY", &mx::MaterialAssign::CATEGORY); py::class_(mod, "Visibility") diff --git a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp index 5a56f169a7..e98a761a7d 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyMaterial.cpp @@ -13,7 +13,6 @@ namespace mx = MaterialX; void bindPyMaterial(py::module& mod) { - mod.def("convertMaterialsToNodes", &mx::convertMaterialsToNodes); mod.def("getShaderNodes", &mx::getShaderNodes); mod.def("getConnectedOutputs", &mx::getConnectedOutputs); } From 8ad4e989efc1cc82fdd7976c8610162972937b0f Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 17:18:07 -0500 Subject: [PATCH 28/35] Patch texture baker. --- source/MaterialXRenderGlsl/TextureBaker.cpp | 61 ++++++++++++--------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index 124a27204a..602510aecd 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -259,8 +259,14 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim // Create top-level elements. Note that the child names may not be what // was requested so member names must be updated here to reflect that. - _bakedGraphName = bakedTextureDoc->createValidChildName(_bakedGraphName); - NodeGraphPtr bakedNodeGraph = bakedTextureDoc->addNodeGraph(_bakedGraphName); + NodeGraphPtr bakedNodeGraph; + if (!_bakedImageMap.empty()) + { + _bakedGraphName = bakedTextureDoc->createValidChildName(_bakedGraphName); + bakedNodeGraph = bakedTextureDoc->addNodeGraph(_bakedGraphName); + bakedNodeGraph->setColorSpace(_colorSpace); + } + _bakedGeomInfoName = bakedTextureDoc->createValidChildName(_bakedGeomInfoName); GeomInfoPtr bakedGeom = !udimSet.empty() ? bakedTextureDoc->addGeomInfo(_bakedGeomInfoName) : nullptr; if (bakedGeom) @@ -333,34 +339,37 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim } else { - // Add the image node. - NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName + BAKED_POSTFIX, sourceType); - InputPtr input = bakedImage->addInput("file", "filename"); - input->setValueString(generateTextureFilename(output, shader->getName(), udimSet.empty() ? EMPTY_STRING : UDIM_TOKEN)); - - // Check if is a normal node and transform normals into world space - auto worldSpaceShaderInput = _worldSpaceShaderInputs.find(sourceInput->getName()); - if (worldSpaceShaderInput != _worldSpaceShaderInputs.end()) + if (bakedNodeGraph) { - NodePtr origNormalMapNode = worldSpaceShaderInput->second; - NodePtr normalMapNode = bakedNodeGraph->addNode("normalmap", sourceName + BAKED_POSTFIX + "_map", sourceType); - if (origNormalMapNode) + // Add the image node. + NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName + BAKED_POSTFIX, sourceType); + InputPtr input = bakedImage->addInput("file", "filename"); + input->setValueString(generateTextureFilename(output, shader->getName(), udimSet.empty() ? EMPTY_STRING : UDIM_TOKEN)); + + // Check if is a normal node and transform normals into world space + auto worldSpaceShaderInput = _worldSpaceShaderInputs.find(sourceInput->getName()); + if (worldSpaceShaderInput != _worldSpaceShaderInputs.end()) { - normalMapNode->copyContentFrom(origNormalMapNode); + NodePtr origNormalMapNode = worldSpaceShaderInput->second; + NodePtr normalMapNode = bakedNodeGraph->addNode("normalmap", sourceName + BAKED_POSTFIX + "_map", sourceType); + if (origNormalMapNode) + { + normalMapNode->copyContentFrom(origNormalMapNode); + } + InputPtr mapInput = normalMapNode->getInput("in"); + if (!mapInput) + { + mapInput = normalMapNode->addInput("in", sourceType); + } + mapInput->setNodeName(bakedImage->getName()); + bakedImage = normalMapNode; } - InputPtr mapInput = normalMapNode->getInput("in"); - if (!mapInput) - { - mapInput = normalMapNode->addInput("in", sourceType); - } - mapInput->setNodeName(bakedImage->getName()); - bakedImage = normalMapNode; - } - // Add the graph output. - OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName + "_output", sourceType); - bakedOutput->setConnectedNode(bakedImage); - bakedInput->setConnectedOutput(bakedOutput); + // Add the graph output. + OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName + "_output", sourceType); + bakedOutput->setConnectedNode(bakedImage); + bakedInput->setConnectedOutput(bakedOutput); + } } } else From cf45883dc8cb3d09cf2d14fc48f752b28e337c23 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 17:46:31 -0500 Subject: [PATCH 29/35] Fix test. --- source/MaterialXCore/Document.cpp | 5 +---- source/MaterialXTest/MaterialXFormat/XmlIo.cpp | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 0eb82d0d35..a2615a24ec 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -1138,10 +1138,7 @@ void Document::upgradeVersion(bool applyFutureUpdates) minorVersion = 37; } - if (applyFutureUpdates) - { - convertParametersToInputs(); - } + convertParametersToInputs(); if (majorVersion == MATERIALX_MAJOR_VERSION && minorVersion == MATERIALX_MINOR_VERSION) diff --git a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp index a2490790a0..58a9d6bcb3 100644 --- a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp +++ b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp @@ -14,10 +14,8 @@ namespace mx = MaterialX; TEST_CASE("Load content", "[xmlio]") { mx::XmlReadOptions readOptions; - std::vector applyUpdates = { false, true }; - for (auto applyUpdate : applyUpdates) { - readOptions.applyFutureUpdates = applyUpdate; + readOptions.applyFutureUpdates = true; mx::FilePath libraryPath("libraries/stdlib"); mx::FilePath examplesPath("resources/Materials/Examples/Syntax"); From 710c65447282258d953d5127d70a649ca8c46a2e Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 18:07:07 -0500 Subject: [PATCH 30/35] Baker patch. --- source/MaterialXRenderGlsl/TextureBaker.cpp | 54 ++++++++++----------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index 602510aecd..d6a6807377 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -264,7 +264,6 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim { _bakedGraphName = bakedTextureDoc->createValidChildName(_bakedGraphName); bakedNodeGraph = bakedTextureDoc->addNodeGraph(_bakedGraphName); - bakedNodeGraph->setColorSpace(_colorSpace); } _bakedGeomInfoName = bakedTextureDoc->createValidChildName(_bakedGeomInfoName); @@ -337,39 +336,36 @@ DocumentPtr TextureBaker::getBakedMaterial(NodePtr shader, const StringVec& udim bakedInput->setColorSpace(_targetColorSpace); } } - else + if (bakedNodeGraph) { - if (bakedNodeGraph) + // Add the image node. + NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName + BAKED_POSTFIX, sourceType); + InputPtr input = bakedImage->addInput("file", "filename"); + input->setValueString(generateTextureFilename(output, shader->getName(), udimSet.empty() ? EMPTY_STRING : UDIM_TOKEN)); + + // Check if is a normal node and transform normals into world space + auto worldSpaceShaderInput = _worldSpaceShaderInputs.find(sourceInput->getName()); + if (worldSpaceShaderInput != _worldSpaceShaderInputs.end()) { - // Add the image node. - NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName + BAKED_POSTFIX, sourceType); - InputPtr input = bakedImage->addInput("file", "filename"); - input->setValueString(generateTextureFilename(output, shader->getName(), udimSet.empty() ? EMPTY_STRING : UDIM_TOKEN)); - - // Check if is a normal node and transform normals into world space - auto worldSpaceShaderInput = _worldSpaceShaderInputs.find(sourceInput->getName()); - if (worldSpaceShaderInput != _worldSpaceShaderInputs.end()) + NodePtr origNormalMapNode = worldSpaceShaderInput->second; + NodePtr normalMapNode = bakedNodeGraph->addNode("normalmap", sourceName + BAKED_POSTFIX + "_map", sourceType); + if (origNormalMapNode) { - NodePtr origNormalMapNode = worldSpaceShaderInput->second; - NodePtr normalMapNode = bakedNodeGraph->addNode("normalmap", sourceName + BAKED_POSTFIX + "_map", sourceType); - if (origNormalMapNode) - { - normalMapNode->copyContentFrom(origNormalMapNode); - } - InputPtr mapInput = normalMapNode->getInput("in"); - if (!mapInput) - { - mapInput = normalMapNode->addInput("in", sourceType); - } - mapInput->setNodeName(bakedImage->getName()); - bakedImage = normalMapNode; + normalMapNode->copyContentFrom(origNormalMapNode); } - - // Add the graph output. - OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName + "_output", sourceType); - bakedOutput->setConnectedNode(bakedImage); - bakedInput->setConnectedOutput(bakedOutput); + InputPtr mapInput = normalMapNode->getInput("in"); + if (!mapInput) + { + mapInput = normalMapNode->addInput("in", sourceType); + } + mapInput->setNodeName(bakedImage->getName()); + bakedImage = normalMapNode; } + + // Add the graph output. + OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName + "_output", sourceType); + bakedOutput->setConnectedNode(bakedImage); + bakedInput->setConnectedOutput(bakedOutput); } } else From b7a1ff285991a6a65958e53c350a05de0fba7d49 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 20:12:24 -0500 Subject: [PATCH 31/35] Fix crash in viewer. --- source/MaterialXView/Viewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index ecd0c19059..b59de96f71 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -1113,6 +1113,10 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie } materials.push_back(node); } + else + { + materials.push_back(nullptr); + } renderablePaths.push_back(renderableElem->getNamePath()); } From 46600e840f5aed5ee973acdeb5a52d317475d7a0 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 14 Dec 2020 20:30:26 -0500 Subject: [PATCH 32/35] Wasm dormant. --- .../JsMaterialXCore/JsMaterial.cpp | 82 ------ .../JsMaterialX/JsMaterialXCore/JsMaterial.js | 28 --- source/JsMaterialX/test/codeExamples.spec.js | 86 +++---- source/JsMaterialX/test/document.spec.js | 238 +++++++++--------- source/JsMaterialX/test/readXml.spec.js | 32 +-- .travis.yml => wasm_disabled.travis.yml | 0 6 files changed, 178 insertions(+), 288 deletions(-) delete mode 100644 source/JsMaterialX/JsMaterialXCore/JsMaterial.cpp delete mode 100644 source/JsMaterialX/JsMaterialXCore/JsMaterial.js rename .travis.yml => wasm_disabled.travis.yml (100%) diff --git a/source/JsMaterialX/JsMaterialXCore/JsMaterial.cpp b/source/JsMaterialX/JsMaterialXCore/JsMaterial.cpp deleted file mode 100644 index 9f34f24b59..0000000000 --- a/source/JsMaterialX/JsMaterialXCore/JsMaterial.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "../helpers.h" -#include -#include - -#include -#include - -namespace ems = emscripten; -namespace mx = MaterialX; - -extern "C" -{ - EMSCRIPTEN_BINDINGS(material) - { - ems::class_>("Material") - .smart_ptr_constructor("Material", &std::make_shared) - .smart_ptr>("Material") - .function("addShaderRef", &mx::Material::addShaderRef) - .function("getShaderRef", &mx::Material::getShaderRef) - .function("getShaderRefs", &mx::Material::getShaderRefs) - .function("getActiveShaderRefs", &mx::Material::getActiveShaderRefs) - .function("removeShaderRef", &mx::Material::removeShaderRef) - .function("getShaderNodeDefs", &mx::Material::getShaderNodeDefs) - .function("getPrimaryShaderNodeDef", &mx::Material::getPrimaryShaderNodeDef) - .function("getPrimaryShaderName", &mx::Material::getPrimaryShaderName) - .function("getPrimaryShaderInputs", &mx::Material::getPrimaryShaderInputs) - .function("getPrimaryShaderTokens", &mx::Material::getPrimaryShaderTokens) - .function("getGeometryBindings", &mx::Material::getGeometryBindings) - .class_property("CATEGORY", &mx::Material::CATEGORY); - - ems::class_>("BindParam") - .smart_ptr_constructor("BindParam", &std::make_shared) - .smart_ptr>("BindParam") - .class_property("CATEGORY", &mx::BindParam::CATEGORY); - - ems::class_>("BindInput") - .smart_ptr_constructor("BindInput", &std::make_shared) - .smart_ptr>("BindInput") - .function("setNodeGraphString", &mx::BindInput::setNodeGraphString) - .function("hasNodeGraphString", &mx::BindInput::hasNodeGraphString) - .function("getNodeGraphString", &mx::BindInput::getNodeGraphString) - .function("setOutputString", &mx::BindInput::setOutputString) - .function("hasOutputString", &mx::BindInput::hasOutputString) - .function("getOutputString", &mx::BindInput::getOutputString) - .function("setConnectedOutput", &mx::BindInput::setConnectedOutput) - .function("getConnectedOutput", &mx::BindInput::getConnectedOutput) - .class_property("CATEGORY", &mx::BindInput::CATEGORY); - - ems::class_>("BindToken") - .smart_ptr_constructor("BindToken", &std::make_shared) - .smart_ptr>("BindToken") - .class_property("CATEGORY", &mx::BindToken::CATEGORY); - - ems::class_>("ShaderRef") - .smart_ptr_constructor("ShaderRef", &std::make_shared) - .smart_ptr>("ShaderRef") - .function("setNodeString", &mx::ShaderRef::setNodeString) - .function("hasNodeString", &mx::ShaderRef::hasNodeString) - .function("getNodeString", &mx::ShaderRef::getNodeString) - .function("setNodeDefString", &mx::ShaderRef::setNodeDefString) - .function("hasNodeDefString", &mx::ShaderRef::hasNodeDefString) - .function("getNodeDefString", &mx::ShaderRef::getNodeDefString) - .function("getNodeDef", &mx::ShaderRef::getNodeDef) - - .function("addBindParam", &mx::ShaderRef::addBindParam) - .function("getBindParam", &mx::ShaderRef::getBindParam) - .function("getBindParams", &mx::ShaderRef::getBindParams) - .function("removeBindParam", &mx::ShaderRef::removeBindParam) - - .function("addBindInput", &mx::ShaderRef::addBindInput) - .function("getBindInput", &mx::ShaderRef::getBindInput) - .function("getBindInputs", &mx::ShaderRef::getBindInputs) - .function("removeBindInput", &mx::ShaderRef::removeBindInput) - - .function("addBindToken", &mx::ShaderRef::addBindToken) - .function("getBindToken", &mx::ShaderRef::getBindToken) - .function("getBindTokens", &mx::ShaderRef::getBindTokens) - .function("removeBindToken", &mx::ShaderRef::removeBindToken) - .function("getReferencedOutputs", &mx::ShaderRef::getReferencedOutputs) - .class_property("CATEGORY", &mx::ShaderRef::CATEGORY); - } -} \ No newline at end of file diff --git a/source/JsMaterialX/JsMaterialXCore/JsMaterial.js b/source/JsMaterialX/JsMaterialXCore/JsMaterial.js deleted file mode 100644 index a11d471102..0000000000 --- a/source/JsMaterialX/JsMaterialXCore/JsMaterial.js +++ /dev/null @@ -1,28 +0,0 @@ -// jsMaterial -addWrapper(function(Module, api) { - /** Setup the Material class */ - api.Material = wrapperFactory(Module.Material, { - addShaderRef: ['', ''], - getShaderNodeDefs: ['', ''], - getPrimaryShaderNodeDef: ['', ''], - getPrimaryShaderName: ['', ''], - getPrimaryShaderInputs: ['', ''], - getPrimaryShaderTokens: ['', ''], - getGeometryBindings: [api.UNIVERSAL_GEOM_NAME] - }); - - /** Setup the BindParam class */ - api.BindParam = wrapperFactory(Module.BindParam); - - /** Setup the BindInput class */ - api.BindInput = wrapperFactory(Module.BindInput); - - /** Setup the BindToken class */ - api.BindToken = wrapperFactory(Module.BindToken); - - /** Setup the ShaderRef class */ - api.ShaderRef = wrapperFactory(Module.ShaderRef, { - addBindParam: [REQUIRED, api.DEFAULT_TYPE_STRING], - addBindInput: [REQUIRED, api.DEFAULT_TYPE_STRING] - }); -}); diff --git a/source/JsMaterialX/test/codeExamples.spec.js b/source/JsMaterialX/test/codeExamples.spec.js index 546c745cfd..6db9928a50 100644 --- a/source/JsMaterialX/test/codeExamples.spec.js +++ b/source/JsMaterialX/test/codeExamples.spec.js @@ -51,28 +51,28 @@ describe('Code Examples', () => { expect(inputValue).to.not.be.null; expect(inputValue.getData()).to.equal(0.25); - // Create a material that instantiates the shader. - const material = doc.addMaterial(); - const materials = doc.getMaterials(); - expect(materials.length).to.equal(1); - expect(materials[0]).to.eql(material); - const refSimpleSrf = material.addShaderRef('SR_simpleSrf', 'simpleSrf'); - const shaderRefs = material.getShaderRefs(); - expect(shaderRefs.length).to.equal(1); - expect(shaderRefs[0]).to.eql(refSimpleSrf); - expect(shaderRefs[0].getName()).to.equal('SR_simpleSrf'); - - // Bind roughness to a new value within this material. - const bindInput = refSimpleSrf.addBindInput('roughness'); - const bindInputs = refSimpleSrf.getBindInputs(); - expect(bindInputs.length).to.equal(1); - expect(bindInputs[0]).to.eql(bindInput); - bindInput.setValuefloat(0.5); - expect(bindInput.getValue()).to.not.be.null; - expect(bindInput.getValue().getData()).to.equal(0.5); - - // Validate the value of roughness in the context of this material. - expect(roughness.getBoundValue(material).getValueString()).to.equal('0.5'); + // // Create a material that instantiates the shader. + // const material = doc.addMaterial(); + // const materials = doc.getMaterials(); + // expect(materials.length).to.equal(1); + // expect(materials[0]).to.eql(material); + // const refSimpleSrf = material.addShaderRef('SR_simpleSrf', 'simpleSrf'); + // const shaderRefs = material.getShaderRefs(); + // expect(shaderRefs.length).to.equal(1); + // expect(shaderRefs[0]).to.eql(refSimpleSrf); + // expect(shaderRefs[0].getName()).to.equal('SR_simpleSrf'); + + // // Bind roughness to a new value within this material. + // const bindInput = refSimpleSrf.addBindInput('roughness'); + // const bindInputs = refSimpleSrf.getBindInputs(); + // expect(bindInputs.length).to.equal(1); + // expect(bindInputs[0]).to.eql(bindInput); + // bindInput.setValuefloat(0.5); + // expect(bindInput.getValue()).to.not.be.null; + // expect(bindInput.getValue().getData()).to.equal(0.5); + + // // Validate the value of roughness in the context of this material. + // expect(roughness.getBoundValue(material).getValueString()).to.equal('0.5'); }); it('Traversing a Document Tree', async () => { @@ -123,26 +123,26 @@ describe('Code Examples', () => { const doc = mx.createDocument(); mx.readFromXmlString(doc, xmlStr); - let materialCount = 0; - let shaderInputCount = 0; - // Iterate through 1.37 materials for which there should be none - const materials = doc.getMaterials(); - materials.forEach((material) => { - materialCount++; - - // For each shader input, find all upstream images in the dataflow graph. - const primaryShaderInputs = material.getPrimaryShaderInputs(); - primaryShaderInputs.forEach((input) => { - const graphIter = input.traverseGraph(material); - let edge = graphIter.next(); - while (edge) { - shaderInputCount++; - edge = graphIter.next(); - } - }); - }); - - expect(materialCount).to.equal(0); - expect(shaderInputCount).to.equal(0); + // let materialCount = 0; + // let shaderInputCount = 0; + // // Iterate through 1.37 materials for which there should be none + // const materials = doc.getMaterials(); + // materials.forEach((material) => { + // materialCount++; + + // // For each shader input, find all upstream images in the dataflow graph. + // const primaryShaderInputs = material.getPrimaryShaderInputs(); + // primaryShaderInputs.forEach((input) => { + // const graphIter = input.traverseGraph(material); + // let edge = graphIter.next(); + // while (edge) { + // shaderInputCount++; + // edge = graphIter.next(); + // } + // }); + // }); + + // expect(materialCount).to.equal(0); + // expect(shaderInputCount).to.equal(0); }); }); diff --git a/source/JsMaterialX/test/document.spec.js b/source/JsMaterialX/test/document.spec.js index 3bf8ebb14d..fca169f56c 100644 --- a/source/JsMaterialX/test/document.spec.js +++ b/source/JsMaterialX/test/document.spec.js @@ -74,123 +74,123 @@ describe('Build Document', () => { expect(constant.getActiveColorSpace()).to.equal('lin_rec709'); }); - let diffColor, specColor, roughness, texId; - it('Create a simple shader interface', () => { - const shaderDef = doc.addNodeDef('shader1', 'surfaceshader', 'simpleSrf'); - diffColor = shaderDef.setInputValuecolor3('diffColor', new mx.Color3(1.0, 1.0, 1.0)); - specColor = shaderDef.setInputValuecolor3('specColor', new mx.Color3(0.0, 0.0, 0.0)); - roughness = shaderDef.setInputValuefloat('roughness', 0.25); - texId = shaderDef.setTokenValue('texId', '01'); - expect(roughness.getIsUniform()).to.equal(false); - roughness.setIsUniform(true); - expect(roughness.getIsUniform()).to.equal(true); - expect(roughness.getValue().getData()).to.equal(0.25); - }); - - let material, shaderRef; - it('Create a material that instantiates the shader', () => { - material = doc.addMaterial(); - shaderRef = material.addShaderRef('shaderRef1', 'simpleSrf'); - expect(material.getPrimaryShaderName()).to.equal('simpleSrf'); - expect(material.getPrimaryShaderInputs().length).to.equal(3); - expect(material.getPrimaryShaderTokens().length).to.equal(1); - expect(roughness.getBoundValue(material).getData()).to.equal(0.25); - }); - - it('Bind a shader input to a float value', () => { - const bindInput = shaderRef.addBindInput('roughness'); - bindInput.setValuefloat(0.5); - expect(roughness.getBoundValue(material).getData()).to.equal(0.5); - expect(roughness.getDefaultValue().getData()).to.equal(0.25); - }); - - let bindInput; - it('Bind a shader input to a color value', () => { - bindInput = shaderRef.addBindInput('specColor'); - bindInput.setValuecolor3(new mx.Color3(0.5, 0.5, 0.5)); - expect(specColor.getBoundValue(material).getData()).to.eql(new mx.Color3(0.5, 0.5, 0.5)); - expect(specColor.getDefaultValue().getData()).to.eql(new mx.Color3(0.0, 0.0, 0.0)); - }); - - it('Bind a shader input to a graph output', () => { - bindInput = shaderRef.addBindInput('diffColor'); - bindInput.setConnectedOutput(output2); - expect(diffColor.getUpstreamElement(material)).to.eql(output2); - expect(diffColor.getBoundValue(material)).to.be.null; - expect(diffColor.getDefaultValue().getData()).to.eql(new mx.Color3(1.0, 1.0, 1.0)); - }); - - it('Bind a shader token to a value', () => { - const bindToken = shaderRef.addBindToken('texId'); - bindToken.setValuestring('02'); - expect(texId.getBoundValue(material).getData()).to.equal('02'); - expect(texId.getDefaultValue().getData()).to.equal('01'); - }); - - it('Create an inherited material', () => { - const material2 = doc.addMaterial(); - material2.setInheritsFrom(material); - expect(roughness.getBoundValue(material2).getData()).to.equal(0.5); - expect(diffColor.getUpstreamElement(material2)).to.eql(output2); - }); - - let look; - it('Create a look for the material', () => { - look = doc.addLook(); - expect(doc.getLooks().length).to.equal(1); - }); - - it('Bind the material to a geometry string', () => { - const matAssign1 = look.addMaterialAssign('matAssign1', material.getName()); - matAssign1.setGeom('/robot1'); - expect(matAssign1.getReferencedMaterial()).to.eql(material); - expect(material.getGeometryBindings('/robot1').length).to.equal(1); - expect(material.getGeometryBindings('/robot2').length).to.equal(0); - }); - - it('Bind the material to a collection', () => { - const matAssign2 = look.addMaterialAssign('matAssign2', material.getName()); - const collection = doc.addCollection(); - collection.setIncludeGeom('/robot2'); - collection.setExcludeGeom('/robot2/left_arm'); - matAssign2.setCollection(collection); - expect(material.getGeometryBindings('/robot2').length).to.equal(1); - expect(material.getGeometryBindings('/robot2/right_arm').length).to.equal(1); - expect(material.getGeometryBindings('/robot2/left_arm').length).to.equal(0); - }); - - it('Create a property assignment', () => { - const propertyAssign = look.addPropertyAssign(); - propertyAssign.setProperty('twosided'); - propertyAssign.setGeom('/robot1'); - propertyAssign.setValueboolean(true); - expect(propertyAssign.getProperty()).to.equal('twosided'); - expect(propertyAssign.getGeom()).to.equal('/robot1'); - expect(propertyAssign.getValue().getData()).to.equal(true); - }); - - it('Create a property set assignment', () => { - const propertySet = doc.addPropertySet(); - propertySet._setPropertyValueboolean('matte', false, ''); - expect(propertySet._getPropertyValue('matte').getData()).to.be.false; - const propertySetAssign = look.addPropertySetAssign(); - propertySetAssign.setPropertySet(propertySet); - propertySetAssign.setGeom('/robot1'); - expect(propertySetAssign.getPropertySet()).to.eql(propertySet); - expect(propertySetAssign.getGeom()).to.equal('/robot1'); - }); - - it('Create a variant set', () => { - const variantSet = doc.addVariantSet(); - variantSet.addVariant('original'); - variantSet.addVariant('damaged'); - expect(variantSet.getVariants().length).to.equal(2); - }); - - it('Disconnect outputs from sources', () => { - output1.setConnectedNode(null); - output2.setConnectedNode(null); - expect(output1.getConnectedNode()).to.be.null; - expect(output2.getConnectedNode()).to.be.null; - }); + // let diffColor, specColor, roughness, texId; + // it('Create a simple shader interface', () => { + // const shaderDef = doc.addNodeDef('shader1', 'surfaceshader', 'simpleSrf'); + // diffColor = shaderDef.setInputValuecolor3('diffColor', new mx.Color3(1.0, 1.0, 1.0)); + // specColor = shaderDef.setInputValuecolor3('specColor', new mx.Color3(0.0, 0.0, 0.0)); + // roughness = shaderDef.setInputValuefloat('roughness', 0.25); + // texId = shaderDef.setTokenValue('texId', '01'); + // expect(roughness.getIsUniform()).to.equal(false); + // roughness.setIsUniform(true); + // expect(roughness.getIsUniform()).to.equal(true); + // expect(roughness.getValue().getData()).to.equal(0.25); + // }); + + // let material, shaderRef; + // it('Create a material that instantiates the shader', () => { + // material = doc.addMaterial(); + // shaderRef = material.addShaderRef('shaderRef1', 'simpleSrf'); + // expect(material.getPrimaryShaderName()).to.equal('simpleSrf'); + // expect(material.getPrimaryShaderInputs().length).to.equal(3); + // expect(material.getPrimaryShaderTokens().length).to.equal(1); + // expect(roughness.getBoundValue(material).getData()).to.equal(0.25); + // }); + + // it('Bind a shader input to a float value', () => { + // const bindInput = shaderRef.addBindInput('roughness'); + // bindInput.setValuefloat(0.5); + // expect(roughness.getBoundValue(material).getData()).to.equal(0.5); + // expect(roughness.getDefaultValue().getData()).to.equal(0.25); + // }); + + // let bindInput; + // it('Bind a shader input to a color value', () => { + // bindInput = shaderRef.addBindInput('specColor'); + // bindInput.setValuecolor3(new mx.Color3(0.5, 0.5, 0.5)); + // expect(specColor.getBoundValue(material).getData()).to.eql(new mx.Color3(0.5, 0.5, 0.5)); + // expect(specColor.getDefaultValue().getData()).to.eql(new mx.Color3(0.0, 0.0, 0.0)); + // }); + + // it('Bind a shader input to a graph output', () => { + // bindInput = shaderRef.addBindInput('diffColor'); + // bindInput.setConnectedOutput(output2); + // expect(diffColor.getUpstreamElement(material)).to.eql(output2); + // expect(diffColor.getBoundValue(material)).to.be.null; + // expect(diffColor.getDefaultValue().getData()).to.eql(new mx.Color3(1.0, 1.0, 1.0)); + // }); + + // it('Bind a shader token to a value', () => { + // const bindToken = shaderRef.addBindToken('texId'); + // bindToken.setValuestring('02'); + // expect(texId.getBoundValue(material).getData()).to.equal('02'); + // expect(texId.getDefaultValue().getData()).to.equal('01'); + // }); + + // it('Create an inherited material', () => { + // const material2 = doc.addMaterial(); + // material2.setInheritsFrom(material); + // expect(roughness.getBoundValue(material2).getData()).to.equal(0.5); + // expect(diffColor.getUpstreamElement(material2)).to.eql(output2); + // }); + + // let look; + // it('Create a look for the material', () => { + // look = doc.addLook(); + // expect(doc.getLooks().length).to.equal(1); + // }); + + // it('Bind the material to a geometry string', () => { + // const matAssign1 = look.addMaterialAssign('matAssign1', material.getName()); + // matAssign1.setGeom('/robot1'); + // expect(matAssign1.getReferencedMaterial()).to.eql(material); + // expect(material.getGeometryBindings('/robot1').length).to.equal(1); + // expect(material.getGeometryBindings('/robot2').length).to.equal(0); + // }); + + // it('Bind the material to a collection', () => { + // const matAssign2 = look.addMaterialAssign('matAssign2', material.getName()); + // const collection = doc.addCollection(); + // collection.setIncludeGeom('/robot2'); + // collection.setExcludeGeom('/robot2/left_arm'); + // matAssign2.setCollection(collection); + // expect(material.getGeometryBindings('/robot2').length).to.equal(1); + // expect(material.getGeometryBindings('/robot2/right_arm').length).to.equal(1); + // expect(material.getGeometryBindings('/robot2/left_arm').length).to.equal(0); + // }); + + // it('Create a property assignment', () => { + // const propertyAssign = look.addPropertyAssign(); + // propertyAssign.setProperty('twosided'); + // propertyAssign.setGeom('/robot1'); + // propertyAssign.setValueboolean(true); + // expect(propertyAssign.getProperty()).to.equal('twosided'); + // expect(propertyAssign.getGeom()).to.equal('/robot1'); + // expect(propertyAssign.getValue().getData()).to.equal(true); + // }); + + // it('Create a property set assignment', () => { + // const propertySet = doc.addPropertySet(); + // propertySet._setPropertyValueboolean('matte', false, ''); + // expect(propertySet._getPropertyValue('matte').getData()).to.be.false; + // const propertySetAssign = look.addPropertySetAssign(); + // propertySetAssign.setPropertySet(propertySet); + // propertySetAssign.setGeom('/robot1'); + // expect(propertySetAssign.getPropertySet()).to.eql(propertySet); + // expect(propertySetAssign.getGeom()).to.equal('/robot1'); + // }); + + // it('Create a variant set', () => { + // const variantSet = doc.addVariantSet(); + // variantSet.addVariant('original'); + // variantSet.addVariant('damaged'); + // expect(variantSet.getVariants().length).to.equal(2); + // }); + + // it('Disconnect outputs from sources', () => { + // output1.setConnectedNode(null); + // output2.setConnectedNode(null); + // expect(output1.getConnectedNode()).to.be.null; + // expect(output2.getConnectedNode()).to.be.null; + // }); }); diff --git a/source/JsMaterialX/test/readXml.spec.js b/source/JsMaterialX/test/readXml.spec.js index fbb97a0627..5c414605f9 100644 --- a/source/JsMaterialX/test/readXml.spec.js +++ b/source/JsMaterialX/test/readXml.spec.js @@ -55,23 +55,23 @@ describe('Build Document', () => { } expect(valueElementCount).to.be.greaterThan(0); - // Traverse upstream from each shader input. - const materials = doc.getMaterials(); - materials.forEach((material) => { - expect(material.getPrimaryShaderNodeDef()).to.exist; - let edgeCount = 0; + // // Traverse upstream from each shader input. + // const materials = doc.getMaterials(); + // materials.forEach((material) => { + // expect(material.getPrimaryShaderNodeDef()).to.exist; + // let edgeCount = 0; - const primaryShaderInputs = material.getPrimaryShaderInputs(); - primaryShaderInputs.forEach((shaderInput) => { - const boundValue = shaderInput.getBoundValue(material); - const upstreamElement = shaderInput.getUpstreamElement(material); - expect(boundValue !== null || upstreamElement !== null).to.be.true; - traverse(shaderInput.traverseGraph(material), () => { - edgeCount++; - }); - }); - expect(edgeCount).to.be.greaterThan(0); - }); + // const primaryShaderInputs = material.getPrimaryShaderInputs(); + // primaryShaderInputs.forEach((shaderInput) => { + // const boundValue = shaderInput.getBoundValue(material); + // const upstreamElement = shaderInput.getUpstreamElement(material); + // expect(boundValue !== null || upstreamElement !== null).to.be.true; + // traverse(shaderInput.traverseGraph(material), () => { + // edgeCount++; + // }); + // }); + // expect(edgeCount).to.be.greaterThan(0); + // }); // Serialize to XML. const writeOptions = new mx.XmlWriteOptions(); diff --git a/.travis.yml b/wasm_disabled.travis.yml similarity index 100% rename from .travis.yml rename to wasm_disabled.travis.yml From d4e5dcdbe9c1dbf7518e4de1bfa43fb46b689285 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 15 Dec 2020 14:59:49 -0500 Subject: [PATCH 33/35] Review fixes. --- source/MaterialXCore/Interface.cpp | 69 +++++++++++++++++------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index 1ec1f1fdf7..44088ec81c 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -239,26 +239,32 @@ OutputPtr Input::getConnectedOutput() const else if (hasNodeName()) { const string& nodeName = getNodeName(); - ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(nodeName) : nullptr; - if (!node && graph) + ConstElementPtr startingElement = getParent(); + if (startingElement) { - ConstElementPtr parent = graph->getParent(); - graph = parent->getAncestorOfType(); - node = graph ? graph->getNode(nodeName) : nullptr; - } - if (node) - { - std::vector outputs = node->getOutputs(); - if (!outputs.empty()) + // Look for a node reference above the nodegraph if input is a direct child. + if (startingElement->isA()) { - if (outputString.empty()) - { - result = outputs[0]; - } - else + startingElement = startingElement->getParent(); + } + if (startingElement) + { + ConstGraphElementPtr graph = startingElement->getAncestorOfType(); + NodePtr node = graph ? graph->getNode(nodeName) : nullptr; + if (node) { - result = node->getOutput(outputString); + std::vector outputs = node->getOutputs(); + if (!outputs.empty()) + { + if (outputString.empty()) + { + result = outputs[0]; + } + else + { + result = node->getOutput(outputString); + } + } } } } @@ -277,7 +283,7 @@ InputPtr Input::getInterface() const if (!interfaceName.empty()) { ConstNodeGraphPtr graph = getAncestorOfType(); - if (graph && !graph->hasNodeDefString()) + if (graph) { return graph->getInput(interfaceName); } @@ -303,19 +309,24 @@ NodePtr Input::getConnectedNode() const } if (hasNodeName()) { - // Check on current parent, and graph parent if any const string& nodeName = getNodeName(); - ConstGraphElementPtr graph = getAncestorOfType(); - NodePtr node = graph ? graph->getNode(nodeName) : nullptr; - if (!node && graph) - { - ConstElementPtr parent = graph->getParent(); - graph = parent->getAncestorOfType(); - node = graph ? graph->getNode(nodeName) : nullptr; - } - if (node) + ConstElementPtr startingElement = getParent(); + if (startingElement) { - return node; + // Look for a node reference above the nodegraph if input is a direct child. + if (startingElement->isA()) + { + startingElement = startingElement->getParent(); + } + if (startingElement) + { + ConstGraphElementPtr graph = startingElement->getAncestorOfType(); + NodePtr node = graph ? graph->getNode(nodeName) : nullptr; + if (node) + { + return node; + } + } } } return PortElement::getConnectedNode(); From a160b32518bba1d7ddfbb69d13974c3d61bdf968 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 15 Dec 2020 17:36:17 -0500 Subject: [PATCH 34/35] Review updates. --- .../stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx | 9 --------- source/MaterialXCore/Interface.cpp | 6 +++--- source/MaterialXCore/Interface.h | 2 +- source/MaterialXCore/Node.cpp | 4 ++-- source/MaterialXTest/MaterialXCore/Traversal.cpp | 2 +- 5 files changed, 7 insertions(+), 16 deletions(-) diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx index dd2ab4b33f..c91b8d8393 100644 --- a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx +++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/nodegraph_nodegraph.mtlx @@ -89,15 +89,6 @@ - diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index 44088ec81c..ffc84fafe2 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -277,7 +277,7 @@ OutputPtr Input::getConnectedOutput() const return result; } -InputPtr Input::getInterface() const +InputPtr Input::getConnectedInterface() const { const string& interfaceName = getInterfaceName(); if (!interfaceName.empty()) @@ -294,7 +294,7 @@ InputPtr Input::getInterface() const NodePtr Input::getConnectedNode() const { // Traverse through interface names to nodegraph input - InputPtr graphInput = getInterface(); + InputPtr graphInput = getConnectedInterface(); if (graphInput && (graphInput->hasNodeName() || graphInput->hasNodeGraphString())) { return graphInput->getConnectedNode(); @@ -350,7 +350,7 @@ bool Input::validate(string* message) const { validateRequire(getDefaultGeomProp() != nullptr, res, message, "Invalid defaultgeomprop string"); } - InputPtr interfaceInput = getInterface(); + InputPtr interfaceInput = getConnectedInterface(); if (interfaceInput) { return interfaceInput->validate() && res; diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index 9af1506b24..cb966968ed 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -220,7 +220,7 @@ class Input : public PortElement /// Return the input on the parent graph corresponding to the interface name /// for the element. - InputPtr getInterface() const; + InputPtr getConnectedInterface() const; /// Return the output, if any, to which this element is connected. OutputPtr getConnectedOutput() const; diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index 394ab25057..1f5f5fa373 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -145,7 +145,7 @@ OutputPtr Node::getNodeDefOutput(ElementPtr connectingElement) InputPtr interfaceInput = nullptr; if (connectedInput->hasInterfaceName()) { - interfaceInput = connectedInput->getInterface(); + interfaceInput = connectedInput->getConnectedInterface(); if (interfaceInput) { outputName = &(interfaceInput->getOutputString()); @@ -674,7 +674,7 @@ bool NodeGraph::validate(string* message) const const string& interfaceName = input->getInterfaceName(); if (!interfaceName.empty()) { - InputPtr interfaceInput = input->getInterface(); + InputPtr interfaceInput = input->getConnectedInterface(); validateRequire(interfaceInput != nullptr, res, message, "NodeGraph interface input: \"" + interfaceName + "\" does not exist on nodegraph"); string connectedNodeName = interfaceInput ? interfaceInput->getNodeName() : EMPTY_STRING; if (connectedNodeName.empty()) diff --git a/source/MaterialXTest/MaterialXCore/Traversal.cpp b/source/MaterialXTest/MaterialXCore/Traversal.cpp index ecdef65767..2b7f473a4d 100644 --- a/source/MaterialXTest/MaterialXCore/Traversal.cpp +++ b/source/MaterialXTest/MaterialXCore/Traversal.cpp @@ -191,7 +191,7 @@ TEST_CASE("InterGraph Tranversal", "[traversal]") { for (mx::InputPtr interfaceInput : graph->getInputs()) { - if (interfaceInput && (!interfaceInput->getNodeName().empty() || !interfaceInput->getNodeGraphString().empty())) + if (!interfaceInput->getNodeName().empty() || !interfaceInput->getNodeGraphString().empty()) { REQUIRE(interfaceInput->getConnectedNode() != nullptr); } From 12c481f47fcaea163992cb7c47daa1de9d4725c0 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 17 Dec 2020 15:39:16 -0500 Subject: [PATCH 35/35] Remove merge leftover. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 614e360407..c9a6fb21d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ # Change Log -<<<<<<< HEAD ## [1.38] - Development ### v1.38_adsk_development2 : WIP