Skip to content

Instantly share code, notes, and snippets.

@JSandusky
Created March 23, 2019 01:48
Show Gist options
  • Save JSandusky/b9d030edf793fc55e7f75c64df1f7f83 to your computer and use it in GitHub Desktop.
Save JSandusky/b9d030edf793fc55e7f75c64df1f7f83 to your computer and use it in GitHub Desktop.
Ubernoise
[Description("Uses noise derivatives to produce an extremely versatile noise")]
[PropertyData.PropertyIgnore("Interpolation")]
public partial class UberNoise : NoiseGenerator
{
float lacunarity_ = 2.0f;
int octaves_ = 3;
float gain_ = 0.5f;
float perturbFeatures_ = 0.2f;
float sharpness_ = 0.7f;
float amplify_ = 0.7f;
float altitudeErosion_ = 0.7f;
float ridgeErosion_ = 0.7f;
float slopeErosion_ = 0.7f;
[PropertyData.AllowPermutations]
[Description("Factor to scale each successive octave by")]
public float Lacunarity { get { return lacunarity_; } set { lacunarity_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Number of passes to accumulate")]
public int Octaves { get { return octaves_; } set { octaves_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Power applied to each octave")]
public float Gain { get { return gain_; } set { gain_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Perturbation creates rippled shapes")]
public float PerturbFeatures { get { return perturbFeatures_; } set { perturbFeatures_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Brightness of the ridged pattern")]
public float Sharpness { get { return sharpness_; } set { sharpness_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Intensity of the centers of the ridged pattern")]
public float AmplifyFeatures { get { return amplify_; } set { amplify_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Dampens noise in the pattern")]
public float AltitudeErosion { get { return altitudeErosion_; } set { altitudeErosion_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Intensity of the \"clouds\" like effect")]
public float RidgeErosion { get { return ridgeErosion_; } set { ridgeErosion_ = value; OnPropertyChanged(); } }
[PropertyData.AllowPermutations]
[Description("Smoothness of the overall pattern")]
public float SlopeErosion { get { return slopeErosion_; } set { slopeErosion_ = value; OnPropertyChanged(); } }
public override void Construct()
{
base.Construct();
Name = "Uber-Noise";
}
public override void Execute(object param)
{
Vector4 vParam = (Vector4)param;
Vector4 pos = new Vector4(vParam.X * Period.X, vParam.Y * Period.Y, 0.0f, 0.0f);
float value = 0.0f;
var seed = noise_.GetSeed();
float sum = 0.0f, featureNoise = 0.0f;
var noiseValue = DerivativeNoise(pos, seed);
featureNoise = noiseValue.X;
float max = 0.0f;
float amp = 1.0f;
float currentGain = 1.0f;
int i = 0;
Vector3 lDerivative = new Vector3(noiseValue.Y, noiseValue.Z, noiseValue.W);
var aaddToPos = lDerivative * PerturbFeatures;
pos.X += aaddToPos.X;
pos.Y += aaddToPos.Y;
pos.Z += aaddToPos.Z;
Vector3 ridgeErosionDerivative = new Vector3(0, 0, 0);
Vector3 slopeErosionDerivative = new Vector3(0, 0, 0);
while (++i < Octaves)
{
// Accumulate max (amp * 2 covers full damped amp range)
max += amp * 2 + (currentGain * AmplifyFeatures);
// Accumulate derivatives
ridgeErosionDerivative += lDerivative * RidgeErosion;
slopeErosionDerivative += lDerivative * SlopeErosion;
// Sharpness
float ridgedNoise = ((1.0f) - Mathf.Abs(featureNoise));
float billowNoise = featureNoise * featureNoise;
featureNoise = Mathf.Lerp(featureNoise, billowNoise, Math.Max(0.0f, Sharpness));
featureNoise = Mathf.Lerp(featureNoise, ridgedNoise, Mathf.Abs(Math.Min(0.0f, Sharpness)));
// Slope Erosion
sum += amp * featureNoise * (1.0f / (1.0f + slopeErosionDerivative.LengthSquared()));
// Amplitude damping
float dampedAmp = amp * (1.0f - (RidgeErosion / (1.0f * ridgeErosionDerivative.LengthSquared())));
sum += dampedAmp * featureNoise * (1.0f / (1.0f * slopeErosionDerivative.LengthSquared()));
amp *= Mathf.Lerp(currentGain, currentGain * Mathf.Lerp(0.0f, 1.0f, sum / max), AltitudeErosion);
// Amplify features
sum += featureNoise * currentGain * AmplifyFeatures;
currentGain = currentGain * Gain * AmplifyFeatures;
// Prepare for next pass
seed = (seed + i) & 0x7fffffff;
var addToPos = lDerivative * PerturbFeatures;
pos.X += addToPos.X;
pos.Y += addToPos.Y;
pos.Z += addToPos.Z;
pos.X *= Lacunarity;
pos.Y *= Lacunarity;
pos.Z *= Lacunarity;
pos.W *= Lacunarity;
noiseValue = DerivativeNoise(pos, ++seed);
featureNoise = noiseValue.X;
lDerivative = new Vector3(noiseValue.Y, noiseValue.Z, noiseValue.W);
}
value = Mathf.Clamp01(sum / max);
value = Mathf.Normalize(value, -1.0f, 1.0f);
if (Inverted)
OutputSockets[0].Data = 1.0f - value;
else
OutputSockets[0].Data = value;
// stupid
OutputSockets[1].Data = OutputSockets[0].Data;
}
Vector4 DerivativeNoise(Vector4 p, int seed)
{
float baseNoise = noise_.GetSimplex(p.X, p.Y, p.Z, p.W);
float H = 0.1f;
float dx = noise_.GetSimplex(p.X + H, p.Y, p.Z, p.W) - noise_.GetSimplex(p.X - H, p.Y, p.Z, p.W);
float dy = noise_.GetSimplex(p.X, p.Y + H, p.Z, p.W) - noise_.GetSimplex(p.X, p.Y - H, p.Z, p.W);
float dz = noise_.GetSimplex(p.X, p.Y, p.Z + H, p.W) - noise_.GetSimplex(p.X, p.Y, p.Z - H, p.W);
//var v = new Vector3(dx, dy, dz);
return new Vector4(baseNoise, dx, dy, 1);// v.z);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment