-
-
Save Kakusakov/c2706dc3ab3c11427606159ef6dd724b to your computer and use it in GitHub Desktop.
Improved Perlin Noise Implementation in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Clone of https://gist.github.com/Flafla2/1a0b9ebef678bbce3215 with more dimensions and seed generation. | |
public class PerlinGen | |
{ | |
private readonly int[] p; // Randomly shuffled array of values from 0 to 255. | |
// Values are repeated twice to get performance boost | |
// from avoiding the use of modulo operator. | |
public PerlinGen(int seed) | |
{ | |
// Generate p. | |
p = new int[512]; | |
System.Random rng = new(seed); | |
for (int i = 0; i < 256; ++i) p[i] = i; | |
int n = 256; | |
while (n > 1) | |
{ | |
int k = rng.Next(n--); | |
(p[k], p[n]) = (p[n], p[k]); | |
} | |
for (int i = 0; i < 256; ++i) p[i + 256] = p[i]; | |
} | |
public PerlinGen(PerlinGen copy) | |
{ | |
p = copy.p; | |
} | |
public float Perlin3(float x, float y, float z) | |
{ | |
int xi = (int)x & 255; | |
int yi = (int)y & 255; | |
int zi = (int)z & 255; | |
x -= (int)x; | |
y -= (int)y; | |
z -= (int)z; | |
float u = Fade(x); | |
float v = Fade(y); | |
float w = Fade(z); | |
int A = p[xi] + yi; | |
int AA = p[A] + zi; | |
int AB = p[A + 1] + zi; | |
int B = p[xi + 1] + yi; | |
int BA = p[B] + zi; | |
int BB = p[B + 1] + zi; | |
return Lerp(w, | |
Lerp(v, | |
Lerp(u, Grad3(p[AA], x, y, z), Grad3(p[BA], x - 1, y, z)), | |
Lerp(u, Grad3(p[AB], x, y - 1, z), Grad3(p[BB], x - 1, y - 1, z)) | |
), | |
Lerp(v, | |
Lerp(u, Grad3(p[AA + 1], x, y, z - 1), Grad3(p[BA + 1], x - 1, y, z - 1)), | |
Lerp(u, Grad3(p[AB + 1], x, y - 1, z - 1), Grad3(p[BB + 1], x - 1, y - 1, z - 1)) | |
) | |
); | |
} | |
public float Perlin2(float x, float y) | |
{ | |
int xi = (int)x & 255; | |
int yi = (int)y & 255; | |
x -= (int)x; | |
y -= (int)y; | |
float u = Fade(x); | |
float v = Fade(y); | |
int A = p[xi] + yi; | |
int B = p[xi + 1] + yi; | |
return Lerp(v, | |
Lerp(u, Grad2(p[A], x, y), Grad2(p[B], x - 1, y)), | |
Lerp(u, Grad2(p[A + 1], x, y - 1), Grad2(p[B + 1], x - 1, y - 1)) | |
); | |
} | |
public float Perlin1(float x) | |
{ | |
int xi = (int)x & 255; | |
x -= (int)x; | |
float u = Fade(x); | |
return Lerp(u, Grad1(p[xi], x), Grad1(p[xi + 1], x - 1)); | |
} | |
public static float Fade(float t) => t * t * t * (t * (t * 6 - 15) + 10); | |
public static float Grad3(int hash, float x, float y, float z) | |
{ | |
int h = hash & 15; | |
float u = h < 8 ? x : y; | |
float v = h < 4 ? y : h == 12 || h == 14 ? x : z; | |
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); | |
} | |
public static float Grad2(int hash, float x, float y) | |
{ | |
return ((hash & 1) == 0 ? x : -x) + ((hash & 2) == 0 ? y : -y); | |
} | |
public static float Grad1(int hash, float x) | |
{ | |
return (hash & 1) == 0 ? x : -x; | |
} | |
public static float Lerp(float t, float a, float b) => a + t * (b - a); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment