diff --git a/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx new file mode 100644 index 0000000000..4fbf6d12d9 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx index 3cb8eb6237..66dc69f668 100644 --- a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx @@ -4,61 +4,110 @@ Examples of MaterialX 1.37 syntax --> - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 0449189873..80143bb9c8 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -1040,39 +1040,7 @@ void Document::upgradeVersion() } } - // Update atan2 interface and rotate3d interface - const string ATAN2 = "atan2"; - const string IN1 = "in1"; - const string IN2 = "in2"; - const string ROTATE3D = "rotate3d"; - const string AXIS = "axis"; - const string INPUT_ONE = "1.0"; - - // Update nodedefs - bool upgradeAtan2Instances = false; - for (auto nodedef : getMatchingNodeDefs(ATAN2)) - { - InputPtr input = nodedef->getInput(IN1); - InputPtr input2 = nodedef->getInput(IN2); - string inputValue = input->getValueString(); - // Only flip value if nodedef value is the previous versions. - if (inputValue == INPUT_ONE) - { - input->setValueString(input2->getValueString()); - input2->setValueString(inputValue); - upgradeAtan2Instances = true; - } - } - for (auto nodedef : getMatchingNodeDefs(ROTATE3D)) - { - ElementPtr axis = nodedef->getChild(AXIS); - if (axis) - { - nodedef->changeChildCategory(axis, "input"); - } - } - - // Update BSDF interfaces + // Define BSDF node pairs. using StringPair = std::pair; const StringPair DIELECTRIC_BRDF = { "dielectric_brdf", "dielectric_bsdf" }; const StringPair DIELECTRIC_BTDF = { "dielectric_btdf", "dielectric_bsdf" }; @@ -1085,57 +1053,11 @@ void Document::upgradeVersion() const StringPair SUBSURFACE_BRDF = { "subsurface_brdf", "subsurface_bsdf" }; const StringPair THIN_FILM_BRDF = { "thin_film_brdf", "thin_film_bsdf" }; - const string SCATTER_MODE = "scatter_mode"; - const string BSDF = "BSDF"; - const string LAYER = "layer"; - const string TOP = "top"; - const string BASE = "base"; - const string INTERIOR = "interior"; - const string ARTISTIC_IOR = "artistic_ior"; - const string COMPLEX_IOR = "complex_ior"; - const string REFLECTIVITY = "reflectivity"; - const string EDGE_COLOR = "edge_color"; - const string IOR = "ior"; - const string EXTINCTION = "extinction"; - const string COLOR3 = "color3"; - const string VECTOR3 = "vector3"; - const string CONVERT = "convert"; - const string IN = "in"; - - // Function for upgrading BSDF nodedef. - auto upgradeBsdfNodeDef = [SCATTER_MODE](NodeDefPtr nodedef, const string& newCategory, bool addScatterMode = false) - { - if (nodedef) - { - nodedef->setName(newCategory); - if (addScatterMode) - { - InputPtr mode = nodedef->addInput(SCATTER_MODE, STRING_TYPE_STRING); - mode->setIsUniform(true); - mode->setValueString("R"); - mode->setAttribute("enum", "R,T,RT"); - } - } - }; - - // Update nodedefs. - upgradeBsdfNodeDef(getNodeDef(DIELECTRIC_BRDF.first), DIELECTRIC_BRDF.second, true); - upgradeBsdfNodeDef(getNodeDef(GENERALIZED_SCHLICK_BRDF.first), GENERALIZED_SCHLICK_BRDF.second, true); - upgradeBsdfNodeDef(getNodeDef(CONDUCTOR_BRDF.first), CONDUCTOR_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(SHEEN_BRDF.first), SHEEN_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BRDF.first), DIFFUSE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(BURLEY_DIFFUSE_BRDF.first), BURLEY_DIFFUSE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BTDF.first), DIFFUSE_BTDF.second); - upgradeBsdfNodeDef(getNodeDef(SUBSURFACE_BRDF.first), SUBSURFACE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(THIN_FILM_BRDF.first), THIN_FILM_BRDF.second); - removeNodeDef(DIELECTRIC_BTDF.first); - removeNodeDef(COMPLEX_IOR); - // Function for upgrading old nested layering setup // to new setup with layer operators. - auto upgradeBsdfLayering = [TOP, BASE, LAYER, BSDF](NodePtr node) + auto upgradeBsdfLayering = [](NodePtr node) { - InputPtr base = node->getInput(BASE); + InputPtr base = node->getInput("base"); if (base) { NodePtr baseNode = base->getConnectedNode(); @@ -1146,13 +1068,13 @@ void Document::upgradeVersion() // so we don't need to update any connection references. const string oldName = node->getName(); node->setName(oldName + "__layer_top"); - NodePtr layer = parent->addNode(LAYER, oldName, BSDF); - InputPtr layerTop = layer->addInput(TOP, BSDF); - InputPtr layerBase = layer->addInput(BASE, BSDF); + NodePtr layer = parent->addNode("layer", oldName, "BSDF"); + InputPtr layerTop = layer->addInput("top", "BSDF"); + InputPtr layerBase = layer->addInput("base", "BSDF"); layerTop->setConnectedNode(node); layerBase->setConnectedNode(baseNode); } - node->removeInput(BASE); + node->removeInput("base"); } }; @@ -1177,31 +1099,31 @@ void Document::upgradeVersion() continue; } const string& nodeCategory = node->getCategory(); - if (upgradeAtan2Instances && nodeCategory == ATAN2) + if (nodeCategory == "atan2") { - InputPtr input = node->getInput(IN1); - InputPtr input2 = node->getInput(IN2); + InputPtr input = node->getInput("in1"); + InputPtr input2 = node->getInput("in2"); if (input && input2) { input->setName(EMPTY_STRING); - input2->setName(IN1); - input->setName(IN2); + input2->setName("in1"); + input->setName("in2"); } else { if (input) { - input->setName(IN2); + input->setName("in2"); } if (input2) { - input2->setName(IN1); + input2->setName("in1"); } } } - else if (nodeCategory == ROTATE3D) + else if (nodeCategory == "rotate3d") { - ElementPtr axis = node->getChild(AXIS); + ElementPtr axis = node->getChild("axis"); if (axis) { node->changeChildCategory(axis, "input"); @@ -1215,8 +1137,8 @@ void Document::upgradeVersion() else if (nodeCategory == DIELECTRIC_BTDF.first) { node->setCategory(DIELECTRIC_BTDF.second); - node->removeInput(INTERIOR); - InputPtr mode = node->addInput(SCATTER_MODE, STRING_TYPE_STRING); + node->removeInput("interior"); + InputPtr mode = node->addInput("scatter_mode", STRING_TYPE_STRING); mode->setValueString("T"); } else if (nodeCategory == GENERALIZED_SCHLICK_BRDF.first) @@ -1240,32 +1162,32 @@ void Document::upgradeVersion() // Create an artistic_ior node to convert from artistic to physical parameterization. GraphElementPtr parent = node->getParent()->asA(); - NodePtr artisticIor = parent->addNode(ARTISTIC_IOR, node->getName() + "__artistic_ior", "multioutput"); - OutputPtr artisticIor_ior = artisticIor->addOutput(IOR, COLOR3); - OutputPtr artisticIor_extinction = artisticIor->addOutput(EXTINCTION, COLOR3); + NodePtr artisticIor = parent->addNode("artistic_ior", node->getName() + "__artistic_ior", "multioutput"); + OutputPtr artisticIor_ior = artisticIor->addOutput("ior", "color3"); + OutputPtr artisticIor_extinction = artisticIor->addOutput("extinction", "color3"); // Copy values and connections from conductor node to artistic_ior node. - InputPtr reflectivity = node->getInput(REFLECTIVITY); + InputPtr reflectivity = node->getInput("reflectivity"); if (reflectivity) { - InputPtr artisticIor_reflectivity = artisticIor->addInput(REFLECTIVITY, COLOR3); + InputPtr artisticIor_reflectivity = artisticIor->addInput("reflectivity", "color3"); copyAttributes(reflectivity, artisticIor_reflectivity); } - InputPtr edge_color = node->getInput(EDGE_COLOR); + InputPtr edge_color = node->getInput("edge_color"); if (edge_color) { - InputPtr artisticIor_edge_color = artisticIor->addInput(EDGE_COLOR, COLOR3); + InputPtr artisticIor_edge_color = artisticIor->addInput("edge_color", "color3"); copyAttributes(edge_color, artisticIor_edge_color); } // Update the parameterization on the conductor node // and connect it to the artistic_ior node. - node->removeInput(REFLECTIVITY); - node->removeInput(EDGE_COLOR); - InputPtr ior = node->addInput(IOR, COLOR3); + node->removeInput("reflectivity"); + node->removeInput("edge_color"); + InputPtr ior = node->addInput("ior", "color3"); ior->setNodeName(artisticIor->getName()); ior->setOutputString(artisticIor_ior->getName()); - InputPtr extinction = node->addInput(EXTINCTION, COLOR3); + InputPtr extinction = node->addInput("extinction", "color3"); extinction->setNodeName(artisticIor->getName()); extinction->setOutputString(artisticIor_extinction->getName()); } @@ -1285,17 +1207,17 @@ void Document::upgradeVersion() { node->setCategory(SUBSURFACE_BRDF.second); } - else if (nodeCategory == ARTISTIC_IOR) + else if (nodeCategory == "artistic_ior") { - OutputPtr ior = node->getOutput(IOR); + OutputPtr ior = node->getOutput("ior"); if (ior) { - ior->setType(COLOR3); + ior->setType("color3"); } - OutputPtr extinction = node->getOutput(EXTINCTION); + OutputPtr extinction = node->getOutput("extinction"); if (extinction) { - extinction->setType(COLOR3); + extinction->setType("color3"); } } @@ -1306,18 +1228,18 @@ void Document::upgradeVersion() // since we can't modify the graph while traversing it. for (InputPtr input : node->getInputs()) { - if (input->getOutputString() == IOR && input->getType() == VECTOR3) + if (input->getOutputString() == "ior" && input->getType() == "vector3") { NodePtr connectedNode = input->getConnectedNode(); - if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR) + if (connectedNode && connectedNode->getCategory() == "artistic_ior") { artisticIorConnections.push_back(input); } } - else if (input->getOutputString() == EXTINCTION && input->getType() == VECTOR3) + else if (input->getOutputString() == "extinction" && input->getType() == "vector3") { NodePtr connectedNode = input->getConnectedNode(); - if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR) + if (connectedNode && connectedNode->getCategory() == "artistic_ior") { artisticExtConnections.push_back(input); } @@ -1331,10 +1253,10 @@ void Document::upgradeVersion() NodePtr artisticIorNode = input->getConnectedNode(); ElementPtr node = input->getParent(); GraphElementPtr parent = node->getParent()->asA(); - NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_ior", VECTOR3); - InputPtr convertInput = convert->addInput(IN, COLOR3); + NodePtr convert = parent->addNode("convert", node->getName() + "__convert_ior", "vector3"); + InputPtr convertInput = convert->addInput("in", "color3"); convertInput->setNodeName(artisticIorNode->getName()); - convertInput->setOutputString(IOR); + convertInput->setOutputString("ior"); input->setNodeName(convert->getName()); input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE); } @@ -1343,10 +1265,10 @@ void Document::upgradeVersion() NodePtr artisticIorNode = input->getConnectedNode(); ElementPtr node = input->getParent(); GraphElementPtr parent = node->getParent()->asA(); - NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_extinction", VECTOR3); - InputPtr convertInput = convert->addInput(IN, COLOR3); + NodePtr convert = parent->addNode("convert", node->getName() + "__convert_extinction", "vector3"); + InputPtr convertInput = convert->addInput("in", "color3"); convertInput->setNodeName(artisticIorNode->getName()); - convertInput->setOutputString(EXTINCTION); + convertInput->setOutputString("extinction"); input->setNodeName(convert->getName()); input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE); } diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index 839f591aa5..ec5e48d4ec 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -23,9 +22,6 @@ #include #include #include -#include -#include -#include #include #include @@ -34,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -174,8 +172,8 @@ GlslShaderGenerator::GlslShaderGenerator() : // registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, BitangentNodeGlsl::create); // - registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create); - registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create); + registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); + registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); // registerImplementation("IM_geomcolor_float_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create); registerImplementation("IM_geomcolor_color3_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create); @@ -228,13 +226,13 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation(elementNames, BlurNodeGlsl::create); // elementNames = { @@ -902,11 +900,6 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, } const string GlslImplementation::SPACE = "space"; -const string GlslImplementation::TO_SPACE = "tospace"; -const string GlslImplementation::FROM_SPACE = "fromspace"; -const string GlslImplementation::WORLD = "world"; -const string GlslImplementation::OBJECT = "object"; -const string GlslImplementation::MODEL = "model"; const string GlslImplementation::INDEX = "index"; const string GlslImplementation::GEOMPROP = "geomprop"; diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h index 1df2ace543..acc8b0d6ee 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.h +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h @@ -45,7 +45,7 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override; /// Determine the prefix of vertex data variables. - virtual string getVertexDataPrefix(const VariableBlock& vertexData) const; + string getVertexDataPrefix(const VariableBlock& vertexData) const override; public: /// Unique identifier for this generator target @@ -110,11 +110,6 @@ class MX_GENGLSL_API GlslImplementation : public ShaderNodeImpl /// Internal string constants static const string SPACE; - static const string TO_SPACE; - static const string FROM_SPACE; - static const string WORLD; - static const string OBJECT; - static const string MODEL; static const string INDEX; static const string GEOMPROP; }; diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp deleted file mode 100644 index 846c77f5b7..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TexCoordNodeGlsl::create() -{ - return std::make_shared(); -} - -void TexCoordNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderOutput* output = node.getOutput(); - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs); - addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps); -} - -void TexCoordNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - const string variable = HW::T_TEXCOORD + "_" + index; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - if (!texcoord->isEmitted()) - { - shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); - texcoord->setEmitted(); - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp deleted file mode 100644 index 0800fb4bf3..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformNormalNodeGlsl::create() -{ - return std::make_shared(); -} - -void TransformNormalNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - TransformVectorNodeGlsl::emitFunctionCall(node, context, stage); - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - const ShaderOutput* output = node.getOutput(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(output, false, false, context, stage); - shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformNormalNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_TRANSPOSE_MATRIX; - } - return EMPTY_STRING; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h deleted file mode 100644 index f08ec564d9..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMNORMALNODEGLSL_H -#define MATERIALX_TRANSFORMNORMALNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformNormal node implementation for GLSL -class MX_GENGLSL_API TransformNormalNodeGlsl : public TransformVectorNodeGlsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - const string& getMatrix(const string& fromSpace, const string& toSpace) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp deleted file mode 100644 index 1570939bfe..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformPointNodeGlsl::create() -{ - return std::make_shared(); -} - -string TransformPointNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h deleted file mode 100644 index eb366d8190..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMPOINTNODEGLSL_H -#define MATERIALX_TRANSFORMPOINTNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformPoint node implementation for GLSL -class MX_GENGLSL_API TransformPointNodeGlsl : public TransformVectorNodeGlsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp deleted file mode 100644 index df1e921497..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformVectorNodeGlsl::create() -{ - return std::make_shared(); -} - -void TransformVectorNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); - } -} - -void TransformVectorNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - - const ShaderInput* inInput = node.getInput("in"); - if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) - { - throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); - } - - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = (", stage); - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - shadergen.emitString(matrix + " * ", stage); - } - shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage); - shadergen.emitString(").xyz", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformVectorNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_INVERSE_MATRIX; - } - return EMPTY_STRING; -} - -string TransformVectorNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h deleted file mode 100644 index e9861650b3..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMVECTORNODEGLSL_H -#define MATERIALX_TRANSFORMVECTORNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformVector node implementation for GLSL -class MX_GENGLSL_API TransformVectorNodeGlsl : public GlslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - protected: - virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 0d97e8408f..ea3fb7112d 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -23,9 +22,6 @@ #include #include #include -#include -#include -#include #include #include @@ -34,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,8 +176,8 @@ MslShaderGenerator::MslShaderGenerator() : // registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, BitangentNodeMsl::create); // - registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create); - registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create); + registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); + registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); // registerImplementation("IM_geomcolor_float_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create); registerImplementation("IM_geomcolor_color3_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create); @@ -232,13 +230,13 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation(elementNames, BlurNodeMsl::create); // elementNames = { @@ -1404,11 +1402,6 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, } const string MslImplementation::SPACE = "space"; -const string MslImplementation::TO_SPACE = "tospace"; -const string MslImplementation::FROM_SPACE = "fromspace"; -const string MslImplementation::WORLD = "world"; -const string MslImplementation::OBJECT = "object"; -const string MslImplementation::MODEL = "model"; const string MslImplementation::INDEX = "index"; const string MslImplementation::GEOMPROP = "geomprop"; diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h index ecbf37d7a6..21817db735 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.h +++ b/source/MaterialXGenMsl/MslShaderGenerator.h @@ -48,7 +48,7 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override; /// Determine the prefix of vertex data variables. - virtual string getVertexDataPrefix(const VariableBlock& vertexData) const; + string getVertexDataPrefix(const VariableBlock& vertexData) const override; public: /// Unique identifier for this generator target @@ -137,11 +137,6 @@ class MX_GENMSL_API MslImplementation : public ShaderNodeImpl /// Internal string constants static const string SPACE; - static const string TO_SPACE; - static const string FROM_SPACE; - static const string WORLD; - static const string OBJECT; - static const string MODEL; static const string INDEX; static const string GEOMPROP; }; diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp deleted file mode 100644 index a88152eb82..0000000000 --- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TexCoordNodeMsl::create() -{ - return std::make_shared(); -} - -void TexCoordNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderOutput* output = node.getOutput(); - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs); - addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps); -} - -void TexCoordNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - const string variable = HW::T_TEXCOORD + "_" + index; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - if (!texcoord->isEmitted()) - { - shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); - texcoord->setEmitted(); - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h deleted file mode 100644 index 6c227cc63b..0000000000 --- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TEXCOORDNODEMSL_H -#define MATERIALX_TEXCOORDNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TexCoord node implementation for MSL -class MX_GENMSL_API TexCoordNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp deleted file mode 100644 index 98810c025b..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformNormalNodeMsl::create() -{ - return std::make_shared(); -} - -void TransformNormalNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - TransformVectorNodeMsl::emitFunctionCall(node, context, stage); - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - const ShaderOutput* output = node.getOutput(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(output, false, false, context, stage); - shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformNormalNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_TRANSPOSE_MATRIX; - } - return EMPTY_STRING; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h deleted file mode 100644 index 603ba3771c..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMNORMALNODEMSL_H -#define MATERIALX_TRANSFORMNORMALNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformNormal node implementation for MSL -class MX_GENMSL_API TransformNormalNodeMsl : public TransformVectorNodeMsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - const string& getMatrix(const string& fromSpace, const string& toSpace) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp deleted file mode 100644 index 38db776855..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformPointNodeMsl::create() -{ - return std::make_shared(); -} - -string TransformPointNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "float4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h deleted file mode 100644 index 9fc2361d7d..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMPOINTNODEMSL_H -#define MATERIALX_TRANSFORMPOINTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformPoint node implementation for MSL -class MX_GENMSL_API TransformPointNodeMsl : public TransformVectorNodeMsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp deleted file mode 100644 index c5d6ce242a..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformVectorNodeMsl::create() -{ - return std::make_shared(); -} - -void TransformVectorNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); - } -} - -void TransformVectorNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - - const ShaderInput* inInput = node.getInput("in"); - if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) - { - throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); - } - - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = (", stage); - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - shadergen.emitString(matrix + " * ", stage); - } - shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage); - shadergen.emitString(").xyz", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformVectorNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_INVERSE_MATRIX; - } - return EMPTY_STRING; -} - -string TransformVectorNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "float4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h deleted file mode 100644 index 013a3db29a..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMVECTORNODEMSL_H -#define MATERIALX_TRANSFORMVECTORNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformVector node implementation for MSL -class MX_GENMSL_API TransformVectorNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - protected: - virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp index 28ada48626..fbb2bb29be 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.cpp +++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp @@ -294,6 +294,25 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G emitLineBreak(stage); } + // Inputs of type 'filename' has been generated into two shader inputs. + // So here we construct a single 'textureresource' from these inputs, + // to be used further downstream. See emitShaderInputs() for details. + VariableBlock& inputs = stage.getUniformBlock(OSL::UNIFORMS); + for (size_t i = 0; i < inputs.size(); ++i) + { + ShaderPort* input = inputs[i]; + if (input->getType() == Type::FILENAME) + { + // Construct the textureresource variable. + const string newVariableName = input->getVariable() + "_"; + const string& type = _syntax->getTypeName(input->getType()); + emitLine(type + newVariableName + " = {" + input->getVariable() + ", " + input->getVariable() + "_colorspace}", stage); + + // Update the variable name to be used downstream. + input->setVariable(newVariableName); + } + } + // Emit all texturing nodes. These are inputs to any // closure/shader nodes and need to be emitted first. emitFunctionCalls(graph, context, stage, ShaderNode::Classification::TEXTURE); @@ -489,111 +508,75 @@ void OslShaderGenerator::emitLibraryIncludes(ShaderStage& stage, GenContext& con emitLineBreak(stage); } -namespace -{ - -std::unordered_map GEOMPROP_DEFINITIONS = -{ - { "Pobject", "transform(\"object\", P)" }, - { "Pworld", "P" }, - { "Nobject", "transform(\"object\", N)" }, - { "Nworld", "N" }, - { "Tobject", "transform(\"object\", dPdu)" }, - { "Tworld", "dPdu" }, - { "Bobject", "transform(\"object\", dPdv)" }, - { "Bworld", "dPdv" }, - { "UV0", "{u,v}" }, - { "Vworld", "I" } -}; - -} // anonymous namespace - void OslShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const { - const std::unordered_map UI_WIDGET_METADATA = - { - { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, - { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, - { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) }, - { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) } - }; - - const std::set METADATA_TYPE_BLACKLIST = + static const std::unordered_map GEOMPROP_DEFINITIONS = { - Type::VECTOR2, // Custom struct types doesn't support metadata declarations. - Type::VECTOR4, // - Type::COLOR4, // - Type::FILENAME, // - Type::BSDF // + { "Pobject", "transform(\"object\", P)" }, + { "Pworld", "P" }, + { "Nobject", "transform(\"object\", N)" }, + { "Nworld", "N" }, + { "Tobject", "transform(\"object\", dPdu)" }, + { "Tworld", "dPdu" }, + { "Bobject", "transform(\"object\", dPdv)" }, + { "Bworld", "dPdv" }, + { "UV0", "{u,v}" }, + { "Vworld", "I" } }; for (size_t i = 0; i < inputs.size(); ++i) { const ShaderPort* input = inputs[i]; - const string& type = _syntax->getTypeName(input->getType()); - string value = _syntax->getValue(input, true); - - emitLineBegin(stage); - emitString(type + " " + input->getVariable(), stage); - const string& geomprop = input->getGeomProp(); - if (!geomprop.empty()) + if (input->getType() == Type::FILENAME) { - auto it = GEOMPROP_DEFINITIONS.find(geomprop); - if (it != GEOMPROP_DEFINITIONS.end()) - { - value = it->second; - } + // Shader inputs of type 'filename' (textures) need special handling. + // In OSL codegen a 'filename' is translated to the custom type 'textureresource', + // which is a struct containing a file string and a colorspace string. + // For the published shader interface we here split this into two separate inputs, + // which gives a nicer shader interface with widget metadata on each input. + + ValuePtr value = input->getValue(); + const string valueStr = value ? value->getValueString() : EMPTY_STRING; + + // Add the file string input + emitLineBegin(stage); + emitString("string " + input->getVariable() + " = \"" + valueStr + "\"", stage); + emitMetadata(input, stage); + emitString(",", stage); + emitLineEnd(stage, false); + + // Add the colorspace string input + emitLineBegin(stage); + emitString("string " + input->getVariable() + "_colorspace = \"" + input->getColorSpace() + "\"", stage); + emitLineEnd(stage, false); + emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); + emitLine("string widget = \"colorspace\"", stage, false); + emitScopeEnd(stage, false, false); } - - if (value.empty()) + else { - value = _syntax->getDefaultValue(input->getType()); - } - emitString(" = " + value, stage); - - // - // Add shader input metadata. - // - - auto widgetMetadataIt = UI_WIDGET_METADATA.find(input->getType()); - const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr; - const ShaderMetadataVecPtr& metadata = input->getMetadata(); + emitLineBegin(stage); + emitString(type + " " + input->getVariable(), stage); - if (widgetMetadata || (metadata && metadata->size())) - { - StringVec metadataLines; - if (metadata) + string value = _syntax->getValue(input, true); + const string& geomprop = input->getGeomProp(); + if (!geomprop.empty()) { - for (size_t j = 0; j < metadata->size(); ++j) + auto it = GEOMPROP_DEFINITIONS.find(geomprop); + if (it != GEOMPROP_DEFINITIONS.end()) { - const ShaderMetadata& data = metadata->at(j); - if (METADATA_TYPE_BLACKLIST.count(data.type) == 0) - { - const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING; - const string& dataType = _syntax->getTypeName(data.type); - const string dataValue = _syntax->getValue(data.type, *data.value, true); - metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim); - } + value = it->second; } } - if (widgetMetadata) + if (value.empty()) { - const string& dataType = _syntax->getTypeName(widgetMetadata->type); - const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true); - metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue); - } - if (metadataLines.size()) - { - emitLineEnd(stage, false); - emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); - for (auto line : metadataLines) - { - emitLine(line, stage, false); - } - emitScopeEnd(stage, false, false); + value = _syntax->getDefaultValue(input->getType()); } + + emitString(" = " + value, stage); + emitMetadata(input, stage); } if (i < inputs.size()) @@ -618,6 +601,65 @@ void OslShaderGenerator::emitShaderOutputs(const VariableBlock& outputs, ShaderS } } +void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage) const +{ + static const std::unordered_map UI_WIDGET_METADATA = + { + { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, + { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, + { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) }, + { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) } + }; + + static const std::set METADATA_TYPE_BLACKLIST = + { + Type::VECTOR2, // Custom struct types doesn't support metadata declarations. + Type::VECTOR4, // + Type::COLOR4, // + Type::FILENAME, // + Type::BSDF // + }; + + auto widgetMetadataIt = UI_WIDGET_METADATA.find(port->getType()); + const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr; + const ShaderMetadataVecPtr& metadata = port->getMetadata(); + + if (widgetMetadata || (metadata && metadata->size())) + { + StringVec metadataLines; + if (metadata) + { + for (size_t j = 0; j < metadata->size(); ++j) + { + const ShaderMetadata& data = metadata->at(j); + if (METADATA_TYPE_BLACKLIST.count(data.type) == 0) + { + const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING; + const string& dataType = _syntax->getTypeName(data.type); + const string dataValue = _syntax->getValue(data.type, *data.value, true); + metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim); + } + } + } + if (widgetMetadata) + { + const string& dataType = _syntax->getTypeName(widgetMetadata->type); + const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true); + metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue); + } + if (metadataLines.size()) + { + emitLineEnd(stage, false); + emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); + for (auto line : metadataLines) + { + emitLine(line, stage, false); + } + emitScopeEnd(stage, false, false); + } + } +} + namespace OSL { diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h index 0c7ca426d7..e5cf13977e 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.h +++ b/source/MaterialXGenOsl/OslShaderGenerator.h @@ -59,6 +59,9 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator /// Emit a block of shader outputs. virtual void emitShaderOutputs(const VariableBlock& inputs, ShaderStage& stage) const; + + /// Emit metadata for a shader parameter. + virtual void emitMetadata(const ShaderPort* port, ShaderStage& stage) const; }; namespace OSL diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h index 66d60dc68a..bba572c631 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.h +++ b/source/MaterialXGenShader/HwShaderGenerator.h @@ -306,6 +306,9 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator /// Unbind all light shaders previously bound. static void unbindLightShaders(GenContext& context); + /// Determine the prefix of vertex data variables. + virtual string getVertexDataPrefix(const VariableBlock& vertexData) const = 0; + /// Types of closure contexts for HW. enum ClosureContextType { diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp new file mode 100644 index 0000000000..3aa84400df --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp @@ -0,0 +1,83 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +string HwTexCoordNode::INDEX = "index"; + +ShaderNodeImplPtr HwTexCoordNode::create() +{ + return std::make_shared(); +} + +void HwTexCoordNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +{ + const ShaderOutput* output = node.getOutput(); + const string index = getIndex(node); + + ShaderStage& vs = shader.getStage(Stage::VERTEX); + ShaderStage& ps = shader.getStage(Stage::PIXEL); + + addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs, true); + addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps, true); +} + +void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + + const string index = getIndex(node); + const string variable = HW::T_TEXCOORD + "_" + index; + const ShaderOutput* output = node.getOutput(); + + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { + VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* texcoord = vertexData[variable]; + if (!texcoord->isEmitted()) + { + shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); + texcoord->setEmitted(); + } + } + + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* texcoord = vertexData[variable]; + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + + // Extract the requested number of components from the texture coordinates (which may be a + // larger datatype than the requested number of texture coordinates, if several texture + // coordinate nodes with different width coexist). + string suffix = EMPTY_STRING; + if (output->getType() == Type::VECTOR2) + { + suffix = ".xy"; + } + else if (output->getType() == Type::VECTOR3) + { + suffix = ".xyz"; + } + + shadergen.emitString(" = " + prefix + texcoord->getVariable() + suffix, stage); + shadergen.emitLineEnd(stage); + } +} + +string HwTexCoordNode::getIndex(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(INDEX); + return input ? input->getValue()->getValueString() : "0"; +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h similarity index 55% rename from source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwTexCoordNode.h index c15a86fd9c..9aae3d18ce 100644 --- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_TEXCOORDNODEGLSL_H -#define MATERIALX_TEXCOORDNODEGLSL_H +#ifndef MATERIALX_HWTEXCOORDNODE_H +#define MATERIALX_HWTEXCOORDNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// TexCoord node implementation for GLSL -class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation +/// Generic texture coordinate node for hardware languages +class MX_GENSHADER_API HwTexCoordNode : public ShaderNodeImpl { public: static ShaderNodeImplPtr create(); @@ -19,6 +19,11 @@ class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; + + protected: + virtual string getIndex(const ShaderNode& node) const; + + static string INDEX; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.cpp b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp new file mode 100644 index 0000000000..018924855d --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp @@ -0,0 +1,110 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string HwTransformNode::FROM_SPACE = "fromspace"; +const string HwTransformNode::TO_SPACE = "tospace"; +const string HwTransformNode::MODEL = "model"; +const string HwTransformNode::OBJECT = "object"; +const string HwTransformNode::WORLD = "world"; + +void HwTransformNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +{ + const string toSpace = getToSpace(node); + const string fromSpace = getFromSpace(node); + const string& matrix = getMatrix(fromSpace, toSpace); + if (!matrix.empty()) + { + ShaderStage& ps = shader.getStage(Stage::PIXEL); + addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); + } +} + +void HwTransformNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + const ShaderGenerator& shadergen = context.getShaderGenerator(); + + const ShaderOutput* output = node.getOutput(); + const ShaderInput* inInput = node.getInput("in"); + if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) + { + throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); + } + + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = (", stage); + + const string toSpace = getToSpace(node); + const string fromSpace = getFromSpace(node); + const string& matrix = getMatrix(fromSpace, toSpace); + if (!matrix.empty()) + { + shadergen.emitString(matrix + " * ", stage); + } + + const string type = shadergen.getSyntax().getTypeName(Type::VECTOR4); + const string input = shadergen.getUpstreamResult(inInput, context); + shadergen.emitString(type + "(" + input + ", " + getHomogeneousCoordinate() + ")).xyz", stage); + shadergen.emitLineEnd(stage); + + if (shouldNormalize()) + { + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, false, false, context, stage); + shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); + shadergen.emitLineEnd(stage); + } + } +} + +string HwTransformNode::getFromSpace(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(FROM_SPACE); + return input ? input->getValueString() : EMPTY_STRING; +} + +string HwTransformNode::getToSpace(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(TO_SPACE); + return input ? input->getValueString() : EMPTY_STRING; +} + +const string& HwTransformNode::getMatrix(const string& fromSpace, const string& toSpace) const +{ + if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) + { + return getModelToWorldMatrix(); + } + else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) + { + return getWorldToModelMatrix(); + } + return EMPTY_STRING; +} + +ShaderNodeImplPtr HwTransformVectorNode::create() +{ + return std::make_shared(); +} + +ShaderNodeImplPtr HwTransformPointNode::create() +{ + return std::make_shared(); +} + +ShaderNodeImplPtr HwTransformNormalNode::create() +{ + return std::make_shared(); +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.h b/source/MaterialXGenShader/Nodes/HwTransformNode.h new file mode 100644 index 0000000000..a97e57405c --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTransformNode.h @@ -0,0 +1,71 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_HWTRANSFORMNODE_H +#define MATERIALX_HWTRANSFORMNODE_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// Generic transformation node for hardware languages +class MX_GENSHADER_API HwTransformNode : public ShaderNodeImpl +{ + public: + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; + + protected: + virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; + virtual const string& getModelToWorldMatrix() const = 0; + virtual const string& getWorldToModelMatrix() const = 0; + virtual string getHomogeneousCoordinate() const = 0; + virtual bool shouldNormalize() const { return false; } + + virtual string getFromSpace(const ShaderNode&) const; + virtual string getToSpace(const ShaderNode&) const; + + static const string FROM_SPACE; + static const string TO_SPACE; + static const string MODEL; + static const string OBJECT; + static const string WORLD; +}; + +class MX_GENSHADER_API HwTransformVectorNode : public HwTransformNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + const string& getModelToWorldMatrix() const override { return HW::T_WORLD_MATRIX; } + const string& getWorldToModelMatrix() const override { return HW::T_WORLD_INVERSE_MATRIX; } + string getHomogeneousCoordinate() const override { return "0.0"; } +}; + +class MX_GENSHADER_API HwTransformPointNode : public HwTransformVectorNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + string getHomogeneousCoordinate() const override { return "1.0"; } +}; + +class MX_GENSHADER_API HwTransformNormalNode : public HwTransformNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + const string& getModelToWorldMatrix() const override { return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; } + const string& getWorldToModelMatrix() const override { return HW::T_WORLD_TRANSPOSE_MATRIX; } + string getHomogeneousCoordinate() const override { return "0.0"; } + bool shouldNormalize() const override { return true; } +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 04551cb6d2..3e393178f1 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -32,6 +32,11 @@ string ShaderPort::getFullName() const return (_node->getName() + "_" + _name); } +string ShaderPort::getValueString() const +{ + return getValue() ? getValue()->getValueString() : EMPTY_STRING; +} + // // ShaderInput methods // diff --git a/source/MaterialXGenShader/ShaderNode.h b/source/MaterialXGenShader/ShaderNode.h index 536e0adc1e..dd74269764 100644 --- a/source/MaterialXGenShader/ShaderNode.h +++ b/source/MaterialXGenShader/ShaderNode.h @@ -170,6 +170,9 @@ class MX_GENSHADER_API ShaderPort : public std::enable_shared_from_thissecond->getType()->getSize() < type->getSize()) + { + it->second->setType(type); + } + } + else if (type != it->second->getType()) + { + throw ExceptionShaderGenError("Trying to add shader port '" + name + "' with type '" + + type->getName() + "', but existing shader port with type '" + + it->second->getType()->getName() + "' was found"); + } return it->second.get(); } diff --git a/source/MaterialXGenShader/ShaderStage.h b/source/MaterialXGenShader/ShaderStage.h index 71004f8e52..a6a5cec0b8 100644 --- a/source/MaterialXGenShader/ShaderStage.h +++ b/source/MaterialXGenShader/ShaderStage.h @@ -113,7 +113,14 @@ class MX_GENSHADER_API VariableBlock ShaderPort* find(const ShaderPortPredicate& predicate); /// Add a new shader port to this block. - ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr); + /// @param type The desired shader port type + /// @param name The shader port name + /// @param value The value to attach to the shader port + /// @param shouldWiden When false, an exception is thrown if the type of the existing port with + /// the same name does not match the requested type. When true, the types can mismatch, and the + /// type of any existing port is widened to match the requested type when necessary. + /// @return A new shader port, or a pre-existing shader port with the same name. + ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr, bool shouldWiden = false); /// Add an existing shader port to this block. void add(ShaderPortPtr port); @@ -339,20 +346,22 @@ inline ShaderPort* addStageUniform(const string& block, inline ShaderPort* addStageInput(const string& block, const TypeDesc* type, const string& name, - ShaderStage& stage) + ShaderStage& stage, + bool shouldWiden = false) { VariableBlock& inputs = stage.getInputBlock(block); - return inputs.add(type, name); + return inputs.add(type, name, {}, shouldWiden); } /// Utility function for adding a new shader port to an output block. inline ShaderPort* addStageOutput(const string& block, const TypeDesc* type, const string& name, - ShaderStage& stage) + ShaderStage& stage, + bool shouldWiden = false) { VariableBlock& outputs = stage.getOutputBlock(block); - return outputs.add(type, name); + return outputs.add(type, name, {}, shouldWiden); } /// Utility function for adding a connector block between stages. @@ -370,10 +379,11 @@ inline void addStageConnector(const string& block, const TypeDesc* type, const string& name, ShaderStage& from, - ShaderStage& to) + ShaderStage& to, + bool shouldWiden = false) { - addStageOutput(block, type, name, from); - addStageInput(block, type, name, to); + addStageOutput(block, type, name, from, shouldWiden); + addStageInput(block, type, name, to, shouldWiden); } MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt index eaae85a825..2ec553856f 100644 --- a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt +++ b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt @@ -41,7 +41,7 @@ if (BUILD_SHARED_LIBS AND UNIX) # On Unix-like systems, shared libraries can use the soname system. set(GLFW_LIB_NAME glfw) else() - set(GLFW_LIB_NAME glfw3) + set(GLFW_LIB_NAME glfw3_minimal) endif() if (GLFW_VULKAN_STATIC) diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index 2b28317ee2..849b8607b4 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -236,9 +236,6 @@ void Graph::addExtraNodes() return; } - // Clear any old nodes, if we previously used tab with another graph doc - _extraNodes.clear(); - // Get all types from the doc std::vector types; std::vector typeDefs = _graphDoc->getTypeDefs(); @@ -252,18 +249,16 @@ void Graph::addExtraNodes() for (const std::string& type : types) { std::string nodeName = "ND_input_" + type; - _extraNodes["Input Nodes"].push_back({ nodeName, type, "input" }); + _nodesToAdd.emplace_back(nodeName, type, "input", "Input Nodes"); nodeName = "ND_output_" + type; - _extraNodes["Output Nodes"].push_back({ nodeName, type, "output" }); + _nodesToAdd.emplace_back(nodeName, type, "output", "Output Nodes"); } // Add group node - std::vector groupNode{ "ND_group", "", "group" }; - _extraNodes["Group Nodes"].push_back(groupNode); + _nodesToAdd.emplace_back("ND_group", "", "group", "Group Nodes"); // Add nodegraph node - std::vector nodeGraph{ "ND_nodegraph", "", "nodegraph" }; - _extraNodes["Node Graph"].push_back(nodeGraph); + _nodesToAdd.emplace_back("ND_nodegraph", "", "nodegraph", "Node Graph"); } ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input) @@ -846,7 +841,7 @@ void Graph::setRenderMaterial(UiNodePtr node) } } -void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value) +void Graph::updateMaterials(mx::InputPtr input /* = nullptr */, mx::ValuePtr value /* = nullptr */) { std::string renderablePath; if (_currRenderNode) @@ -1224,20 +1219,63 @@ void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::st void Graph::createNodeUIList(mx::DocumentPtr doc) { _nodesToAdd.clear(); - const std::string EXTRA_GROUP_NAME = "extra"; - for (mx::NodeDefPtr nodeDef : doc->getNodeDefs()) + + std::vector ordered_groups = { + "texture2d", + "texture3d", + "procedural", + "procedural2d", + "procedural3d", + "geometric", + "translation", + "convolution2d", + "math", + "adjustment", + "compositing", + "conditional", + "channel", + "organization", + "global", + "application", + "material", + "shader", + "pbr", + "light", + "colortransform", + "no_group" + }; + + auto nodeDefs = doc->getNodeDefs(); + std::unordered_map> groupToNodeDef; + + for (const auto& nodeDef : nodeDefs) { - // NodeDef is the key for the map std::string group = nodeDef->getNodeGroup(); + if (group.empty()) { - group = EXTRA_GROUP_NAME; + group = "no_group"; } - if (_nodesToAdd.find(group) == _nodesToAdd.end()) + + if (groupToNodeDef.find(group) == groupToNodeDef.end()) + { + groupToNodeDef[group] = std::vector(); + } + groupToNodeDef[group].push_back(nodeDef); + } + + for (const auto& group : ordered_groups) + { + auto it = groupToNodeDef.find(group); + if (it != groupToNodeDef.end()) { - _nodesToAdd[group] = std::vector(); + const auto& groupNodeDefs = it->second; + + for (const auto& nodeDef : groupNodeDefs) + { + _nodesToAdd.emplace_back(nodeDef->getName(), nodeDef->getType(), nodeDef->getNodeString(), group); + } } - _nodesToAdd[group].push_back(nodeDef); } addExtraNodes(); @@ -2483,12 +2521,22 @@ void Graph::setDefaults(mx::InputPtr input) } } -void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId) +void Graph::addLink(ed::PinId startPinId, ed::PinId endPinId) { - int end_attr = int(outputPinId.Get()); - int start_attr = int(inputPinId.Get()); - UiPinPtr inputPin = getPin(outputPinId); - UiPinPtr outputPin = getPin(inputPinId); + // prefer to assume left to right - start is an output, end is an input; swap if inaccurate + if (UiPinPtr inputPin = getPin(endPinId); inputPin && inputPin->_kind != ed::PinKind::Input) + { + auto tmp = startPinId; + startPinId = endPinId; + endPinId = tmp; + } + + int end_attr = int(endPinId.Get()); + int start_attr = int(startPinId.Get()); + ed::PinId outputPinId = startPinId; + ed::PinId inputPinId = endPinId; + UiPinPtr outputPin = getPin(outputPinId); + UiPinPtr inputPin = getPin(inputPinId); if (!inputPin || !outputPin) { @@ -2505,187 +2553,206 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId) return; } - if (inputPin->_connected == false) + // Perform kind check + bool kindsMatch = (outputPin->_kind == inputPin->_kind); + if (kindsMatch) { - int upNode = getNodeId(inputPinId); - int downNode = getNodeId(outputPinId); - UiNodePtr uiDownNode = _graphNodes[downNode]; - UiNodePtr uiUpNode = _graphNodes[upNode]; - if (!uiDownNode || !uiUpNode) - { - ed::RejectNewItem(); - return; - } + ed::RejectNewItem(); + showLabel("Invalid connection due to same input/output kind", ImColor(50, 50, 50, 255)); + return; + } - // make sure there is an implementation for node - const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator(); + int upNode = getNodeId(outputPinId); + int downNode = getNodeId(inputPinId); + UiNodePtr uiDownNode = _graphNodes[downNode]; + UiNodePtr uiUpNode = _graphNodes[upNode]; + if (!uiDownNode || !uiUpNode) + { + ed::RejectNewItem(); + return; + } - // Prevent direct connecting from input to output - if (uiDownNode->getInput() && uiUpNode->getOutput()) - { - ed::RejectNewItem(); - showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255)); - return; - } + // make sure there is an implementation for node + const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator(); + + // Prevent direct connecting from input to output + if (uiDownNode->getInput() && uiUpNode->getOutput()) + { + ed::RejectNewItem(); + showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255)); + return; + } - // Find the implementation for this nodedef if not an input or output uinode - if (uiDownNode->getInput() && _isNodeGraph) + // Find the implementation for this nodedef if not an input or output uinode + if (uiDownNode->getInput() && _isNodeGraph) + { + ed::RejectNewItem(); + showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255)); + return; + } + else if (uiUpNode->getNode()) + { + mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext()); + if (!impl) { ed::RejectNewItem(); - showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255)); + showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255)); return; } - else if (uiUpNode->getNode()) + } + + if (ed::AcceptNewItem()) + { + // If the accepting node already has a link, remove it + if (inputPin->_connected) { - mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext()); - if (!impl) + for (auto linksItr = _currLinks.begin(); linksItr != _currLinks.end(); linksItr++) { - ed::RejectNewItem(); - showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255)); - return; + if (linksItr->_endAttr == end_attr) + { + // found existing link - remove it; adapted from deleteLink + // note: ed::BreakLinks doesn't work as the order ends up inaccurate + deleteLinkInfo(linksItr->_startAttr, linksItr->_endAttr); + _currLinks.erase(linksItr); + break; + } } + } - if (ed::AcceptNewItem()) - { - // Since we accepted new link, lets add one to our list of links. - Link link; - link._startAttr = start_attr; - link._endAttr = end_attr; - _currLinks.push_back(link); - _frameCount = ImGui::GetFrameCount(); - _renderer->setMaterialCompilation(true); + // Since we accepted new link, lets add one to our list of links. + Link link; + link._startAttr = start_attr; + link._endAttr = end_attr; + _currLinks.push_back(link); + _frameCount = ImGui::GetFrameCount(); + _renderer->setMaterialCompilation(true); - if (uiDownNode->getNode() || uiDownNode->getNodeGraph()) + if (uiDownNode->getNode() || uiDownNode->getNodeGraph()) + { + mx::InputPtr connectingInput = nullptr; + for (UiPinPtr pin : uiDownNode->inputPins) { - mx::InputPtr connectingInput = nullptr; - for (UiPinPtr pin : uiDownNode->inputPins) + if (pin->_pinId == inputPinId) { - if (pin->_pinId == outputPinId) + addNodeInput(uiDownNode, pin->_input); + // update value to be empty + if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING) { - addNodeInput(uiDownNode, pin->_input); - // update value to be empty - if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING) + if (uiUpNode->getOutput() != nullptr) { - if (uiUpNode->getOutput() != nullptr) - { - pin->_input->setConnectedOutput(uiUpNode->getOutput()); - } - else if (uiUpNode->getInput() != nullptr) - { - pin->_input->setInterfaceName(uiUpNode->getName()); - } - else + pin->_input->setConnectedOutput(uiUpNode->getOutput()); + } + else if (uiUpNode->getInput() != nullptr) + { + pin->_input->setInterfaceName(uiUpNode->getName()); + } + else + { + // node graph + if (uiUpNode->getNodeGraph() != nullptr) { - // node graph - if (uiUpNode->getNodeGraph() != nullptr) + for (UiPinPtr outPin : uiUpNode->outputPins) { - for (UiPinPtr outPin : uiUpNode->outputPins) + // set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) - { - mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); - pin->_input->setConnectedOutput(outputs); - } + mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); + pin->_input->setConnectedOutput(outputs); } } - else - { - pin->_input->setConnectedNode(uiUpNode->getNode()); - } + } + else + { + pin->_input->setConnectedNode(uiUpNode->getNode()); } } + } + else + { + if (uiUpNode->getInput()) + { + pin->_input->setInterfaceName(uiUpNode->getName()); + } else { - if (uiUpNode->getInput()) - { - pin->_input->setInterfaceName(uiUpNode->getName()); - } - else + if (uiUpNode->getNode()) { - if (uiUpNode->getNode()) + mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode(); + mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef(); + bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false; + + // This is purely to avoid adding a reference to an update node only 1 output, + // as currently validation consides adding this an error. Otherwise + // it will add an "output" attribute all the time. + if (!isMultiOutput) { - mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode(); - mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef(); - bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false; - - // This is purely to avoid adding a reference to an update node only 1 output, - // as currently validation consides adding this an error. Otherwise - // it will add an "output" attribute all the time. - if (!isMultiOutput) - { - pin->_input->setConnectedNode(uiUpNode->getNode()); - } - else + pin->_input->setConnectedNode(uiUpNode->getNode()); + } + else + { + for (UiPinPtr outPin : _graphNodes[upNode]->outputPins) { - for (UiPinPtr outPin : _graphNodes[upNode]->outputPins) + // set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) + mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name); + if (!outputs) { - mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name); - if (!outputs) - { - outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType()); - } - pin->_input->setConnectedOutput(outputs); + outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType()); } + pin->_input->setConnectedOutput(outputs); } } } - else if (uiUpNode->getNodeGraph()) + } + else if (uiUpNode->getNodeGraph()) + { + for (UiPinPtr outPin : uiUpNode->outputPins) { - for (UiPinPtr outPin : uiUpNode->outputPins) + // set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) - { - mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); - pin->_input->setConnectedOutput(outputs); - } + mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); + pin->_input->setConnectedOutput(outputs); } } } } - - pin->setConnected(true); - pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE); - connectingInput = pin->_input; - break; } + + pin->setConnected(true); + pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE); + connectingInput = pin->_input; + break; } - // create new edge and set edge information - createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); } - else if (_graphNodes[downNode]->getOutput() != nullptr) - { - mx::InputPtr connectingInput = nullptr; - _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode()); + // create new edge and set edge information + createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); + } + else if (_graphNodes[downNode]->getOutput() != nullptr) + { + mx::InputPtr connectingInput = nullptr; + _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode()); - // create new edge and set edge information - createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); - } - else + // create new edge and set edge information + createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); + } + else + { + // create new edge and set edge info + UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr); + if (!edgeExists(newEdge)) { - // create new edge and set edge info - UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr); - if (!edgeExists(newEdge)) - { - _graphNodes[downNode]->edges.push_back(newEdge); - _currEdge.push_back(newEdge); + _graphNodes[downNode]->edges.push_back(newEdge); + _currEdge.push_back(newEdge); - // update input node num and output connections - _graphNodes[downNode]->setInputNodeNum(1); - _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]); - } + // update input node num and output connections + _graphNodes[downNode]->setInputNodeNum(1); + _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]); } } } - else - { - ed::RejectNewItem(); - } } void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin) @@ -3566,96 +3633,66 @@ void Graph::addNodePopup(bool cursor) // Input string length // Filter extra nodes - includes inputs, outputs, groups, and node graphs const std::string NODEGRAPH_ENTRY = "Node Graph"; - for (std::unordered_map>>::iterator it = _extraNodes.begin(); it != _extraNodes.end(); ++it) + + // Filter nodedefs and add to menu if matches filter + for (auto node : _nodesToAdd) { // Filter out list of nodes if (subs.size() > 0) { ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f)); - for (size_t i = 0; i < it->second.size(); i++) - { - std::string str(it->second[i][0]); - std::string nodeName = it->second[i][0]; + std::string str(node.getName()); + std::string nodeName = node.getName(); - // Disallow creating nested nodegraphs - if (_isNodeGraph && it->first == NODEGRAPH_ENTRY) - { - continue; - } + // Disallow creating nested nodegraphs + if (_isNodeGraph && node.getGroup() == NODEGRAPH_ENTRY) + { + continue; + } - // Allow spaces to be used to search for node names - std::replace(subs.begin(), subs.end(), ' ', '_'); + // Allow spaces to be used to search for node names + std::replace(subs.begin(), subs.end(), ' ', '_'); - if (str.find(subs) != std::string::npos) + if (str.find(subs) != std::string::npos) + { + if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) { - if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) - { - addNode(it->second[i][2], getUserNodeDefName(nodeName), it->second[i][1]); - _addNewNode = true; - memset(input, '\0', sizeof(input)); - } + addNode(node.getCategory(), getUserNodeDefName(nodeName), node.getType()); + _addNewNode = true; + memset(input, '\0', sizeof(input)); } } } else { ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300)); - if (ImGui::BeginMenu(it->first.c_str())) + if (ImGui::BeginMenu(node.getGroup().c_str())) { ImGui::SetWindowFontScale(_fontScale); - for (size_t j = 0; j < it->second.size(); j++) + std::string name = node.getName(); + std::string prefix = "ND_"; + if (name.compare(0, prefix.size(), prefix) == 0 && name.compare(prefix.size(), std::string::npos, node.getCategory()) == 0) { - std::string name = it->second[j][0]; if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) { - addNode(it->second[j][2], getUserNodeDefName(name), it->second[j][1]); + addNode(node.getCategory(), getUserNodeDefName(name), node.getType()); _addNewNode = true; } } - ImGui::EndMenu(); - } - } - } - - // Filter nodedefs and add to menu if matches filter - for (std::unordered_map>::iterator it = _nodesToAdd.begin(); it != _nodesToAdd.end(); ++it) - { - // Filter out list of nodes - if (subs.size() > 0) - { - ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f)); - for (size_t i = 0; i < it->second.size(); i++) - { - std::string str(it->second[i]->getName()); - std::string nodeName = it->second[i]->getName(); - if (str.find(subs) != std::string::npos) - { - std::string val = getUserNodeDefName(nodeName); - if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) - { - addNode(it->second[i]->getNodeString(), val, it->second[i]->getType()); - _addNewNode = true; - memset(input, '\0', sizeof(input)); - } - } - } - } - else - { - ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300)); - if (ImGui::BeginMenu(it->first.c_str())) - { - ImGui::SetWindowFontScale(_fontScale); - for (size_t i = 0; i < it->second.size(); i++) + else { - std::string name = it->second[i]->getName(); - std::string val = getUserNodeDefName(name); - if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) + if (ImGui::BeginMenu(node.getCategory().c_str())) { - addNode(it->second[i]->getNodeString(), val, it->second[i]->getType()); - _addNewNode = true; + if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) + { + addNode(node.getCategory(), getUserNodeDefName(name), node.getType()); + _addNewNode = true; + } + ImGui::EndMenu(); } } + + ImGui::EndMenu(); } } @@ -4045,12 +4082,12 @@ void Graph::drawGraph(ImVec2 mousePos) // Add new link if (ed::BeginCreate()) { - ed::PinId inputPinId, outputPinId, filterPinId; - if (ed::QueryNewLink(&inputPinId, &outputPinId)) + ed::PinId startPinId, endPinId, filterPinId; + if (ed::QueryNewLink(&startPinId, &endPinId)) { if (!readOnly()) { - addLink(inputPinId, outputPinId); + addLink(startPinId, endPinId); } else { diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h index 8c76f0f68d..87d4119c2a 100644 --- a/source/MaterialXGraphEditor/Graph.h +++ b/source/MaterialXGraphEditor/Graph.h @@ -14,6 +14,30 @@ #include +class MenuItem +{ + public: + MenuItem(const std::string& name, const std::string& type, const std::string& category, const std::string& group) : + name(name), type(type), category(category), group(group) { } + + // getters + std::string getName() const { return name; } + std::string getType() const { return type; } + std::string getCategory() const { return category; } + std::string getGroup() const { return group; } + + // setters + void setName(const std::string& newName) { this->name = newName; } + void setType(const std::string& newType) { this->type = newType; } + void setCategory(const std::string& newCategory) { this->category = newCategory; } + void setGroup(const std::string& newGroup) { this->group = newGroup; } + + private: + std::string name; + std::string type; + std::string category; + std::string group; +}; namespace ed = ax::NodeEditor; namespace mx = MaterialX; @@ -90,7 +114,9 @@ class Graph // Add link to nodegraph and set up connections between UiNodes and // MaterialX Nodes to update shader - void addLink(ed::PinId inputPinId, ed::PinId outputPinId); + // startPinId - where the link was initiated + // endPinId - where the link was ended + void addLink(ed::PinId startPinId, ed::PinId endPinId); // Delete link from current link vector and remove any connections in // UiNode or MaterialX Nodes to update shader @@ -246,8 +272,7 @@ class Graph std::vector _currGraphName; // for adding new nodes - std::unordered_map> _nodesToAdd; - std::unordered_map>> _extraNodes; + std::vector _nodesToAdd; // stacks to dive into and out of node graphs std::stack> _graphStack; diff --git a/source/MaterialXGraphEditor/Main.cpp b/source/MaterialXGraphEditor/Main.cpp index 754d766798..5bbcbdad66 100644 --- a/source/MaterialXGraphEditor/Main.cpp +++ b/source/MaterialXGraphEditor/Main.cpp @@ -23,44 +23,6 @@ static void errorCallback(int error, const char* description) fprintf(stderr, "Glfw Error %d: %s\n", error, description); } -mx::FilePath getConfigPath() -{ - mx::FilePath configPath; - auto xdgConfigHome = mx::getEnviron("XDG_CONFIG_HOME"); - auto homeDirectory = mx::getEnviron("HOME"); - if (!xdgConfigHome.empty()) - { - configPath = mx::FilePath(xdgConfigHome); - } - else if (!homeDirectory.empty()) - { -#if defined(__APPLE__) - configPath = mx::FilePath(homeDirectory) / "Library" / "Preferences"; -#else - configPath = mx::FilePath(homeDirectory) / ".config"; - if (!configPath.exists()) - { - configPath.createDirectory(); - } -#endif - } - else - { - return {}; - } - - configPath = configPath / "MaterialX"; - configPath.createDirectory(); - - if (!configPath.exists()) - { - std::cerr << "Failed to create MaterialX config directory at " << configPath.asString() << std::endl; - return {}; - } - - return configPath / "GraphEditor.imgui.ini"; -} - const std::string options = " Options: \n" " --material [FILENAME] Specify the filename of the MTLX document to be displayed in the graph editor\n" @@ -197,13 +159,14 @@ int main(int argc, char* const argv[]) IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - io.Fonts->AddFontDefault(); - mx::FilePath configPath = getConfigPath(); - if (!configPath.isEmpty()) - { - io.IniFilename = configPath.asString().c_str(); - } + // Set ini and log filename to NULL. This will prevent the automatic creation of imgui.ini + // in the same folder as the saved material. + // TODO: Consider setting the ini and log file paths to an application directory. + io.IniFilename = NULL; + io.LogFilename = NULL; + + io.Fonts->AddFontDefault(); // Setup Dear ImGui style ImGui::StyleColorsDark(); diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp index 4106bf2eb3..006538891c 100644 --- a/source/MaterialXTest/MaterialXCore/Look.cpp +++ b/source/MaterialXTest/MaterialXCore/Look.cpp @@ -75,6 +75,7 @@ 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); @@ -86,6 +87,7 @@ 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/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 560a19e778..c06846f2ce 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -1375,7 +1375,7 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie // with later assignments superseding earlier ones. for (mx::LookPtr look : doc->getLooks()) { - for (mx::MaterialAssignPtr matAssign : look->getMaterialAssigns()) + for (mx::MaterialAssignPtr matAssign : look->getActiveMaterialAssigns()) { const std::string& activeGeom = matAssign->getActiveGeom(); for (mx::MeshPartitionPtr part : _geometryList) diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp index 343442e071..146674c222 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp @@ -24,6 +24,7 @@ void bindPyShaderPort(py::module& mod) .def("getSemantic", &mx::ShaderPort::getSemantic) .def("setValue", &mx::ShaderPort::setValue) .def("getValue", &mx::ShaderPort::getValue) + .def("getValueString", &mx::ShaderPort::getValueString) .def("setGeomProp", &mx::ShaderPort::setGeomProp) .def("getGeomProp", &mx::ShaderPort::getGeomProp) .def("setPath", &mx::ShaderPort::setPath)