Add support for custom location of Custom Global Code in generated material source code

This commit is contained in:
Wojciech Figat
2022-05-12 13:44:57 +02:00
parent 70de677266
commit f7955a5c4e
3 changed files with 73 additions and 17 deletions

View File

@@ -236,6 +236,39 @@ namespace FlaxEditor.Surface.Archetypes
} }
} }
internal enum MaterialTemplateInputsMapping
{
/// <summary>
/// Constant buffers.
/// </summary>
Constants = 1,
/// <summary>
/// Shader resources such as textures and buffers.
/// </summary>
ShaderResources = 2,
/// <summary>
/// Pre-processor definitions.
/// </summary>
Defines = 3,
/// <summary>
/// Included files.
/// </summary>
Includes = 7,
/// <summary>
/// Default location after all shader resources and methods but before actual material code.
/// </summary>
Utilities = 8,
/// <summary>
/// Shader functions location after all material shaders.
/// </summary>
Shaders = 9,
}
/// <summary> /// <summary>
/// The nodes for that group. /// The nodes for that group.
/// </summary> /// </summary>
@@ -814,17 +847,20 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Custom Global Code", 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.", 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, Flags = NodeFlags.MaterialGraph,
Size = new Vector2(300, 220), Size = new Vector2(300, 240),
DefaultValues = new object[] DefaultValues = new object[]
{ {
"// Here you can add HLSL code\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}", "// Here you can add HLSL code\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}",
true, true,
(int)MaterialTemplateInputsMapping.Utilities,
}, },
Elements = new[] Elements = new[]
{ {
NodeElementArchetype.Factory.Bool(0, 0, 1), NodeElementArchetype.Factory.Bool(0, 0, 1),
NodeElementArchetype.Factory.Text(20, 0, "Enabled"), 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),
} }
}, },
}; };

View File

@@ -392,6 +392,21 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Update material usage based on material generator outputs // Update material usage based on material generator outputs
materialInfo.UsageFlags = baseLayer->UsageFlags; materialInfo.UsageFlags = baseLayer->UsageFlags;
// Find all Custom Global Code nodes
Array<const MaterialGraph::Node*, InlinedAllocation<8>> customGlobalCodeNodes;
Array<Graph*, InlinedAllocation<8>> 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(); #define WRITE_FEATURES(input) FeaturesLock.Lock(); for (auto f : features) _writer.Write(Features[f].Inputs[(int32)FeatureTemplateInputsMapping::input]); FeaturesLock.Unlock();
// Defines // Defines
{ {
@@ -408,6 +423,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
} }
WRITE_FEATURES(Defines); WRITE_FEATURES(Defines);
inputs[In_Defines] = _writer.ToString(); inputs[In_Defines] = _writer.ToString();
WriteCustomGlobalCode(customGlobalCodeNodes, In_Defines);
_writer.Clear(); _writer.Clear();
} }
@@ -416,6 +432,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
for (auto& include : _includes) for (auto& include : _includes)
_writer.Write(TEXT("#include \"{0}\"\n"), include.Item); _writer.Write(TEXT("#include \"{0}\"\n"), include.Item);
WRITE_FEATURES(Includes); WRITE_FEATURES(Includes);
WriteCustomGlobalCode(customGlobalCodeNodes, In_Includes);
inputs[In_Includes] = _writer.ToString(); inputs[In_Includes] = _writer.ToString();
_writer.Clear(); _writer.Clear();
} }
@@ -425,6 +442,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
WRITE_FEATURES(Constants); WRITE_FEATURES(Constants);
if (_parameters.HasItems()) if (_parameters.HasItems())
ShaderGraphUtilities::GenerateShaderConstantBuffer(_writer, _parameters); ShaderGraphUtilities::GenerateShaderConstantBuffer(_writer, _parameters);
WriteCustomGlobalCode(customGlobalCodeNodes, In_Constants);
inputs[In_Constants] = _writer.ToString(); inputs[In_Constants] = _writer.ToString();
_writer.Clear(); _writer.Clear();
} }
@@ -485,6 +503,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
return true; return true;
} }
} }
WriteCustomGlobalCode(customGlobalCodeNodes, In_ShaderResources);
inputs[In_ShaderResources] = _writer.ToString(); inputs[In_ShaderResources] = _writer.ToString();
_writer.Clear(); _writer.Clear();
} }
@@ -492,21 +511,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Utilities // Utilities
{ {
WRITE_FEATURES(Utilities); WRITE_FEATURES(Utilities);
Array<Graph*, InlinedAllocation<8>> graphs; WriteCustomGlobalCode(customGlobalCodeNodes, In_Utilities);
_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]);
}
}
}
inputs[In_Utilities] = _writer.ToString(); inputs[In_Utilities] = _writer.ToString();
_writer.Clear(); _writer.Clear();
} }
@@ -514,6 +519,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Shaders // Shaders
{ {
WRITE_FEATURES(Shaders); WRITE_FEATURES(Shaders);
WriteCustomGlobalCode(customGlobalCodeNodes, In_Shaders);
inputs[In_Shaders] = _writer.ToString(); inputs[In_Shaders] = _writer.ToString();
_writer.Clear(); _writer.Clear();
} }
@@ -799,4 +805,17 @@ void MaterialGenerator::ProcessGroupMath(Box* box, Node* node, Value& value)
} }
} }
void MaterialGenerator::WriteCustomGlobalCode(const Array<const MaterialGraph::Node*, InlinedAllocation<8>>& 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 #endif

View File

@@ -205,6 +205,7 @@ private:
MaterialValue AccessParticleAttribute(Node* caller, const StringView& name, ParticleAttributeValueTypes valueType, const Char* index = nullptr, ParticleAttributeSpace space = ParticleAttributeSpace::AsIs); MaterialValue AccessParticleAttribute(Node* caller, const StringView& name, ParticleAttributeValueTypes valueType, const Char* index = nullptr, ParticleAttributeSpace space = ParticleAttributeSpace::AsIs);
void prepareLayer(MaterialLayer* layer, bool allowVisibleParams); void prepareLayer(MaterialLayer* layer, bool allowVisibleParams);
void WriteCustomGlobalCode(const Array<const MaterialGraph::Node*, InlinedAllocation<8>>& nodes, int32 templateInputsMapping);
public: public: