-
-
Save chaojian-zhang/1b32c77a39ce5045c325e9c63b17d3be 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 up to size of 512 to avoid using 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