I am quite new to the wondrous world of "Procedural Textures", and I am trying to create a double precission perlin noise algorithm.
I am almost done with it except for the fact that the coordinates seem to be off, any idea what I've done wrong? Here's the code:
public static class Noise { static int[] p = new int[Convert.ToInt32(Math.Pow(2,16))]; public static vector2dDouble v1i; public static vector2dDouble v2i; public static vector2dDouble v3i; public static vector2dDouble v4i; public static double[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector3 offset) { double[,] noiseMap = new double[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) + offset.z; octaveOffsets[i] = new Vector2(offsetX, offsetY); } if (scale <= 0) { scale = 0.0001f; } float maxNoiseHeight = float.MinValue; float minNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { float amplitude = 1; float frequency = 1; double noiseHeight = 0; for (int i = 0; i < octaves; i++) { double sampleX = (double)(x - halfWidth) / scale * frequency + octaveOffsets[i].x + 0.001; double sampleY = (double)(y - halfHeight) / scale * frequency + octaveOffsets[i].y + 0.001; double perlinValue = Noise2d(sampleX, sampleY); noiseHeight += perlinValue * amplitude; //Debug.Log(perlinValue); amplitude *= persistance; frequency *= lacunarity; } if (noiseHeight > maxNoiseHeight) { maxNoiseHeight = (float)noiseHeight; } else if (noiseHeight < minNoiseHeight) { minNoiseHeight = (float)noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < noiseMap.GetLength(1); y++) { for (int x = 0; x < noiseMap.GetLength(0); x++) { noiseMap[x, y] = (double)Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, (float)noiseMap[x, y]); } } [![enter image description here][1]][1] return noiseMap; } public static void init(int seed) { createGradients(p, seed); } public static int[] createGradients(int[] p, int seed) { System.Random prng = new System.Random(seed); for (int i = 0; i < p.GetLength(0) / 2; i++) { p[i] = prng.Next(0, 256); p[i + ((int)p.GetLength(0) / 2)] = p[i]; } return p; } static vector2dDouble generateGradient(int val) { int hash = val & 3; switch (hash) { case 0: return new vector2dDouble(1.0, 1.0); case 1: return new vector2dDouble(-1.0, 1.0); case 2: return new vector2dDouble(-1.0, -1.0); case 3: return new vector2dDouble(1.0, -1.0); default: return new vector2dDouble(0, 0); } } static double Noise2d(double x, double y) { int ix = Convert.ToInt32(Math.Floor(x)) & (p.GetLength(0) / 2 - 1); int iy = Convert.ToInt32(Math.Floor(y)) & (p.GetLength(0) / 2 - 1); x -= Math.Floor(x); y -= Math.Floor(y); vector2dDouble v1 = new vector2dDouble(x - 1, y), v2 = new vector2dDouble(x - 1, y - 1), v3 = new vector2dDouble(x, y), v4 = new vector2dDouble(x, y - 1); int g1 = p[p[ix + 1] + iy + 1], g2 = p[p[ix] + iy + 1], g3 = p[p[ix + 1] + iy], g4 = p[p[ix] + iy]; double u = fade(x); double v = fade(y); double f1 = v1.dot(generateGradient(g1)), f2 = v2.dot(generateGradient(g2)), f3 = v3.dot(generateGradient(g3)), f4 = v4.dot(generateGradient(g4)); return lerp(u, lerp(v, f2, f4), lerp(v ,f1, f3)); } static double lerp(double t, double argc, double argv) { return argc + t * (argv - argc); } static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); } } [System.Serializable] public struct vector2dDouble { public double x, y; public vector2dDouble(double argx, double argy) { x = argx; y = argy; } public double dot(vector2dDouble argc) { argc.x *= x; argc.y *= y; return argc.x + argc.y; } public void print() { Debug.Log(x + "," + y); } }