OpenSimplexNoise not returning noise values from [-1, 1]

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By eod

When I run get_noise_2d() I don’t get values returned that are in the range of -1 to 1. It always in a range from about -0.57 to 0.57

var _osn:OpenSimplexNoise = OpenSimplexNoise.new()

_osn.lacunarity = 2.0
_osn.octaves = 3
_osn.period = 64.0
_osn.persistence = 0.5 
randomize()
_osn.set_seed(randi())

for x in range(60):
    for y in range(60):
        print(_osn.get_noise_2d(float(x), float(y)))

I’ve played around with different values with the period, octaves, persistence etc…

Is there a way to make it so the noise always ranges the full spread of -1 to 1?

If not, What is a good practice for determining what high, medium and low noise values are?

e.g. I’m trying to determine “high” noise values for mountain tiles, “low” noise values for water tiles, etc… I was putting something like this, but no mountains or hills were ever printed, since the noise_value never really got higher than 0.57

var noise_sample:float = _osn.get_noise_2d(float(x), float(y))

if noise_sample < -0.4: print("Water")
elif noise_sample < 0.4: print("Grass")
elif noise_sample < 0.7: print("Hill")
else: print("Mountain")

eod | 2020-01-16 07:33

:bust_in_silhouette: Reply From: Zylann

Remember noise is random. As a matter of probability, it is increasingly rare to get values near -1 or 1, especially with smooth noise such as OpenSimplex.

You have a period of 64, which means “hill” patterns will have that length.
So the general “shape” of the 60x60 area you are testing only represents part of a hill. For that hill in particular it’s very unlikely you will reach values near the limits. If we divided space by 64, it would be as if you generated 2x2 numbers to form a square and interpolated corner values inside of it. 4 random numbers is too few to measure.

If you try a larger area, or if you decrease period, you will notice the minimum and maximum values get closer to -1 and 1.

However…
After testing more, I found that even with 1 octave and a period of 1, the maximum I could get was:

Min: -0.864366
Max: 0.864366

And never beyond. Yet this is over a 10,000 x 1,000 area, and the seed was randomized on each run… maybe there is a flaw somewhere.
The Godot wrapper class looks fine, so this has to do with the C implementation of OpenSimplex itself.

Appreciate the additional detailed info, and the confirmation that reaching the min/max of -1/1 may be an issue of OpenSimplex itself.

I think what I’ll do is: generate the noise values, get the min/max, and then from there, dynamically determine where the cut off noise values should be, so that like 5% is mountains, 20% is hills etc…

eod | 2020-01-16 21:15

I’d not rely on this as it would make the normalization different on each run (unless you really intend to even out sea and land no matter the seed).
Based on my experimental result you could normalize the result by dividing noise values by 0.864366, as I’m fairly confident this is the actual boundary.

I discussed with the original author of the algorithm and he made an updated version called “SuperSimplexNoise”, or “OpenSimplex2”, which hasn’t been ported to Godot yet.

Zylann | 2020-01-17 13:25

Interesting, just looked into that OpenSimplex2.

For the porting of OpenSimplex2 to Godot, any idea if it’s on the “todo” list? Or how I/we could submit a request?

I think the % is OK for my specific use case, as when I generate a map, I do have a specific parameter that requests that (e.g.) 50% of the map be land, 25% be water etc…

eod | 2020-01-20 16:49

I’m not sure about next-gen OpenSimplex, but someone is working on integrating FastNoise with new types of noise: https://github.com/godotengine/godot/pull/35144

Zylann | 2020-01-20 19:24