diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs
index 424511cce..f7ce33c92 100644
--- a/Source/Editor/Surface/Archetypes/Material.cs
+++ b/Source/Editor/Surface/Archetypes/Material.cs
@@ -236,6 +236,39 @@ namespace FlaxEditor.Surface.Archetypes
}
}
+ internal enum MaterialTemplateInputsMapping
+ {
+ ///
+ /// Constant buffers.
+ ///
+ Constants = 1,
+
+ ///
+ /// Shader resources such as textures and buffers.
+ ///
+ ShaderResources = 2,
+
+ ///
+ /// Pre-processor definitions.
+ ///
+ Defines = 3,
+
+ ///
+ /// Included files.
+ ///
+ Includes = 7,
+
+ ///
+ /// Default location after all shader resources and methods but before actual material code.
+ ///
+ Utilities = 8,
+
+ ///
+ /// Shader functions location after all material shaders.
+ ///
+ Shaders = 9,
+ }
+
///
/// The nodes for that group.
///
@@ -814,17 +847,20 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Custom Global Code",
Description = "Custom global HLSL shader code expression (placed before material shader code). Can contain includes to shader utilities or declare functions to reuse later.",
Flags = NodeFlags.MaterialGraph,
- Size = new Vector2(300, 220),
+ Size = new Vector2(300, 240),
DefaultValues = new object[]
{
"// Here you can add HLSL code\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}",
true,
+ (int)MaterialTemplateInputsMapping.Utilities,
},
Elements = new[]
{
NodeElementArchetype.Factory.Bool(0, 0, 1),
NodeElementArchetype.Factory.Text(20, 0, "Enabled"),
- NodeElementArchetype.Factory.TextBox(0, 20, 300, 200, 0),
+ NodeElementArchetype.Factory.Text(0, 20, "Location"),
+ NodeElementArchetype.Factory.Enum(50, 20, 120, 2, typeof(MaterialTemplateInputsMapping)),
+ NodeElementArchetype.Factory.TextBox(0, 40, 300, 200, 0),
}
},
};
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
index f1d5b5840..42b57c341 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
@@ -392,6 +392,21 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Update material usage based on material generator outputs
materialInfo.UsageFlags = baseLayer->UsageFlags;
+ // Find all Custom Global Code nodes
+ Array> customGlobalCodeNodes;
+ Array> graphs;
+ _functions.GetValues(graphs);
+ for (MaterialLayer* layer : _layers)
+ graphs.Add(&layer->Graph);
+ for (Graph* graph : graphs)
+ {
+ for (const MaterialGraph::Node& node : graph->Nodes)
+ {
+ if (node.Type == GRAPH_NODE_MAKE_TYPE(1, 38) && (bool)node.Values[1])
+ customGlobalCodeNodes.Add(&node);
+ }
+ }
+
#define WRITE_FEATURES(input) FeaturesLock.Lock(); for (auto f : features) _writer.Write(Features[f].Inputs[(int32)FeatureTemplateInputsMapping::input]); FeaturesLock.Unlock();
// Defines
{
@@ -408,6 +423,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
}
WRITE_FEATURES(Defines);
inputs[In_Defines] = _writer.ToString();
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_Defines);
_writer.Clear();
}
@@ -416,6 +432,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
for (auto& include : _includes)
_writer.Write(TEXT("#include \"{0}\"\n"), include.Item);
WRITE_FEATURES(Includes);
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_Includes);
inputs[In_Includes] = _writer.ToString();
_writer.Clear();
}
@@ -425,6 +442,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
WRITE_FEATURES(Constants);
if (_parameters.HasItems())
ShaderGraphUtilities::GenerateShaderConstantBuffer(_writer, _parameters);
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_Constants);
inputs[In_Constants] = _writer.ToString();
_writer.Clear();
}
@@ -485,6 +503,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
return true;
}
}
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_ShaderResources);
inputs[In_ShaderResources] = _writer.ToString();
_writer.Clear();
}
@@ -492,21 +511,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Utilities
{
WRITE_FEATURES(Utilities);
- Array> graphs;
- _functions.GetValues(graphs);
- for (MaterialLayer* layer : _layers)
- graphs.Add(&layer->Graph);
- for (Graph* graph : graphs)
- {
- for (const MaterialGraph::Node& node : graph->Nodes)
- {
- if (node.Type == GRAPH_NODE_MAKE_TYPE(1, 38) && (bool)node.Values[1])
- {
- // Custom Global Code
- _writer.Write((StringView)node.Values[0]);
- }
- }
- }
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_Utilities);
inputs[In_Utilities] = _writer.ToString();
_writer.Clear();
}
@@ -514,6 +519,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Shaders
{
WRITE_FEATURES(Shaders);
+ WriteCustomGlobalCode(customGlobalCodeNodes, In_Shaders);
inputs[In_Shaders] = _writer.ToString();
_writer.Clear();
}
@@ -799,4 +805,17 @@ void MaterialGenerator::ProcessGroupMath(Box* box, Node* node, Value& value)
}
}
+void MaterialGenerator::WriteCustomGlobalCode(const Array>& nodes, int32 templateInputsMapping)
+{
+ for (const MaterialGraph::Node* node : nodes)
+ {
+ if ((int32)node->Values[2] == templateInputsMapping)
+ {
+ _writer.Write(TEXT("\n"));
+ _writer.Write((StringView)node->Values[0]);
+ _writer.Write(TEXT("\n"));
+ }
+ }
+}
+
#endif
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h
index 48cd21cb4..9a8aa5290 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h
@@ -205,6 +205,7 @@ private:
MaterialValue AccessParticleAttribute(Node* caller, const StringView& name, ParticleAttributeValueTypes valueType, const Char* index = nullptr, ParticleAttributeSpace space = ParticleAttributeSpace::AsIs);
void prepareLayer(MaterialLayer* layer, bool allowVisibleParams);
+ void WriteCustomGlobalCode(const Array>& nodes, int32 templateInputsMapping);
public: