public PerlinNoise(int octaves, float amplitude, float roughness, Vector2 offset, NormaliseMode normaliseMode) { this.seed = new System.Random().Next(1000000000); this.octaves = octaves; this.amplitude = amplitude; this.roughness = roughness; this.offset = offset; this.normaliseMode = normaliseMode; System.Random prng = new System.Random(this.seed); this.octaveOffsets = new Vector2[this.octaves]; for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-100000, 100000) + this.offset.x; float offsetY = prng.Next(-100000, 100000) - this.offset.y; this.octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += (float)Mathf.Pow(this.roughness, i) * this.amplitude; } }
public static float[,] GenerateNoiseMap(int width, int height, float scale, int octaves, float persistance, float lacunarity, int seed, Vector2 offset, NormaliseMode normMode) { if (scale <= 0) { scale = 0.001f; } System.Random prng = new System.Random(seed); float amplitude = 1; float freq = 1; float noiseHeight = 0; float maxPossHeight = 0f; float minPossHeight = 0f; // Sample each octave from a new part (increases noise) 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.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossHeight += amplitude; amplitude *= persistance; } // Used to normalise the noisemap at end float maxNoiseVal = float.MinValue; float minNoiseVal = float.MaxValue; // Used to offset the noise to the centre instead of top-left float hWidth = width / 2f; float hHeight = height / 2f; float[,] noiseMap = new float[width, height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { amplitude = 1; freq = 1; noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - hWidth + octaveOffsets[i].x) / scale * freq; float sampleY = (y - hHeight + octaveOffsets[i].y) / scale * freq; float perlinVal = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinVal * amplitude; amplitude *= persistance; freq *= lacunarity; } if (noiseHeight > maxNoiseVal) { maxNoiseVal = noiseHeight; } else if (noiseHeight < minNoiseVal) { minNoiseVal = noiseHeight; } noiseMap[x, height - 1 - y] = noiseHeight; } } // Normalise noisemap between min and max values to be between 0f - 1f for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (normMode == NormaliseMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minNoiseVal, maxNoiseVal, noiseMap[x, y]); } if (normMode == NormaliseMode.Global) { noiseMap[x, y] = ((noiseMap[x, y] + 1) / (2f * maxPossHeight / 1.75f)); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormaliseMode normalisedMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency += lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalisedMode == NormaliseMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalisedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalisedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, float scale, int octaves, float persistance, float lacunarity, int seed, Vector2 offset, NormaliseMode normaliseMode) { System.Random prng = new System.Random(seed); Vector2[] octavesOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; i++) //randomly offset octabes from each other to make random landscape { float offsetx = prng.Next(-100000, 100000) + offset.x; //empirical values float offsety = prng.Next(-100000, 100000) - offset.y; octavesOffsets [i] = new Vector2(offsetx, offsety); maxPossibleHeight += amplitude; amplitude *= persistance; } float[,] noiseMap = new float [mapWidth, mapHeight]; if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x + octavesOffsets [i].x) / scale * frequency; // + offset.x; float sampleY = (y + octavesOffsets[i].y) / scale * frequency; //+ offset.y; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // multiply by 2 and negate one to ensure in range -1 to 1 noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } //get range of noise height values to defina a max and a min value (to allow for normalisation) if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap [x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normaliseMode == NormaliseMode.local) //if generating single chunk - ie not procedural { noiseMap [x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap [x, y]); //inverselerp method standardises the noiseheingt (it returns a value between 0-1) } else { float normalisedHeight = (noiseMap [x, y] + 1) / (2f * maxPossibleHeight / 5f); //reverses the operation above. The final float is an empirical correction to compensate for scaling by the maxpossible height noiseMap[x, y] = Mathf.Clamp(normalisedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int _width, int _height, int _seed, float _scale, int _octaves, float _persistence, float _lacunarity, Vector2 _offset, NormaliseMode _normaliseMode) { float[,] noiseMap = new float[_width, _height]; System.Random prng = new System.Random(_seed); Vector2[] octaveOffsets = new Vector2[_octaves]; float maxGlobalNoiseHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < _octaves; i++) { float offsetX = prng.Next(-100000, 100000) + _offset.x; float offsetY = prng.Next(-100000, 100000) - _offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxGlobalNoiseHeight += amplitude; amplitude *= _persistence; } if (_scale <= 0) { _scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = _width / 2; float halfHeight = _height / 2; for (int y = 0; y < _height; y++) { for (int x = 0; x < _width; x++) { frequency = 1; amplitude = 1; float noiseHeight = 0; for (int i = 0; i < _octaves; i++) { // the higher the freuency, the further away the sample points, // this means the height changes more rapidly float sampleX = (x - halfWidth + octaveOffsets[i].x) / _scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / _scale * frequency; // generate values between -1 and 1 so that there can be dips in the // terrain when it is later generated float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= _persistence; // frequency increases per octave since lacunarity is greater // than 1. frequency *= _lacunarity; } // work out the range of the noisemap values if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } // normalise the noise map for (int y = 0; y < _height; y++) { for (int x = 0; x < _width; x++) { if (_normaliseMode == NormaliseMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { // make the height values consistent across the entire map float normalizedHeight = (noiseMap[x, y] + 1) / (2 * maxGlobalNoiseHeight / 1.75f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }