Expand description
Procedural terrain generation with fractal noise, hydraulic erosion and river extraction.
The pipeline runs in five stages; everything after the first is optional:
- Base heightmap — fractal (fBm) OpenSimplex noise via the
noisecrate. - Land mask — either a single radial island
(
IslandParams) or an archipelago of several (ArchipelagoParams), both with noise-perturbed coastlines. - Hydraulic erosion — a particle/droplet simulation that carves valleys and drainage networks into the terrain.
- Basin breaching (opt-in) — cuts outlets through the rims of
oversized closed basins so they drain instead of becoming inland
seas. See
TerrainBuilder::breach_basins. - Hydrology — depressions are filled (priority-flood), then D8
flow routing; cells with enough upstream catchment become rivers,
filled depressions become lakes, and border-connected sea becomes
the
oceanmask.
§Quick start
use terrain_generator::{RenderStyle, Terrain};
let terrain = Terrain::builder()
.size(512, 512)
.seed(42)
.generate();
terrain.save_png("map.png", RenderStyle::Shaded).unwrap();
// raw data access for games/simulations:
let h = terrain.heightmap[(100, 100)]; // elevation in [0, 1]
let wet = terrain.flow_at(100, 100); // moisture proxy in [0, 1]
let catchment = terrain.flow_accumulation_at(100, 100); // cells upstream
let river = terrain.is_river(100, 100);§What this crate does and does not decide
The output is a set of raw, independent layers: elevation, flow accumulation, and river/lake/ocean masks. It deliberately stops short of gameplay or domain semantics — there is no “drinkable”, no biome enum, no navigability. Anything that is a judgement call is either a parameter (how dense are rivers? how big may a lake be?) or derivable from the raw layers, so a consumer can substitute its own rules.
Consumers that bring their own hydrology should use
TerrainBuilder::no_rivers, which skips flow routing entirely and
leaves Terrain::heightmap as the single source of truth.
§Data model
All per-cell outputs are Grids: dense row-major buffers indexed as
grid[(x, y)], with the flat storage available via Grid::as_slice
for zero-copy hand-off to FFI, GPUs or file formats.
§Determinism
The same seed and parameters produce the same terrain, run after run. Ordering that could otherwise vary — the flow-routing sort and both priority queues — is broken by cell index, so no result depends on sort or heap internals.
Two caveats worth knowing before you persist a world as a seed:
- Pin the version. The base noise comes from the
noisecrate, and tuning inside this crate also changes output. If you regenerate terrain from a stored seed, depend on an exact tag or revision and commit yourCargo.lock; treat any change to the generated output as a breaking change on your side. flowuses a transcendental.Terrain::flowis log-normalised withf32::ln, whose last-bit rounding is not guaranteed identical across platforms and libm implementations. Every other layer — heightmap,flow_accumulation, rivers, lakes, ocean — is computed with IEEE-exact operations only (+ - * /,sqrt, comparisons), so those are reproducible bit-for-bit everywhere. If you need cross-platform exactness for moisture, derive it fromflow_accumulationyourself.
§Cargo features
png(default) — PNG output (Terrain::save_png,Terrain::save_layer_png); pulls in thepngcrate.Terrain::to_rgbworks without it.cli(default) — theterrain-generatorcommand-line binary; pulls inclapand impliespng. Library consumers should usedefault-features = false, which leavesnoiseas the only dependency.
Structs§
- Archipelago
Params - Archipelago mask parameters: several radial islands instead of one.
- Breach
Params - Basin breaching parameters. See
TerrainBuilder::breach_basinsfor what the stage does. - Erosion
Params - Hydraulic erosion parameters. The defaults are good for maps between
256² and 2048²; usually only
dropletsneeds tuning. - Grid
- A
width × heightgrid ofT, stored row-major. - Island
Params - Radial island mask parameters.
- Noise
Params - Fractal (fBm) noise parameters for the base heightmap.
- Param
Error - An invalid generation parameter.
- River
Params - River extraction parameters.
- Terrain
- A generated terrain: elevation plus the hydrology layers derived from it.
- Terrain
Builder - Builder for
Terrain. Obtained viaTerrain::builder. - Unknown
Layer - Returned when a string does not name a
Layer.
Enums§
- Layer
- A single output layer of a
Terrain, for writing one file per layer. - Render
Error - Errors that can occur while writing an image.
- Render
Style - How a
Terrainis turned into an image. - River
Threshold - How the river network is cut out of the flow accumulation map.
Constants§
- MAX_
CELLS - The most cells a map can have:
width * heightmust not exceed it.
Functions§
- ocean_
mask - Marks cells that belong to the ocean: at or below
sea_leveland reachable from the map border through other such cells.