Tuesday, April 22, 2014

Adventures in Procedural Terrain

Recently, I decided to do a bit of research on the procedural generation of terrain. As an avid Minecraft player, the worlds that could be generated always amazed me, and as a programmer I wondered how they could possibly be created. I didn't go into this project expecting to find the exact solution, but just get a feel for how it could be done in other games.

I chose two techniques for my terrain generation, a Fault Algorithm and a Circle Algorithm. These are fairly simple algorithms to implement with most of the work coming down to the tuning, but if you have no background rendering 3D terrain it could be a challenge. The first Algorithm I implemented was the fault Algorithm. This one works by creating straight lines across the area of your terrain and modifying the heights on each side. On one side the height is lowered and on the other it is raised. After many iterations you can achieve a fairly realistic terrain.


This image is a wire frame of one of my early versions of the Fault Algorithm. One downside of the fault Algorithm is that it creates very jagged, rough edges and peaks. This can be softened through a few ways. One, the fault can be a sin or cos wave instead of a straight edge. A second way is through terrain smoothing. The third way is a combination of the two. I decided to focus solely on terrain smoothing since it sounded the most interesting and could be applied to any and all terrain generation techniques. It Worked very well, almost too well, and I spent a while fine tuning my terrain to get it generating in the right position and with the right amount of edges.

This picture showcases the smoothing, also in wire frame mode. This was when I had my smoothing value and my fault values too low for my liking. However, it it a great contrast to the previous image, since the  fault values are the same range, but smoothing has made the edges and peaks much softer and more realistic. With smoothing, the closer the value is to one, the softer the terrain will be.


After smoothing was complete and I had finished tweaking my generation values, I decided it would look best with some textures. Up until this point I had been working mostly in wire frame mode to make sure everything was generating correctly and to see exactly what effects the different values had.

I chose a grass texture for my hills, got a nice blue coloration for the water, and my lighting is based on how far away the camera is from a part of the terrain. I thought it gave it a nice shadowed effect and gave the illusion that the world was bigger than it really is. When making and exploring my generated world, I realized how many I really liked and how awesome it would be if I could remake them, so I added seeding. The game is first loaded with a random seed, which can be saved to a text file. If you don't like the level, you can simply reload it. I included two reload options. One is a completely new seed, the other is loaded randomly from the file of saved seeds if it exists. That file can also be reloaded to include new seeds that may have been saved while going through fresh ones.


Four different worlds. Two saved, two randomly generated.

With seeding a success I turned to my last challenge, another generation algorithm. This was the Circle Algorithm. This one was a big harder to create and tune, but it is also a much gentler form of generation and doesn't require the same amount of terrain smoothing as the Fault Algorithm, if at all. It's well suited to to rolling hills compared to the Fault Algorithm's more jagged peaks that better fit a mountain range.
 On Left: Fault Algorithm. On Right: Circle Algorithm

 Both algorithms allow for a wide range of terrain generation and I learned a lot about both techniques as well as others. In the future I would like to expand this project to include Mid-point Displacement, Fractal Noise, and the Diamond-Square Algorithm.

No comments:

Post a Comment