fenomas / noa

Experimental voxel game engine.
MIT License
611 stars 87 forks source link

How to make realistic terrain. #125

Closed csf30816 closed 4 years ago

csf30816 commented 4 years ago

I've been using Simplex noise to make the terrain for my voxel game using your engine. The result is okay but it's pretty much all hills. So I made another noise that's flatter and interpolated them together using another noise value. It still isn't what I want.

I am wondering how I could achieve realistic terrain with flatlands, mountains, cliffs, hills, and natural-looking water spots (right now ALL my water spots are surrounded by hills/mountains and are very steep/deep). I've been searching the internet and couldn't find much. I went here as a last resort to hope somebody knew this stuff better than me.

My current code:

const mountains = noise(x * 0.01, z * 0.01, 3 /*octaves*/) * 50;
const flatlands = noise(x * 0.05, z * 0.05, 1) * 10;
const value = 0.5 + noise(x * 0.01, z * 0.01, 1) / 2; // Normalize since noise returns -1 to 1

const height = lerp(mountains, flatlands, value);

also, it'd be nice to know how to do rivers :)

csf30816 commented 4 years ago

So I just tried something that made it look a bit better. I made a BIG LONG base ground that made it look better. Then I subtracted in the water parts to make it deeper. I am currently trying to add mountains but when I do there is a huge cliff seamline where the mountains are added and where the mountains were not added. I tried fixing that with interpolation but that wrecked the oceans interpolation and made a big cliff border in the ocean. I'll update if I find a solution.

EDIT:

Okay so I fixed that (it was pretty easy) so now I have good hills and good water spots (oceans). Going to attempt to add large pointy mountains and flat areas (as most of my flat areas got wiped out when I added hills, and yeah, the things that I said were mountains earlier ended up being hills when I fixed the issue).

EDIT:

Added better flat areas (really I just realized that there are some that are pretty good). Gonna attempt cliffs. Gonna be tricky, once I am done with the whole thing I'll postcode here so other people can learn, it's really just trial and error stuff. Aight I'm skipping cliffs for now. Doing caves. Currently using Simplex3D but they are just short tubes with no flat areas or anything.

EDIT:

Simplex3D slowed down the game and didn't look good enough to make that slowness worth it. It basically just made a bunch of holes in the ground with little chambers.

EDIT:

For rivers, I tried just doing a Simplex2D noise that had a threshold set to around 0.5 (0-1 noise) but I am having trouble getting the water to be level. I think a solution to this would be to do advanced rivers and have them follow the slope downhill instead of running down a hill to the north-east and ending up being lopsided.

EDIT:

Went back at caves with the idea of applying octaves to the 3D noise. It is better now, still not great. I'm too much of a lazy developer to implement some kind of advanced "worm" type thing. but I might anyway. Re: Its not actually that hard. The hard part is making the tunnel that the "worm" digs thicc.

fenomas commented 4 years ago

I'm afraid the big-picture answer here is: it's a really hard problem, and if you find a simple solution let me know. 😁

But things you're doing are all good approaches. Note that the thing you're doing, where you add together several different noise values, with different wavelengths and amplitudes, is essentially the same thing that the "octaves" parameter on the noise function. That is, one noise function with octaves=2 is equivalent to adding together two noise functions, where the same has half the wavelength and half the amplitude of the first.

One thing you might try is having biomes, i.e.:

var biomeNoise = noiseFunction1(x/500, z/500)
if (biomeNoise > 0) {
    // create mostly flat terrain
} else {
    // create mountainous terrain
}

and so on. Of course code like the above would have discontinuities at the border between biomes, so you might want smoothing there etc.

For rivers and tunnels, the only good approaches I know of are really slow (e.g. 3D noise). Maybe other folks have good ideas...

csf30816 commented 4 years ago

I might try 3D noise for tunnels. Your code is very similar to my new code except I interpolate them, the downside of that is you never really get the truly flat areas or the truly mountainous areas (only small hills and big hills) but it gets flat toward the ocean and overall looks nice.

csf30816 commented 4 years ago

I'm just gonna close this as it isn't really an issue or anything. I am still developing a realistic algorithm but this is unrelated to noa