diff --git a/Content/Editor/Particles/Smoke.flax b/Content/Editor/Particles/Smoke.flax
index 06eda8aaf..1335a84f4 100644
--- a/Content/Editor/Particles/Smoke.flax
+++ b/Content/Editor/Particles/Smoke.flax
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d92b6e83025ca078058dead6f1fb0ebbc4ce2b7835ca9d0ae7d31ef913745c72
-size 16157
+oid sha256:c3dc51e7805056006ca6cbb481ba202583a9b2287c152fc04e28e1d07747d6ce
+size 14706
diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs
index d924f69f5..21fe069db 100644
--- a/Source/Editor/Surface/Archetypes/Tools.cs
+++ b/Source/Editor/Surface/Archetypes/Tools.cs
@@ -1260,6 +1260,23 @@ namespace FlaxEditor.Surface.Archetypes
}
}
+ private static NodeArchetype Noise(ushort id, string name, Type resultType, Type pointType, string desc)
+ {
+ return new NodeArchetype
+ {
+ TypeID = id,
+ Title = name,
+ Description = desc,
+ Flags = NodeFlags.MaterialGraph | NodeFlags.ParticleEmitterGraph | NodeFlags.AnimGraph,
+ Size = new Float2(150, 20),
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Point", true, pointType, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, resultType, 1),
+ }
+ };
+ }
+
///
/// The nodes for that group.
///
@@ -1736,6 +1753,11 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Output(0, string.Empty, null, 1, true),
}
},
+ Noise(30, "Perlin Noise", typeof(float), typeof(Float2), "Classic Perlin noise (normalized to 0-1)."),
+ Noise(31, "Simplex Noise", typeof(float), typeof(Float2), "Simplex noise (normalized to 0-1)."),
+ Noise(32, "Worley Noise", typeof(Float2), typeof(Float2), "Worley noise (cellar noise with standard 3x3 search window for F1 and F2 values)."),
+ Noise(33, "Voronoi Noise", typeof(Float3), typeof(Float2), "Voronoi noise (X=minDistToCell, Y=randomColor, Z=minEdgeDistance)."),
+ Noise(34, "Custom Noise", typeof(float), typeof(Float3), "Custom noise function (3D -> 1D)."),
};
}
}
diff --git a/Source/Engine/Utilities/Noise.h b/Source/Engine/Utilities/Noise.h
index c8a12fd1a..96ddcb2a3 100644
--- a/Source/Engine/Utilities/Noise.h
+++ b/Source/Engine/Utilities/Noise.h
@@ -42,7 +42,7 @@ public:
API_FUNCTION() static Float2 WorleyNoise(const Float2& p);
///
- /// Voronoi noise.
+ /// Voronoi noise (X=minDistToCell, Y=randomColor, Z=minEdgeDistance).
///
/// Point on a 2D grid to sample noise at.
/// Noise result with: X=minDistToCell, Y=randomColor, Z=minEdgeDistance.
diff --git a/Source/Engine/Visject/ShaderGraph.cpp b/Source/Engine/Visject/ShaderGraph.cpp
index 322828697..a17964d67 100644
--- a/Source/Engine/Visject/ShaderGraph.cpp
+++ b/Source/Engine/Visject/ShaderGraph.cpp
@@ -793,6 +793,41 @@ void ShaderGenerator::ProcessGroupTools(Box* box, Node* node, Value& value)
case 29:
value = tryGetValue(node->GetBox(0), Value::Zero);
break;
+ // Noises
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ {
+ _includes.Add(TEXT("./Flax/Noise.hlsl"));
+ const Char* format;
+ ValueType pointType = VariantType::Float2;
+ ValueType resultType = VariantType::Float;
+ switch (node->TypeID)
+ {
+ case 30:
+ format = TEXT("PerlinNoise({0})");
+ break;
+ case 31:
+ format = TEXT("SimplexNoise({0})");
+ break;
+ case 32:
+ format = TEXT("WorleyNoise({0})");
+ resultType = VariantType::Float2;
+ break;
+ case 33:
+ format = TEXT("VoronoiNoise({0})");
+ resultType = VariantType::Float3;
+ break;
+ case 34:
+ format = TEXT("CustomNoise({0})");
+ pointType = VariantType::Float3;
+ break;
+ }
+ value = writeLocal(resultType, String::Format(format, tryGetValue(node->GetBox(0), Value::Zero).Cast(pointType).Value), node);
+ break;
+ }
default:
break;
}
diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp
index fa7ab24a0..4f4ca0c41 100644
--- a/Source/Engine/Visject/VisjectGraph.cpp
+++ b/Source/Engine/Visject/VisjectGraph.cpp
@@ -15,6 +15,7 @@
#include "Engine/Scripting/ManagedCLR/MUtils.h"
#include "Engine/Serialization/MemoryReadStream.h"
#include "Engine/Utilities/StringConverter.h"
+#include "Engine/Utilities/Noise.h"
#define RAND Random::Rand()
#define ENSURE(condition, errorMsg) if (!(condition)) { OnError(node, box, errorMsg); return; }
@@ -1052,6 +1053,22 @@ void VisjectExecutor::ProcessGroupTools(Box* box, Node* node, Value& value)
case 29:
value = tryGetValue(node->GetBox(0), Value::Zero);
break;
+ // Noises
+ case 30:
+ value = Noise::PerlinNoise((Float2)tryGetValue(node->GetBox(0)));
+ break;
+ case 31:
+ value = Noise::SimplexNoise((Float2)tryGetValue(node->GetBox(0)));
+ break;
+ case 32:
+ value = Noise::WorleyNoise((Float2)tryGetValue(node->GetBox(0)));
+ break;
+ case 33:
+ value = Noise::VoronoiNoise((Float2)tryGetValue(node->GetBox(0)));
+ break;
+ case 34:
+ value = Noise::CustomNoise((Float3)tryGetValue(node->GetBox(0)));
+ break;
default:
break;
}
diff --git a/Source/Engine/Visject/VisjectGraph.h b/Source/Engine/Visject/VisjectGraph.h
index 6e2c338b1..cd560d47f 100644
--- a/Source/Engine/Visject/VisjectGraph.h
+++ b/Source/Engine/Visject/VisjectGraph.h
@@ -259,6 +259,11 @@ protected:
return defaultValue;
}
+ FORCE_INLINE Value tryGetValue(Box* box)
+ {
+ return box && box->HasConnection() ? eatBox(box->GetParent(), box->FirstConnection()) : Value::Zero;
+ }
+
FORCE_INLINE Value tryGetValue(Box* box, const Value& defaultValue)
{
return box && box->HasConnection() ? eatBox(box->GetParent(), box->FirstConnection()) : defaultValue;