TLDR: For GSoC, I propose to implement a world generator which moves most of the generation from the global world generator to the individual biomes (I've done a prototype of it here). Then I'll use this to implement a number of biomes, to provide an Earth-like world generator with distinct regions of terrain.
Hey everyone,
I've been working away at my GSoC proposal: I'm planning a project based on Noise-based generation of distinguishable terrain features (#943). So far I've figured out a rough plan for the project, and have implemented a prototype world generator which shows some of the concepts I am thinking about. I would like to get some feedback on the idea, both from the perspective of a GSoC project (e.g. whether the scope is right), and from the perspective of it as a game feature.
The prototype is on my GitHub; it is explained below, and I tried to document most of the code to show what it is doing.
The project would have two main components: first implementing an updated world generation system, and then using that to build a world generator. The world generator would provide many different biomes to give a world that feels like it could exist in real life (though on a smaller scale, and slightly more blocky).
Updated world generator
The updated world generator is based on the principle that the biomes should control what is generated in them, rather than them being set based on the existing world that has been generated. It would still use a global generator to calculate a general heightmap, which will determine the approximate location of oceans, mountains, and the stuff in between, but then the biomes take over and can modify the world however they like.
This means that, for example, plains and deserts can be made to be roughly flat, hills can be a bit more bumpy, and mountains can be as big as they like.
For anyone who is interested in the class-level architecture, here is the basic plan (though it is still very flexible at this stage):
- The WorldGenerator acts as normal, with FacetProviders and Rasterizers applied
- The global heightmap is calculated with a SurfaceHeightFacet as usual
- A BiomeFacet is added, which calculates the most appropriate Biome for each column
- Each Biome then calculates an updated height for each column, and updates the global heightmap with this information
- At the rasterisation stage, the Biome rasterises the world one column at a time (rather than one chunk at a time, so that biomes can have smooth borders, rather than being aligned to chunk borders)*
- The rasteriser also tells the chunk which biome each block is in, so the rest of the game can use this information
*Alternatively, the system could just generate dummy chunks where only the blocks within the biome are affected, which are then copied into the main chunks. This would allow the Biome to always rasterise as if it was doing a whole chunk at a time, so the rasterisation process would be very similar to the current process.
This is quite a flexible system, as it still uses the current facet/rasterizer system, so should be compatible with other modules that add world generation. It also can be extended, such as to add another layer of biomes by adding another BiomeFacetProvider, which controls the underground biomes. These underground biomes control all of the generation under the surface, such as generating different rock types and affecting generation of ore, caves, and other underground features. This would allow surface biomes to only focus on the surface, and then underground biomes can be added completely independently (or in a way which is linked to the surface biomes, such as certain rock types being more common under mountains).
This whole system still follows the modular philosophy of the game, allowing any part to be changed or added to. One such extension could be an implementation of Advanced and dynamic geology based on plate tectonics (#141). This could be implemented by using the tectonic plate-based heightmap as the base heightmap, adding surface biomes as usual, and then adding multiple layers of underground biomes to control underground generation.
One of the main issues to be solved is making the biomes interact smoothly at the boundries. There are several ways this could be done, such as having a step after the biome heightmap calculations that interpolates at the edges of biomes, or allowing the biomes themselves to know where the edges are, and make sure they are smooth at those points. There are advantages and disadvantages to each method, so more research and testing would need to be done before a decicion is made.
Another thing to work out is how the biome locations will be determined. This will probably involve generating a few more layers of data such as temperature, humidity, rainfall, etc., which can also be affected by the heightmap (such as high-rainfall areas near oceans). From there, the BiomeFacet can work out the most suitable biome for each column, and the continuous nature of the data should mostly keep the biomes in large clusters (though some other checks, such as making sure each biome area is a suitable minimum size, can be done).
My prototype implements most of the basics, and I quickly made 2 biomes to show it in action (mountains and plains). They are currently only generated on either side of the x=0 line to show the side-by-side generation provided by the biomes, but it shows how the BiomeFacet controls placement of biomes, and that most of the world generation is handled by the biomes themselves. The attached screenshot shows the mountains on the right, and the plains on the left.
Earth-like world
The second part of this project would be to use the generator detailed above to implement biomes that represent some of the most iconic terrains on Earth. The basic biomes I would implement would be grasslands/plains, ocean, desert, mountain, and hills. As all of the world generation code is stored in the biome classes, inheritance can be utilised to great extent. The heightmap generators can be reduced down to oceanic, flat, and mountainous (with adjustable parameters, for example to control the height variation), with each of the biomes extending the appropriate heightmap generator and rasterising the chunk as appropriate (some of them could even share a parent for this too, as grasslands and hills would look similar, just with a different heightmap generator).
Forests and bodies of water (rivers/lakes) can be implemented as biomes that inherit from an appropriate parent (such as allowing for different types of forest/lake on plains to the types found in the mountains), or just an extra decorator on top of the biome system. Forests would mainly require adding trees and vegetation to the existing landscape. Lakes and rivers are more tricky because they modify the landscape, and have stricter requirements on where they can occur (such as a lake needing a big flat area), so they would require more research, planning, and testing.
Another interesting challenge would be to generate some terrain with overlaps and overhangs, which are not created by the standard heightmap-based approaches. Fortunately, this system makes it easy to use a standard heightmap-based approach for most of the terrain, and add only modify biomes that need it, such as mountains.
Thanks for reading; please leave any feedback below! At this stage I'm still open to big changes, but I think this is a fairly solid foundation for the project.
Hey everyone,
I've been working away at my GSoC proposal: I'm planning a project based on Noise-based generation of distinguishable terrain features (#943). So far I've figured out a rough plan for the project, and have implemented a prototype world generator which shows some of the concepts I am thinking about. I would like to get some feedback on the idea, both from the perspective of a GSoC project (e.g. whether the scope is right), and from the perspective of it as a game feature.
The prototype is on my GitHub; it is explained below, and I tried to document most of the code to show what it is doing.
The project would have two main components: first implementing an updated world generation system, and then using that to build a world generator. The world generator would provide many different biomes to give a world that feels like it could exist in real life (though on a smaller scale, and slightly more blocky).
Updated world generator
The updated world generator is based on the principle that the biomes should control what is generated in them, rather than them being set based on the existing world that has been generated. It would still use a global generator to calculate a general heightmap, which will determine the approximate location of oceans, mountains, and the stuff in between, but then the biomes take over and can modify the world however they like.
This means that, for example, plains and deserts can be made to be roughly flat, hills can be a bit more bumpy, and mountains can be as big as they like.
For anyone who is interested in the class-level architecture, here is the basic plan (though it is still very flexible at this stage):
- The WorldGenerator acts as normal, with FacetProviders and Rasterizers applied
- The global heightmap is calculated with a SurfaceHeightFacet as usual
- A BiomeFacet is added, which calculates the most appropriate Biome for each column
- Each Biome then calculates an updated height for each column, and updates the global heightmap with this information
- At the rasterisation stage, the Biome rasterises the world one column at a time (rather than one chunk at a time, so that biomes can have smooth borders, rather than being aligned to chunk borders)*
- The rasteriser also tells the chunk which biome each block is in, so the rest of the game can use this information
*Alternatively, the system could just generate dummy chunks where only the blocks within the biome are affected, which are then copied into the main chunks. This would allow the Biome to always rasterise as if it was doing a whole chunk at a time, so the rasterisation process would be very similar to the current process.
This is quite a flexible system, as it still uses the current facet/rasterizer system, so should be compatible with other modules that add world generation. It also can be extended, such as to add another layer of biomes by adding another BiomeFacetProvider, which controls the underground biomes. These underground biomes control all of the generation under the surface, such as generating different rock types and affecting generation of ore, caves, and other underground features. This would allow surface biomes to only focus on the surface, and then underground biomes can be added completely independently (or in a way which is linked to the surface biomes, such as certain rock types being more common under mountains).
This whole system still follows the modular philosophy of the game, allowing any part to be changed or added to. One such extension could be an implementation of Advanced and dynamic geology based on plate tectonics (#141). This could be implemented by using the tectonic plate-based heightmap as the base heightmap, adding surface biomes as usual, and then adding multiple layers of underground biomes to control underground generation.
One of the main issues to be solved is making the biomes interact smoothly at the boundries. There are several ways this could be done, such as having a step after the biome heightmap calculations that interpolates at the edges of biomes, or allowing the biomes themselves to know where the edges are, and make sure they are smooth at those points. There are advantages and disadvantages to each method, so more research and testing would need to be done before a decicion is made.
Another thing to work out is how the biome locations will be determined. This will probably involve generating a few more layers of data such as temperature, humidity, rainfall, etc., which can also be affected by the heightmap (such as high-rainfall areas near oceans). From there, the BiomeFacet can work out the most suitable biome for each column, and the continuous nature of the data should mostly keep the biomes in large clusters (though some other checks, such as making sure each biome area is a suitable minimum size, can be done).
My prototype implements most of the basics, and I quickly made 2 biomes to show it in action (mountains and plains). They are currently only generated on either side of the x=0 line to show the side-by-side generation provided by the biomes, but it shows how the BiomeFacet controls placement of biomes, and that most of the world generation is handled by the biomes themselves. The attached screenshot shows the mountains on the right, and the plains on the left.
Earth-like world
The second part of this project would be to use the generator detailed above to implement biomes that represent some of the most iconic terrains on Earth. The basic biomes I would implement would be grasslands/plains, ocean, desert, mountain, and hills. As all of the world generation code is stored in the biome classes, inheritance can be utilised to great extent. The heightmap generators can be reduced down to oceanic, flat, and mountainous (with adjustable parameters, for example to control the height variation), with each of the biomes extending the appropriate heightmap generator and rasterising the chunk as appropriate (some of them could even share a parent for this too, as grasslands and hills would look similar, just with a different heightmap generator).
Forests and bodies of water (rivers/lakes) can be implemented as biomes that inherit from an appropriate parent (such as allowing for different types of forest/lake on plains to the types found in the mountains), or just an extra decorator on top of the biome system. Forests would mainly require adding trees and vegetation to the existing landscape. Lakes and rivers are more tricky because they modify the landscape, and have stricter requirements on where they can occur (such as a lake needing a big flat area), so they would require more research, planning, and testing.
Another interesting challenge would be to generate some terrain with overlaps and overhangs, which are not created by the standard heightmap-based approaches. Fortunately, this system makes it easy to use a standard heightmap-based approach for most of the terrain, and add only modify biomes that need it, such as mountains.
Thanks for reading; please leave any feedback below! At this stage I'm still open to big changes, but I think this is a fairly solid foundation for the project.
Last edited: