Infinite terrain generation in chunks - need hints on handling chunk edges

Started by
33 comments, last by Kylotan 11 years, 1 month ago

That's quite interesting, and I can see that I might be able to simplify some aspects with a generalised selection function like that. However I don't get to have a smoothly varying base layer. The system has discrete per-chunk values for Grass, Hills, Mountains, etc.

I have already implemented a system that produces something much like in the screenshot, but achieved the smoothing across chunks by using bilinear interpolation when deciding what each position's topography weighting (ie. how much plains/hills/mountains) should be. This seems to be working well for me, and I'm quite relieved that it is equivalent in many ways to what you're describing as it shows I'm not doing something ridiculous.

Advertisement

Kylotan could you elaborate a bit on your bilinear interpolation using discrete per-chunk values? I'm now working on a terrain that will be finite, but generated by noise based on properties of "chunks" that will be generated from voronoi cells (look at http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/). Basically:

  • I generate random set of points and run voronoi algorithm on it to create voronoi cells and delaunay triangulation, as described in Amit's post
  • Diagram allows me to run all sorts of terrain-building algorithms, with manual control over some details like where I want cliffs, generating rivers thanks to interconnection of voronoi cells and so on. I call this large scale detail map.
  • I generate a pixel map out of that diagram (again, like Amit) to have a finite (say 4096x496 bitmap) array of values which will describe various data. It can contain base height, biome type, humidity, temperature - all factors that later affect small scale details like how the terrain is generated, what plants are there. I can sample this bitmap by coords of chunk and know exactly what conditions are in this chunk.
  • Now I had a plan to generate perlin noise for small detail, so final terrain. I wanted to base this on sampled value from array, but I realized that single value from that map will create chunky terrain - every chunk will end exactly on its boundaries, and terrain wont blend between. So i need to smooth the transitions somehow - I also thought about blending nearby factors and using that interpolated value as input into noise function, but I haven't yet figured out how to do it best. Reading from FLeBlanc's post, thats what he uses falloff for in first picture probably, so the borders are not sharp but slightly blended.

Where are we and when are we and who are we?
How many people in how many places at how many times?

I'm facing a similar problem in my current project.

the world is 2500 miles by 2500 miles. Its divided up into 5 by 5 mile map squares. A map square can use one of five different procedural heightmap formulas, depending on the elevation in the map square (ocean, flat, hill, mountains, or impassable mountains). Needless to say, heightmaps at map square edges don't line up. I spent a bit of time working on this, and just about have it solved. what i do is blend the values of the two heightmaps together over a distance of 100 d3d units from the edge. so at the edge, the height is 50% of one edge + 50% of the next edge. at 100 from the edge its 100% just the one heightmap. at 50 units from the edge, its 75% one + 25% the other, and so on. this yields beautiful seamless edges. until you get to the corners. I haven't implemented it yet, but it looks like the trick is to "zip up" (average together) all the seams running north south, then use those results to zip up the seams running east west. a method like this doesn't care about the procedure used to create the heightmaps, so you wouldn't have to worry about finding a noise function that works. you could use anything you wanted, then just "zip up" the seams.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Kylotan could you elaborate a bit on your bilinear interpolation using discrete per-chunk values?

Basically for any position in the world, I collect the 4 nearest per-chunk terrain types. This is done by subtracting half a chunk from the x and y directions, then checking the chunk values at (chunkX, chunkY), (chunkX+1, chunkY), (chunkX, chunkY+1), and (chunkX+1, chunkY+1).

Interpolating between them is a bit tricky because the terrain types are stored in an enumeration and obviously you can't just linearly interpolate along that. So I create a vector for each chunk that holds the chunk's weight for each of the terrain types. This will be 1 for the chunk's designated type and 0 for everything else, eg. (0,1,0) if I had 3 terrain types of Plains/Hills/Mountain and this was a hill.

Then I can interpolate between those, which will give me a value like (0.6, 0.4, 0) for an area just inside a Plains chunk, next to a Hills chunk. So I run the noise generator on this position for the Plains and for the Hills, then use the interpolated values to weight the sum, ie. PlainsNoise * 0.6 + HillsNoise * 0.4.

I had a plan to generate perlin noise for small detail, so final terrain. I wanted to base this on sampled value from array, but I realized that single value from that map will create chunky terrain - every chunk will end exactly on its boundaries, and terrain wont blend between.

In your situation I don't think you need to try and blend anything. If you're just generating fine detail and that detail is the same everywhere then you can just add the noise to whatever is already there and the values should be continuous as long as the underlying terrain is continuous and the noise is continuous also. To achieve that, you just need to ensure that the noise sampling wraps around. Most implementations of noise already do that. You'll have the problem I did, in that most implementations assume the resolution and dimensions of the world follow the patch of noise rather than vice versa, but it's simple to fix that once you get your head around it (which only took me about 20 forum posts above. ;) )

I spent a bit of time working on this, and just about have it solved. what i do is blend the values of the two heightmaps together over a distance of 100 d3d units from the edge. so at the edge, the height is 50% of one edge + 50% of the next edge. at 100 from the edge its 100% just the one heightmap. at 50 units from the edge, its 75% one + 25% the other, and so on. this yields beautiful seamless edges. until you get to the corners.

That's basically what I do, except I blend everywhere rather than just at edges. So in the middle of a section, that section contributes 100% of the value. As you move towards the edge of the section, that drops linearly to 50% of the value, plus 50% of the next section's value. I do this with linear interpolation for now, so I could change it to only blend nearer the edges by scaling the input values.

The problem with corners is solved by bilinearly interpolating across the 4 nearest sections. You can do it the way I described in my previous post, although there may be a simpler way to achieve the same effect - my attempt was shaped somewhat by the code I had already written.

This topic is closed to new replies.

Advertisement