1 using Microsoft.Xna.Framework;
3 using System.Collections.Generic;
11 public static class PerlinNoise
13 public static double OctavePerlin(
double x,
double y,
double z,
double frequency,
int octaves,
double persistence)
17 for (
int i = 0; i < octaves; i++)
19 total += CalculatePerlin(x * frequency, y * frequency, z * frequency) * amplitude;
21 amplitude *= persistence;
30 private static readonly
int[] permutation =
33 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
34 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
35 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
36 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
37 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
38 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
39 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
40 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
41 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
42 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
43 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
44 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
47 private static readonly
int[] p;
49 private static readonly
float[] cachedNoise;
51 private const int CacheResolution = 256;
56 for (
int x = 0; x < 512; x++)
58 p[x] = permutation[x % 256];
61 float minValue =
float.MaxValue;
62 float maxValue =
float.MinValue;
63 cachedNoise =
new float[CacheResolution * CacheResolution];
64 for (
int x = 0; x < CacheResolution; x++)
66 for (
int y = 0; y < CacheResolution; y++)
68 cachedNoise[x + CacheResolution * y] = (float)OctavePerlin(x / (
double)CacheResolution, y / (double)CacheResolution, 0.5, 10, 4, 0.5f);
72 for (
int i = 0; i < CacheResolution * CacheResolution; i++)
74 minValue = Math.Min(cachedNoise[i], minValue);
75 maxValue = Math.Max(cachedNoise[i], maxValue);
79 for (
int i = 0; i < CacheResolution * CacheResolution; i++)
81 cachedNoise[i] = (cachedNoise[i] - minValue) / (maxValue - minValue);
91 public static float GetPerlin(
float x,
float y)
93 x = Math.Abs(x) % 1.0f;
94 y = Math.Abs(y) % 1.0f;
96 float xIndex = x < 0.5f ? (x * 2.0f * CacheResolution) : CacheResolution - ((x - 0.5f) * 2.0f * CacheResolution);
97 xIndex = Math.Min(xIndex, CacheResolution - 1);
99 float yIndex = y < 0.5f ? (y * 2.0f * CacheResolution) : CacheResolution - ((y - 0.5f) * 2.0f * CacheResolution);
100 yIndex = Math.Min(yIndex, CacheResolution - 1);
102 int minX = (int)xIndex, maxX = (
int)Math.Ceiling(xIndex);
103 int minY = (int)yIndex, maxY = (
int)Math.Ceiling(yIndex);
105 return MathHelper.Lerp(
106 MathHelper.Lerp(cachedNoise[minX + minY * CacheResolution], cachedNoise[maxX + minY * CacheResolution], xIndex % 1.0f),
107 MathHelper.Lerp(cachedNoise[minX + maxY * CacheResolution], cachedNoise[maxX + maxY * CacheResolution], xIndex % 1.0f),
111 public static double CalculatePerlin(
double x,
double y,
double z)
113 int xi = (int)x & 255;
114 int yi = (int)y & 255;
115 int zi = (int)z & 255;
116 double xf = x - (int)x;
117 double yf = y - (int)y;
118 double zf = z - (int)z;
125 int ab = p[a + 1] + zi;
126 int b = p[xi + 1] + yi;
128 int bb = p[b + 1] + zi;
132 double x1, x2, y1, y2;
133 x1 = Lerp(Grad(p[aa], xf, yf, zf),
134 Grad(p[ba], xf - 1, yf, zf),
136 x2 = Lerp(Grad(p[ab], xf, yf - 1, zf),
137 Grad(p[bb], xf - 1, yf - 1, zf),
139 y1 = Lerp(x1, x2, v);
141 x1 = Lerp(Grad(p[aa + 1], xf, yf, zf - 1),
142 Grad(p[ba + 1], xf - 1, yf, zf - 1),
144 x2 = Lerp(Grad(p[ab + 1], xf, yf - 1, zf - 1),
145 Grad(p[bb + 1], xf - 1, yf - 1, zf - 1),
147 y2 = Lerp(x1, x2, v);
149 return (Lerp(y1, y2, w) + 1) / 2;
152 public static double Grad(
int hash,
double x,
double y,
double z)
155 double u = h < 8 ? x : y;
162 else if (h == 12 || h == 14 )
167 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
170 public static double Fade(
double t)
175 return t * t * t * (t * (t * 6 - 15) + 10);
178 public static double Lerp(
double a,
double b,
double x)
180 return a + x * (b - a);