Monday, September 7, 2015

procedural generation - Creating a set of islands by subtracting gradient values from a Perlin noise


The answers to this question explains fairly well how to create a big island in the center of the screen by setting up a gradient and then subtracting its value from a Perlin Noise.


Anyway they explain how to create only one gradient at the center of the screen to create a big, sort of circular island.


But what if I want to create an island which has more than one gradient to create a less regular shape, or if I want to create multiple separated islands by setting multiple gradients in different positions? What value should I subtract from the Perlin Noise function for each point? The sum of the distance from each gradient to that point? The average?


Edit: Jon's method of multiplying and normalizing worked, got this result with 4 gradient points:


4 gradients: one with center in the top-left corner, one on down-left, another is in the center and the last is a bit on the right of the center



Answer



You can blend noise together easily, the concept is pretty simple. You essentially loop through each noise value, and perform an operation on the data, and then save the result. It is also a good idea to normalize this data as it makes it easier to use for future operations.


Here is a simple container class to hold resulting noise data:



public class MapData {

public float[,] Data;
public float Min { get; set; }
public float Max { get; set; }

public MapData(int width, int height)
{
Data = new float[width, height];
Min = float.MaxValue;

Max = float.MinValue;
}
}

Using this class, we can generate and store our noise data. You don't have to use this, but it makes it easier to have something to manage your generated noise data. We will use this to blend the gradients together:


blendData = new MapData (Width, Height);

Grab your data and blend it, keeping track of your upper/lower limits:


// first pass - blend gradient values
for (var x = 0; x < Width; x++) {

for (var y = 0; y < Height; y++) {

// Get both gradient values
float gradValue1 = (float)GradientMap1.Get (nx, ny);
float gradValue2 = (float)GradientMap2.Get (nx, ny);

// Multiply
float blendValue = gradValue1 * gradValue2;

// keep track of the max and min values found

if (blendValue > blendData.Max) blendData.Max = blendValue;
if (blendValue < blendData.Min) blendData.Min = blendValue;

blendData.Data[x,y] = blendValue;
}
}

Normalize the resulting data, so that you don't have crazy values to deal with in the future:


// secondary pass to normalize the blended values
for (var x = 0; x < Width; x++) {

for (var y = 0; y < Height; y++) {
blendData.Data[x,y] = (blendData.Data[x,y] - blendData.Min) / (blendData.Max - blendData.Min);
}
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...