Skip to content

Instantly share code, notes, and snippets.

@rorydriscoll
Last active August 30, 2021 07:16
Show Gist options
  • Save rorydriscoll/be1375a63999a272524a to your computer and use it in GitHub Desktop.
Save rorydriscoll/be1375a63999a272524a to your computer and use it in GitHub Desktop.
2D Perlin noise with derivatives
static const int permutations[256] =
{
249, 69, 172, 0, 116, 3, 219, 221,
224, 5, 6, 145, 128, 131, 97, 108,
133, 14, 165, 45, 166, 127, 114, 111,
119, 20, 34, 4, 103, 67, 48, 158,
85, 143, 181, 238, 217, 173, 78, 139,
179, 77, 191, 89, 251, 150, 183, 8,
168, 225, 23, 65, 55, 247, 136, 104,
117, 193, 174, 106, 122, 199, 243, 211,
57, 162, 189, 125, 146, 7, 21, 169,
194, 98, 95, 233, 244, 175, 62, 137,
232, 86, 148, 113, 52, 252, 88, 30,
185, 216, 132, 248, 215, 51, 178, 239,
76, 242, 27, 192, 29, 195, 188, 206,
40, 94, 250, 75, 210, 203, 214, 152,
120, 81, 25, 198, 254, 245, 255, 90,
80, 213, 66, 82, 124, 43, 83, 102,
161, 170, 53, 246, 118, 91, 18, 36,
107, 134, 110, 163, 73, 33, 167, 138,
87, 58, 31, 123, 140, 182, 71, 141,
231, 74, 184, 92, 19, 115, 63, 135,
218, 17, 241, 24, 207, 79, 13, 177,
186, 155, 93, 153, 42, 39, 99, 144,
222, 190, 64, 47, 157, 142, 187, 101,
56, 202, 100, 253, 235, 16, 11, 236,
60, 240, 129, 70, 109, 156, 180, 228,
105, 220, 44, 130, 229, 54, 1, 61,
208, 37, 237, 196, 223, 38, 154, 226,
35, 159, 112, 72, 46, 200, 9, 22,
49, 234, 204, 164, 59, 126, 209, 201,
121, 171, 10, 26, 32, 212, 227, 28,
160, 15, 84, 147, 230, 149, 68, 96,
151, 205, 41, 197, 50, 176, 12, 2
};
void GetIntegerAndFractional(int& i, float& f, float v)
{
const float l = floorf(v);
i = (int)l;
f = v - l;
}
Vector2 Gradient(int xi, int yi)
{
const int hash = permutations[(permutations[xi & 0xff] + yi) & 0xff];
switch (hash & 0x3)
{
case 0x0: return Vector2(+1, +1);
case 0x1: return Vector2(-1, +1);
case 0x2: return Vector2(+1, -1);
case 0x3: return Vector2(-1, -1);
}
return 0;
}
float NoiseWithDerivatives(float& dndx, float& dndy, float x, float y)
{
int i, j;
float u, v;
GetIntegerAndFractional(i, u, x);
GetIntegerAndFractional(j, v, y);
const Vector2 ga = Gradient(i, j);
const Vector2 gb = Gradient(i + 1, j);
const Vector2 gc = Gradient(i, j + 1);
const Vector2 gd = Gradient(i + 1, j + 1);
const float a = u * ga.x + v * ga.y;
const float b = (u - 1) * gb.x + v * gb.y;
const float c = u * gc.x + (v - 1) * gc.y;
const float d = (u - 1) * gd.x + (v - 1) * gd.y;
const float dudx = 30 * u * u * (u * (u - 2) + 1);
const float dvdy = 30 * v * v * (v * (v - 2) + 1);
u = u * u * u * (u * (u * 6 - 15) + 10);
v = v * v * v * (v * (v * 6 - 15) + 10);
const float k0 = 1 - u - v + u * v;
const float k1 = u - u * v;
const float k2 = v - u * v;
const float k3 = u * v;
const float n = a * k0 + b * k1 + c * k2 + d * k3;
// dndx = dadx * k0 + dbdx * k1 + dcdx * k2 + dddx * k3 + dudx * (b - a) + dudx * v * (a - b - c + d)
// dndy = dady * k0 + dbdy * k1 + dcdy * k2 + dddy * k3 + dvdy * (c - a) + dvdy * u * (a - b - c + d)
dndx = ga.x * k0 + gb.x * k1 + gc.x * k2 + gd.x * k3 + dudx * (b - a + (a - b - c + d) * v);
dndy = ga.y * k0 + gb.y * k1 + gc.y * k2 + gd.y * k3 + dvdy * (c - a + (a - b - c + d) * u);
return n;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment