A User-Controlled Pipeline for Organic Procedural Terrain Generation
Godot 4.4 is currently used Version
We introduce a comprehensive, user-driven pipeline for generating rich, organic terrains. We employ FastNoiseLite to produce a base height map, which is then refined by a cascade of cellular automata filters that expand flat regions, patch & eliminate outliers, and selectively shrink water bodies. Blocky posterization adapts terrains to isometric grids & flow accumulation yields road networks. And a Poisson disk sampler places small objects, such as plant life. We demonstrate the ability to influence random noise into terrain morphology.
- Setup a C++ Environment
- Possible Setup for VS Code : https://code.visualstudio.com/docs/cpp/config-mingw
Ensure that C++ can run :
gcc --version
g++ --version
gdb --version
-
User Control Inputs
- Seeding :
int32_t seed
- Frequency :
float noiseFrequency
- Allow user to define frequency: Lower-frequency noise gives broad zones; higher-frequency adds detail.
- Elevation Threshold :
int elevationMax
- Allow user to determine the number of elevations created in the final solution
- Open Area Minimum :
int openAreaMin
- Allow users to determine the minimum number of open areas for large structure placement
- Water Reduction Value :
waterRemoval
- Water reduction percentage of 0 to 100
- Ignore values of 10 or lower
- Seeding :
-
Produce Random Noise
- Using FastNoiseLite
- Allow user to define frequency: Lower-frequency noise gives broad zones; higher-frequency adds detail.
-
Generate Height Map
- Take the Filtered Noise, Normalize and Scale to (0,
elevationMax
) - Assume 0 values are base elevation of Water
- Take the Filtered Noise, Normalize and Scale to (0,
-
Noise Processing
- Noise Conversion (into square patterns)
- Send through filters to create blocky patterns useable for isometric 3d grids
- Use Elevation Threshold to determine values between 0 to Elevation Threshold
- Reduce Resolution by sampling one pixel per block
- Posterize
- Upscale back to Original Size
- Noise Conversion (into square patterns)
-
Cellular Automata (CA) Filter on Noise
- CA Filter A : Expanding Zones
- Find X number of
openAreaMin
, find flat zones that are 3x3 cells of flat area - Smooth the noise by expanding the flat areas
- Create a CA rule that defines flattened areas and expand them
- Scan to find new flat zones
- Find X number of
- CA Filter B : Patching / Removing Outliers
- Even out zero elevation && any cells that are islands
- If a cell is zero and has many zero neighbors, it stays zero. Also true for values of 1, 2, 3, etc. If a cell is x and has many x neighbors it stays x.
- If a cell is non-zero/x but surrounded by zeros/x, it becomes zero/x (growth).
- If a zero/x is isolated, it becomes non-zero/x+1 (pruning).
- CA Filter C : Water Reduction
- Use Flood Fill to find 0 regions
- Reduce its size by a percentage and flipping the 0s to 1s
- Have a variable to determine percentage by user (0-100)
- Skip this filter if user defined percentage is less than 10%
- Bias reduction on edges to simulate evaporation
- CA Filter A : Expanding Zones
-
Hydrology Path Generation
- Each grid cell in the elevation map is a node in a graph
- Downhill Flow
- Assign movement cost to each path, using the raw noise for the height map to determine costs by slope descent
- Steeper slopes are higher cost
- For each node point to the lowest cost neighbor
- Assign movement cost to each path, using the raw noise for the height map to determine costs by slope descent
- Flow Accumulation : Count the neighbors that flow into our tile as a flow value
- Use the high flow values to create major roads && the small values to create minor roads
- Done by marking walkable cells that can’t be placed with objects
- Use the high flow values to create major roads && the small values to create minor roads
-
Tile Placement
- Using a Dual-Grid System
- Determine the correct tile type for each cell in the grid
- Set the Grid map cells using Godot's Grid map system
- Using a Dual-Grid System
-
Open Area Finder / Large Structure Locations
- Find areas that have flat ground tiles of 3x3 cells
- Elevation buffer, ensure structures aren’t placed against cliffs and ramps
- Store the center cell into a list of available locations
-
Poisson Object Placement
-
Create a copy of the finalized grid (tileMap) and increase its size by splitting cells into 4 pieces
-
New grid contains data about each cell's (4x4 area) place-ability
-
Use the data from the previous steps to know cells that can’t have objects placed on them
vector<vector<bool>> walkableMap
size gridx2- This is Hydrology Pathing which determines non-placeable cells
- Find non-walkable area's as object placeable area's
vector<vector<TileType>> tileMap
size grid- Use Cliffs & Ramp's Placement as object non-placeable area's
-
-
Generate a list of placeable points on the grid using poisson disk sampling
- If a cell is a valid place for object placement, turn all four cells in the new grid to true/valid
-
Any and all Contributions are subject to the CLA.md