From 1d066bb2e1d2c5c7ffc7ccea3bdcea271d940740 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 1 Aug 2024 12:16:10 -0400 Subject: [PATCH] Add code generation hints support (#1954) Initial implementation of code generation hints, as described in the 1.39 specification --- libraries/bxdf/open_pbr_surface.mtlx | 4 +-- .../surfaceshader/transparency_hints.mtlx | 15 ++++++++++ source/MaterialXCore/Definition.cpp | 13 +++++++++ source/MaterialXCore/Definition.h | 7 +++++ source/MaterialXCore/Interface.cpp | 4 +++ source/MaterialXCore/Interface.h | 26 +++++++++++++++++ source/MaterialXGenShader/Util.cpp | 29 +++++++++++++++---- 7 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 resources/Materials/TestSuite/pbrlib/surfaceshader/transparency_hints.mtlx diff --git a/libraries/bxdf/open_pbr_surface.mtlx b/libraries/bxdf/open_pbr_surface.mtlx index 8186482cf8..87084bf7fe 100644 --- a/libraries/bxdf/open_pbr_surface.mtlx +++ b/libraries/bxdf/open_pbr_surface.mtlx @@ -23,7 +23,7 @@ doc="Index of refraction of the dielectric base." /> - @@ -75,7 +75,7 @@ doc="The amount of emitted light, as a luminance in nits." /> - diff --git a/resources/Materials/TestSuite/pbrlib/surfaceshader/transparency_hints.mtlx b/resources/Materials/TestSuite/pbrlib/surfaceshader/transparency_hints.mtlx new file mode 100644 index 0000000000..0773e7e654 --- /dev/null +++ b/resources/Materials/TestSuite/pbrlib/surfaceshader/transparency_hints.mtlx @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp index 842330c95c..9bbaefb16a 100644 --- a/source/MaterialXCore/Definition.cpp +++ b/source/MaterialXCore/Definition.cpp @@ -100,6 +100,19 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const return InterfaceElementPtr(); } +const StringMap NodeDef::getInputHints() const +{ + StringMap hints; + for (InputPtr input : getActiveInputs()) + { + if (input->hasHint()) + { + hints[input->getName()] = input->getHint(); + } + } + return hints; +} + bool NodeDef::validate(string* message) const { bool res = true; diff --git a/source/MaterialXCore/Definition.h b/source/MaterialXCore/Definition.h index 9ec7251221..e3aecbe24a 100644 --- a/source/MaterialXCore/Definition.h +++ b/source/MaterialXCore/Definition.h @@ -146,6 +146,13 @@ class MX_CORE_API NodeDef : public InterfaceElement /// an Implementation element or a NodeGraph element. InterfaceElementPtr getImplementation(const string& target = EMPTY_STRING) const; + /// @} + /// @name Hints + /// @{ + + /// Return list of input hint pairs of the form { input_name, hint_string } + const StringMap getInputHints() const; + /// @} /// @name Validation /// @{ diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp index 6b200a8dcf..24d3ccfe0d 100644 --- a/source/MaterialXCore/Interface.cpp +++ b/source/MaterialXCore/Interface.cpp @@ -20,6 +20,10 @@ const string InterfaceElement::TARGET_ATTRIBUTE = "target"; const string InterfaceElement::VERSION_ATTRIBUTE = "version"; const string InterfaceElement::DEFAULT_VERSION_ATTRIBUTE = "isdefaultversion"; const string Input::DEFAULT_GEOM_PROP_ATTRIBUTE = "defaultgeomprop"; +const string Input::HINT_ATTRIBUTE = "hint"; +const string Input::TRANSPARENCY_HINT = "transparency"; +const string Input::OPACITY_HINT = "opacity"; +const string Input::ANISOTROPY_HINT = "anisotropy"; const string Output::DEFAULT_INPUT_ATTRIBUTE = "defaultinput"; // diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h index 39fd888b94..599f85ed9d 100644 --- a/source/MaterialXCore/Interface.h +++ b/source/MaterialXCore/Interface.h @@ -219,6 +219,28 @@ class MX_CORE_API Input : public PortElement /// for this input. InputPtr getInterfaceInput() const; + /// @} + /// @name Hints + /// @{ + + /// Return true if the input has a hint + bool hasHint() const + { + return hasAttribute(HINT_ATTRIBUTE); + } + + /// Return the code generation hint + const string& getHint() const + { + return getAttribute(HINT_ATTRIBUTE); + } + + // Set the code generation hint + void setHint(const string& hint) + { + setAttribute(HINT_ATTRIBUTE, hint); + } + /// @} /// @name Validation /// @{ @@ -232,6 +254,10 @@ class MX_CORE_API Input : public PortElement public: static const string CATEGORY; static const string DEFAULT_GEOM_PROP_ATTRIBUTE; + static const string HINT_ATTRIBUTE; + static const string TRANSPARENCY_HINT; + static const string OPACITY_HINT; + static const string ANISOTROPY_HINT; }; /// @class Output diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index 9722952390..af34fa1b2a 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -16,10 +16,10 @@ using OpaqueTestPair = std::pair; using OpaqueTestPairList = vector; // Inputs on a surface shader which are checked for transparency -const OpaqueTestPairList inputPairList = { { "opacity", 1.0f }, - { "existence", 1.0f }, - { "alpha", 1.0f }, - { "transmission", 0.0f } }; +const OpaqueTestPairList DEFAULT_INPUT_PAIR_LIST = { { "opacity", 1.0f }, + { "existence", 1.0f }, + { "alpha", 1.0f }, + { "transmission", 0.0f } }; const string MIX_CATEGORY("mix"); const string MIX_FG_INPUT("fg"); @@ -116,6 +116,23 @@ bool isTransparentShaderNode(NodePtr node, NodePtr interfaceNode) return false; } + // Check against nodedef input hints + OpaqueTestPairList inputPairList = DEFAULT_INPUT_PAIR_LIST; + NodeDefPtr nodeDef = node->getNodeDef(); + StringMap nodeDefList = nodeDef ? nodeDef->getInputHints() : StringMap(); + for (auto &item : nodeDefList) + { + string inputName = item.first; + if (item.second == Input::TRANSPARENCY_HINT) + { + inputPairList.push_back(std::make_pair(inputName, 0.0f) ); + } + else if (item.second == Input::OPACITY_HINT) + { + inputPairList.push_back(std::make_pair(inputName, 1.0f)); + } + } + // Check against the interface if a node is passed in to check against OpaqueTestPairList interfaceNames; if (interfaceNode) @@ -167,8 +184,8 @@ bool isTransparentShaderNode(NodePtr node, NodePtr interfaceNode) NodePtr inputNode = checkInput->getConnectedNode(); if (inputNode) { - NodeDefPtr nodeDef = inputNode->getNodeDef(); - string nodeGroup = nodeDef ? nodeDef->getAttribute(NodeDef::NODE_GROUP_ATTRIBUTE) : EMPTY_STRING; + NodeDefPtr inputNodeDef = inputNode->getNodeDef(); + string nodeGroup = inputNodeDef ? inputNodeDef->getAttribute(NodeDef::NODE_GROUP_ATTRIBUTE) : EMPTY_STRING; if (nodeGroup != NodeDef::ADJUSTMENT_NODE_GROUP && nodeGroup != NodeDef::CHANNEL_NODE_GROUP) {