diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index b85d1c9d4..8aba82d86 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -882,6 +882,62 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.Output(1, "Inv Size", typeof(Float2), 1), } }, + new NodeArchetype + { + TypeID = 40, + Title = "Rectangle Mask", + Description = "Creates a Rectangle mask", + Flags = NodeFlags.MaterialGraph, + Size = new Float2(150, 40), + ConnectionsHints = ConnectionsHint.Vector, + DefaultValues = new object[] + { + new Float2(0, 0), + new Float2(0.5f, 0.5f), + }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "UV", true, typeof(Float2), 0), + NodeElementArchetype.Factory.Input(1, "Rectangle", true, typeof(Float2), 1), + NodeElementArchetype.Factory.Output(0, string.Empty, typeof(float), 5), + } + }, + new NodeArchetype + { + TypeID = 41, + Title = "FWidth", + Description = "Creates a partial derivative (fwidth)", + Flags = NodeFlags.MaterialGraph, + Size = new Float2(150, 20), + ConnectionsHints = ConnectionsHint.Numeric, + IndependentBoxes = new[] { 0 }, + DependentBoxes = new[] { 1 }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "value", true, null, 0), + NodeElementArchetype.Factory.Output(0, string.Empty, null, 1), + } + }, + new NodeArchetype + { + TypeID = 42, + Title = "AAStep", + Description = "Smooth version of step", + Flags = NodeFlags.MaterialGraph, + Size = new Float2(150, 40), + ConnectionsHints = ConnectionsHint.Vector, + DefaultValues = new object[] + { + 1, + 0 + }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "value", true, typeof(float), 0), + NodeElementArchetype.Factory.Input(1, "gradient", true, typeof(float), 1), + NodeElementArchetype.Factory.Output(0, string.Empty, typeof(float), 5), + } + }, }; } } diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp index 830a2ab06..56de05137 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp @@ -519,6 +519,41 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) } break; } + // Ratangle Mask + case 40: + { + const auto uv = tryGetValue(node->GetBox(0), getUVs).AsFloat2(); + const auto rectangle = tryGetValue(node->GetBox(1), node->Values[1]).AsFloat2(); + + auto d = writeLocal(ValueType::Float2, String::Format(TEXT("abs({0} * 2 - 1) - {1}"),uv.Value, rectangle.Value), node); + auto d2 = writeLocal(ValueType::Float2 , String::Format(TEXT("1 - {0} / fwidth({0})"), d.Value), node); + value = writeLocal(ValueType::Float , String::Format(TEXT("saturate(min({0}.x, {0}.y))"), d2.Value), node); + break; + } + // FWidth + case 41: + { + const auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero); + value = writeLocal(inValue.Type, String::Format(TEXT("fwidth({0})"), inValue.Value), node); + break; + } + //AAStep (smooth version of step) + case 42: + { + //source https://www.ronja-tutorials.com/post/046-fwidth/#a-better-step + + const auto compValue = tryGetValue(node->GetBox(0), getUVs).AsFloat(); + const auto gradient = tryGetValue(node->GetBox(1), node->Values[1]).AsFloat(); + + auto change = writeLocal(ValueType::Float, String::Format(TEXT("fwidth({0})"), gradient.Value), node); + + //base the range of the inverse lerp on the change over two pixels + auto lowerEdge = writeLocal(ValueType::Float, String::Format(TEXT("{0} - {1})"), compValue.Value, change.Value), node); + auto upperEdge = writeLocal(ValueType::Float, String::Format(TEXT("{0} + {1})"), compValue.Value, change.Value), node); + + //do the inverse interpolation and saturate it + value = writeLocal(ValueType::Float, String::Format(TEXT("saturate((({0} - {1}) / ({2} - {1})))"), gradient.Value, lowerEdge.Value, upperEdge.Value), node); + } default: break; }