LayerProcGen v0.1.0
Layer-based infinite procedural generation
|
A central purpose of the LayerProcGen framework is to support contextual generation while staying deterministic. Procedural operations can be performed across chunk boundaries, producing seamless results for context-based operations. For example:
Contextual generation means having the following two traits at once:
The trait of determinism is possible by dividing the generation into multiple layers and keeping a strict separation between the input and output of each layer, as detailed on the page about layer dependencies.
The trait of integrity is possible by supplying a chunk with sufficient context from lower layers, as detailed on the page about effect distance and padding.
The example below is meant to give a general idea of how layer-based contextual generation can be used, while other pages in the documentation go in more detail with how exactly it works.
It's possible to procedurally create natural-looking path through uneven terrain using a technique described in this external article. The technique is based on pathfinding, with a cost function that penalizes steepness. This can create path shapes such as switchbacks on steep terrain as an emergent behavior.
When using this technique for a world that's generated on the fly in chunks, we still want the generated paths to seamlessly cross chunk boundaries.
The following setup of layers with dependencies between each other is an example of how to do that.
The descriptions below reference various principles that will be introduced later on the internal layer levels page and the software patterns for layers page.
A LocationLayer with three internal layer levels generates positions representing locations, and determines which of those positions should be connected by paths:
A GeoGridLayer generates initial terrain height data based on noise and flattens the terrain around the locations.
The heights are only calculated in a coarse grid used for pathfinding in the CultivationLayer. Height data at full resolution is calculated later in the LandscapeLayer within a smaller area.
A CultivationLayer generates path splines between connected locations based on pathfinding.
Because all the input data comes from other layers, each chunk in the CultivationLayer can collect this data from a larger area than its own bounds. This means that paths can be planned even when they go partially outside of the chunk boundaries. Again the "owned within bounds" principle is used to determine which chunk calculates a path that goes across multiple chunks.
A LandscapeLayerA generates terrain chunks used for rendering and physics. Like the GeoGridLayer, it generates terrain height data based on noise (but at a higher resolution) and flattens it around the locations. It then flattens it around the paths too.
Each LandscapeLayerA chunk collects all locations that overlap its bounds from the LocationLayer 1, and all paths that overlaps its bounds from the CultivationLayer, both based on the "overlapping bounds" principle. This way the path deformation in adjacent terrain chunks matches seamlessly.