diff --git a/Source/Editor/Surface/Archetypes/Textures.cs b/Source/Editor/Surface/Archetypes/Textures.cs index af8ddf608..60a43a6cb 100644 --- a/Source/Editor/Surface/Archetypes/Textures.cs +++ b/Source/Editor/Surface/Archetypes/Textures.cs @@ -86,6 +86,71 @@ namespace FlaxEditor.Surface.Archetypes } } + // TODO merge the above and below function into one? + internal class ProceduralSampleNode : SurfaceNode + { + private ComboBox _textureGroupPicker; + + public ProceduralSampleNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) + : base(id, context, nodeArch, groupArch) + { + } + + public override void OnValuesChanged() + { + base.OnValuesChanged(); + + UpdateUI(); + } + + public override void OnLoaded() + { + base.OnLoaded(); + + UpdateUI(); + } + + private void UpdateUI() + { + if ((int)Values[1] == (int)CommonSamplerType.TextureGroup) + { + if (_textureGroupPicker == null) + { + _textureGroupPicker = new ComboBox + { + Location = new Float2(FlaxEditor.Surface.Constants.NodeMarginX + 50, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.LayoutOffsetY * 3), + Width = 100, + Parent = this, + }; + _textureGroupPicker.SelectedIndexChanged += OnSelectedTextureGroupChanged; + var groups = GameSettings.Load(); + if (groups?.TextureGroups != null) + { + for (int i = 0; i < groups.TextureGroups.Length; i++) + _textureGroupPicker.AddItem(groups.TextureGroups[i].Name); + } + } + else + { + _textureGroupPicker.Visible = true; + } + _textureGroupPicker.SelectedIndexChanged -= OnSelectedTextureGroupChanged; + _textureGroupPicker.SelectedIndex = (int)Values[2]; + _textureGroupPicker.SelectedIndexChanged += OnSelectedTextureGroupChanged; + } + else if (_textureGroupPicker != null) + { + _textureGroupPicker.Visible = false; + } + ResizeAuto(); + } + + private void OnSelectedTextureGroupChanged(ComboBox comboBox) + { + SetValue(2, _textureGroupPicker.SelectedIndex); + } + } + /// /// The nodes for that group. /// @@ -408,19 +473,24 @@ namespace FlaxEditor.Surface.Archetypes new NodeArchetype { TypeID = 17, + Create = (id, context, arch, groupArch) => new ProceduralSampleNode(id, context, arch, groupArch), Title = "Procedural Sample Texture", Description = "Samples a texture to create a more natural look with less obvious tiling.", Flags = NodeFlags.MaterialGraph, - Size = new Float2(240, 60), + Size = new Float2(240, 100), DefaultValues = new object[] { new Float2(1.0f, 1.0f), + 2, + 0, }, Elements = new[] { NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0), NodeElementArchetype.Factory.Input(1, "UV", true, typeof(Float2), 1, 0), NodeElementArchetype.Factory.Output(0, "Color", typeof(Float4), 2), + NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY * 2, "Sampler"), + NodeElementArchetype.Factory.ComboBox(50, Surface.Constants.LayoutOffsetY * 2, 100, 1, typeof(CommonSamplerType)) } }, }; diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp index 66024540c..9c786a827 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp @@ -672,6 +672,20 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) // Procedural Texture Sample case 17: { + enum CommonSamplerType + { + LinearClamp = 0, + PointClamp = 1, + LinearWrap = 2, + PointWrap = 3, + TextureGroup = 4, + }; + const Char* SamplerNames[] + { + TEXT("SamplerLinearClamp"), + TEXT("SamplerLinearWrap"), + }; + auto textureBox = node->GetBox(0); auto uvsBox = node->GetBox(1); @@ -706,6 +720,23 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) const auto textureParam = findParam(texture.Value); const bool isNormalMap = textureParam->Type == MaterialParameterType::NormalMap; + const Char* samplerName; + const int32 samplerIndex = node->Values[1].AsInt; + if (samplerIndex == TextureGroup) + { + auto& textureGroupSampler = findOrAddTextureGroupSampler(node->Values[2].AsInt); + samplerName = *textureGroupSampler.ShaderName; + } + else if (samplerIndex >= 0 && samplerIndex < ARRAY_COUNT(SamplerNames)) + { + samplerName = SamplerNames[samplerIndex]; + } + else + { + OnError(node, box, TEXT("Invalid texture sampler.")); + return; + } + auto result = writeLocal(Value::InitForZero(ValueType::Float4), node); createGradients(node); @@ -741,14 +772,15 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) " UV1 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 );\n" " UV2 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 );\n" " UV3 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 );\n" - " float4 tex1 = {1}.SampleGrad(SamplerLinearWrap, UV1, {2}, {3});\n" - " float4 tex2 = {1}.SampleGrad(SamplerLinearWrap, UV2, {2}, {3});\n" - " float4 tex3 = {1}.SampleGrad(SamplerLinearWrap, UV3, {2}, {3});\n" + " float4 tex1 = {1}.SampleGrad({4}, UV1, {2}, {3});\n" + " float4 tex2 = {1}.SampleGrad({4}, UV2, {2}, {3});\n" + " float4 tex3 = {1}.SampleGrad({4}, UV3, {2}, {3});\n" ), uvs.Value, // {0} texture.Value, // {1} _ddx.Value, // {2} - _ddy.Value // {3} + _ddy.Value, // {3} + samplerName // {4} ); // Decode normal map vector