1
\$\begingroup\$

I'm trying to generate a 2D map and currently I'm doing so by the use of voronoi diagram. The problem I found is that all biomes have really hard edges and I would like to smooth them out a bit.

enter image description here

Initially I was thinking smoothing out voronoi curves, which appears to be far more complex as I imagined. Then I thought about perlin distorion, which seems far more doable. Although, I'm not sure what is the best way to implement this.

This is the function I use to generate a voronoi diagram:

void Generate()
{
    Vector2Int[] centroids = new Vector2Int[regions.Length];
    Color[] regColors = new Color[regions.Length];
    for (int i = 0; i < regions.Length; i++)
    {
        centroids[i] = new Vector2Int(Rand.Range(0, map), Rand.Range(0, map));
        regColors[i] = regions[i].color;
    }
    Color[] colors = new Color[map * map];
    for (int x = 0; x < map; x++)
    {
        for (int y = 0; y < map; y++)
        {
            int index = x * map + y;
            colors[index] = regColors[GetClosestCentroidIndex(new Vector2Int(x, y), centroids)];
        }
    }
}
int GetClosestCentroidIndex(Vector2Int pixelPos, Vector2Int[] centroids)
{
    float smallestDst = float.MaxValue;
    int index = 0;
    for (int i = 0; i < centroids.Length; i++)
    {
        if (Vector2.Distance(pixelPos, centroids[i]) < smallestDst)
        {
            smallestDst = Vector2.Distance(pixelPos, centroids[i]);
            index = i;
        }
    }
    return index;
}

While doing some research I stumbled upon this website, which shows the exact result I'm trying to achieve: https://observablehq.com/@kerryrodden/image-distortion-with-perlin-noise

Can someone help me with this problem? Thank you

[Solved]

By the help of the user DMGregory, the map is now looking much better! This is the new voronoi diagram, after the distortion had been applied.

enter image description here

Currently, I'm using these settings, but I will probably tweak them later.

Scale: 10
Octave Count: 1
Amplitude: 4
Lacunarity: 1
Persistence: 1

And for the seed, currently, I'm using just a randomly generated seed.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

First, give yourself a 2D turbulence function with parameters you can adjust to shape the noise the way you want:

public float baseScale = 50.0f;
public int octaveCount = 4;
public float amplitude = 5.0f;
public float lacunarity = 2.0f;
public float persistence = 0.5f;

// Arbitrary numbers to break up visible correlation between octaves / x & y
public Vector2 seed = new Vector2(-71, 37); 

Vector2 Get2DTurbulence(Vector2 input) {

    input = input/baseScale + seed;
    float a = 2f * amplitude;

    Vector2 noise = Vector2.zero;

    for(int octave = 0; octave < octaveCount; octave++) {
        noise.x += a * (Mathf.PerlinNoise(input.x, input.y) - 0.5f);
        noise.y += a * (Mathf.PerlinNoise(input.x + seed.y, input.y + seed.y) - 0.5f);
        input = input * lacunarity + seed;
        a *= persistence;
    }

    return noise
}

Then add turbulence to your position before you use it to find the closest centroid:

int GetClosestCentroidIndex(Vector2Int pixelPos, Vector2Int[] centroids)
{
    Vector2 warpedPos = pixelPos + Get2DTurbulence(pixelPos);

    float smallestDst = float.MaxValue;
    int index = 0;
    for (int i = 0; i < centroids.Length; i++)
    {
        float distance = Vector2.Distance(warped, centroids[i]);
        if (distance < smallestDst)
        {
            smallestDst = distance;
            index = i;
        }
    }
    return index;
}
\$\endgroup\$
6
  • \$\begingroup\$ Works great! Thank you :) \$\endgroup\$ Commented May 14, 2020 at 19:42
  • \$\begingroup\$ I'd love to see an image of your result, if you'd like to edit it into this answer. :) Sharing the parameter values you used could help future users too — I just guessed at these ones without running the code. ;) \$\endgroup\$
    – DMGregory
    Commented May 14, 2020 at 19:43
  • \$\begingroup\$ Of course! I added a small update of the final result :) The map is not looking too interesting at the moment, but that's because more biomes will be added. But the shape of the regions is now looking much better! \$\endgroup\$ Commented May 14, 2020 at 20:07
  • \$\begingroup\$ Nicely done! You might also be interested in the notion of the Worley noise basis, where you use not just the identity of the closest noise point, but also the distance to the closest noise point, or distance to the second-closest, or difference between closest & 2nd-closest distances etc. This can help you generate internal structure in your cells, or cross-fade near the border regions. More on the relationships between these noise bases and cool stuff you can do with them here \$\endgroup\$
    – DMGregory
    Commented May 14, 2020 at 20:46
  • \$\begingroup\$ Thank you for the advice and the link to the website! I was thinking about this, how can I recognize the borders of the regions. When the map is generated I will then create props and doodads on each cell and would like to also create mountains or trees surround each region. To kind of separate them better. I will try to read through this website and hopefully figure out the best way in doing this. Cause at the moment the only way I can think of is to look around each cell and if the neighbor cell belongs to the other type of region, create a separator, which is either a tree or a mountain. \$\endgroup\$ Commented May 18, 2020 at 12:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .