0
\$\begingroup\$

I would like to implement a Perlin noise algorithm into my MonoGame project in order to procedurally generate 2D terrain. I've been using engines in the past (Godot, mostly) where there was an API to call, we would set the seed, the octave and frequency to have the wanted noise.

Problem is, in the clean implementations I gathered online, I don't know where I'm supposed to tweak the parameters of the noise.

For instance, with this one implementation that seems to be well-written: how to handle tweaking with octaves & frequency?

Or, with a simpler and shorter code, here with the pseudo-code of the original algorithm.

Thanks!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Godot is open source, maybe you could just port their algorithm to c#? \$\endgroup\$
    – Vaillancourt
    Nov 14 '21 at 16:41
  • 1
    \$\begingroup\$ Yup, I've had the same idea actually! But, Godot algorithm is Open Simplex Noise with up to four dimensions. I thought that if I was really stuck with nothing I would try to translate some 2D part from C++ to C# but I'm not used to C++ nor programming noise generators so I prefered to ask here first -- and @DMGregory answer got me understanding what I needed \$\endgroup\$
    – atrefeu
    Nov 14 '21 at 16:54
1
\$\begingroup\$

These functions compute a single octave of noise.

To layer noise into something like Fractional Brownian Motion (FBM), you can invoke one of these functions multiple times.

Let's say I have a noise function like EvaluateNoise(float x, float y)

The number of octaves determines how many times I call that function. The frequency determines a scaling value I apply to my x,y values before calling it. In addition to this we'll usually have persistence and lacunarity parameters, determining how the amplitude should diminish and frequency increase as we drop down the octaves. Something like...

float EvaluateFBM(float x, float y, 
                  float amplitude, float frequency,
                  int octaveCount, float persistence, float lacunarity) {

    float value = 0;

    for (int i = 0; i < octaveCount; i++) {
        value += amplitude * EvaluateNoise(x * frequency, y * frequency);
        amplitude *= persistence;
        frequency *= lacunarity;
    }

    return value;
}

Persistence (also called gain) is a value in the range (0, 1) that controls how quickly the later octaves "die out". Something around 0.5 is pretty conventional here.

Lacunarity is a value greater than 1 that controls how much finer a scale each subsequent octave should use. Something around 2.0 is a conventional choice.

You may also want to apply an offset to x/y/z at each octave to decorrelate the layers, so you don't see repeated features constructively interfering when you're close to zero.

You can modify this function in various ways to get things like turbulence or ridge noise, IQ Noise, Swiss or Jordan Turbulence, or other custom terrain styles.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much for your deep answer, you've got me out a mess! For some reason there's little ressource explaining these intermediate things. I'll look with interest to the IQ Noise and the Swiss turbulence, thank you for sharing these :) \$\endgroup\$
    – atrefeu
    Nov 14 '21 at 16:49

You must log in to answer this question.

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