// ===================================================================================================================== // OpenShaderDesigner, an open source software utility to create materials and shaders. // Copyright (C) 2024 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #include using namespace OpenShaderDesigner; using namespace OpenShaderDesigner::Nodes::Math; RegisterNode("Math/Comparison/Min", Minimum); RegisterNode("Math/Comparison/Max", Maximum); RegisterNode("Math/Comparison/Clamp", Clamp); RegisterNode("Math/Comparison/Saturate", Saturate); // ===================================================================================================================== // User Defined Constants // ===================================================================================================================== // Minimum ----------------------------------------------------------------------------------------------------------------- Minimum::Minimum(ShaderGraph& graph, ImVec2 pos) : MathOp(graph, pos) { Info.Alias = "Minimum"; Header.Title = HeaderMarker + "Min"; Header.Color = HeaderColor; Header.HoveredColor = HeaderHoveredColor; Header.ActiveColor = HeaderActiveColor; IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous); IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous); Info.Flags |= NodeFlags_DynamicInputs; IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous); } Node* Minimum::Copy(ShaderGraph& graph) const { return new Minimum(graph, Position); } void Minimum::Inspect() { } std::string Minimum::GetCode() const { // TODO: Support more than 2 inputs return std::format("const {} {} = min({}, {});", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) , Graph.GetValue(IO.Inputs[1].Ptr) ); } // Maximum ----------------------------------------------------------------------------------------------------------------- Maximum::Maximum(ShaderGraph& graph, ImVec2 pos) : MathOp(graph, pos) { Info.Alias = "Maximum"; Header.Title = HeaderMarker + "Max"; Header.Color = HeaderColor; Header.HoveredColor = HeaderHoveredColor; Header.ActiveColor = HeaderActiveColor; IO.Inputs.emplace_back("A", PinType_Any, PinFlags_Ambiguous); IO.Inputs.emplace_back("B", PinType_Any, PinFlags_Ambiguous); Info.Flags |= NodeFlags_DynamicInputs; IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous); } Node* Maximum::Copy(ShaderGraph& graph) const { return new Maximum(graph, Position); } void Maximum::Inspect() { } std::string Maximum::GetCode() const { return std::format("const {} {} = max({}, {});", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) , Graph.GetValue(IO.Inputs[1].Ptr) ); } // Clamp ----------------------------------------------------------------------------------------------------------------- Clamp::Clamp(ShaderGraph& graph, ImVec2 pos) : MathOp(graph, pos) { Info.Alias = "Clamp"; Header.Title = HeaderMarker + "Clamp"; Header.Color = HeaderColor; Header.HoveredColor = HeaderHoveredColor; Header.ActiveColor = HeaderActiveColor; IO.Inputs.emplace_back("X", PinType_Any, PinFlags_Ambiguous); IO.Inputs.emplace_back("Min", PinType_Any, PinFlags_Ambiguous); IO.Inputs.emplace_back("Max", PinType_Any, PinFlags_Ambiguous); Info.Flags |= NodeFlags_DynamicInputs; IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous); } Node* Clamp::Copy(ShaderGraph& graph) const { return new Clamp(graph, Position); } void Clamp::Inspect() { } std::string Clamp::GetCode() const { return std::format("const {} {} = clamp({}, {}, {});", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) , Graph.GetValue(IO.Inputs[1].Ptr) , Graph.GetValue(IO.Inputs[2].Ptr) ); } // Clamp ----------------------------------------------------------------------------------------------------------------- Saturate::Saturate(ShaderGraph& graph, ImVec2 pos) : MathOp(graph, pos) { Info.Alias = "Saturate"; Header.Title = HeaderMarker + "Saturate"; Header.Color = HeaderColor; Header.HoveredColor = HeaderHoveredColor; Header.ActiveColor = HeaderActiveColor; IO.Inputs.emplace_back("X", PinType_Any, PinFlags_Ambiguous); Info.Flags |= NodeFlags_DynamicInputs; IO.Outputs.emplace_back("Out", PinType_Any, PinFlags_Ambiguous); } Node* Saturate::Copy(ShaderGraph& graph) const { return new Saturate(graph, Position); } void Saturate::Inspect() { } std::string Saturate::GetCode() const { switch(IO.Outputs[0].Type) { case PinType_Int: case PinType_UInt: return std::format("const {} {} = clamp({}, 0, 1);", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) ); case PinType_Float: default: return std::format("const {} {} = clamp({}, 0.0, 1.0);", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) ); case PinType_Vector: return std::format("const {} {} = clamp({}, vec3(0.0), vec3(1.0));", Pin::TypeKeywords[IO.Outputs[0].Type] , Graph.GetValue(IO.Outputs[0].Ptr) , Graph.GetValue(IO.Inputs[0].Ptr) ); } }