Yet another procedural terrain project :)

Hello,

So, like many others here, I’m also working on a procedural terrain system. Just thought I’d show how it’s going so far, and hopefully get a few helpful pointers from everyone while I’m at it :wink:

My attempt has so far been targeted at making the terrain infinite, reproduceable (no randoms) and light-weight… The system creates a N by N grid of tiles around the reference transform (usually a camera), and shifts the tiles around as needed to keep the grid centered…

The tiles are just planes (for now), and deform themselves according to a heightmap.

The relief map is generated by a series of noise functions from libNoise (and the very convenient port to unity I found here on the forums)… The big thing here is that each vertex get’s it’s noise coordinates from it’s global position, so the amount of polygons and the tile’s position or size is irrelevant to the system… it will always conform to the heightmap below.

Each tile also calculates an RGBA texture map to be used as a blending mask for the terrain shader I found on the Unify Wiki… one of the channels is based on the vertex normal’s alignment to the up axis, so it blends in rock textures for steep terrain. The others are all based on height (so far), and switch the textures between sand, grass, and, uh… another kind of grass :wink:

There are also LOD meshes, and the system swaps them out according to distance, in the example below I’m using a 20x20 tile near the player, then a 10x10 for medium distances, and finally a 4x4.

Also, all the updating, moving and refreshing cycles are done in coroutines, so it never lags the game (although it’s kind of a tradeoff, since updating also takes a while longer to complete). The system keeps track of how much time it has spent on a given loop, and if it exceeds the predefined threshold, it yields until the next update cycle.

Performance wise I can say it’s going relatively well… It draws the entire 19x19 tile setup in 0.2 seconds, and everything else is done in the coroutines, so they don’t really weigh much at all… My dev rig isn’t exactly an average spec machine, so it’s possible this will perform worse in lower-spec computers… but I expect it to have a reasonable performace in any case.

There are a couple of issues still, though…

The tiles need to average their normals with their neighbours, to prevent hard edges where there shouldn’t be any… The thing is that, since the tiles shift around to remain centered, finding the neighbours isn’t so trivial as adding one to the index… I’ll probably have to maintain a reference map so I can retrieve the neighbours…

Also, I have to find a way to generate a spherical world from these tiles… that’s probably gonna require some major restructuring, and I’m scared just to think of it :shock:

Anyways, let me know what you think :slight_smile:

Cheers

EDIT: Fixed image link… hopefully :stuck_out_tongue:

The image link is broken :frowning:

Looking good so far!

Hi,

Looks good!, Ive done a few of these terrain generators so I might have some tips that could help.
Computing normals… if you are looking up heights by worldx,z co ord when making the meshes you can ofc also use these to generate your noermal (ie get th eneigbour height from the heightmap, not the adjacnet polygon). Because your tiles are different sizes due to your LOD you might get probmems where a normal provides lighting across 1 tiles and then when swopped to 2 individual tiles (at your greater detail) another normal is introduced midway. This can cause visual popping.
Another method is to calculate a lightmap by shadowcasting and lightmapping the terrain to an internal texture, then just slapping that in alongside the rgba mix in the shader more here. That way it doesnt matter what resolution or LOD your mesh actually is (this does make realtime lighting a little less effective, but loads of game terrains have baked in lighting )

As for our LOD, id be tempted to try and use a brute force mesh and see how much of a performance hit you take (as this will also solve your normals issue and your potential edge cracks). You could also use the LOD just for simplifying the mesh (low detail areas have less polys) but not have it adjust in realtime, this way any normals taken fro the heightmap wont change and pop.

If you are going to go with a sphere then some of the terrain will be over the horizon anyway! In this case you can chunk the mesh into smaller blocks and cull those when they go under the horizon.
Again, some info here on making spheres. Id probably advise this cubesphere approach since you are already generating flat square maps.

Keep up the good work, procedural terrains are fun!

Hi Tom,

Thanks for the tips!! I’ve read your posts and blogs and they were a big part of my research!

The idea of calculating the normals off the heightmap is a very good one!! it doesn’t rely on automatic calculations, and has the best chance of working!

Also, since the heightmap is completely abstract (i.e. it doesn’t generate a texture of limited resolution), I can get good normals even from lower-res meshes, since they can look up neighbours at arbitrary distances, not necessarily at the next vertex position.

I’m doing this mostly for learning, and as a stepping stone for bigger projects, but this might probably end up in a game… Next, I want to try a Marching Cubes approach and a voxel map… big step… but we’ll see how that goes :slight_smile:

Cheers