TerrainGenerator (terrain_generator v0.3.1)

Copy Markdown View Source

Procedural terrain generation with fractal noise, hydraulic erosion and river extraction, backed by a Rust NIF.

The pipeline has four stages, each optional after the first:

  1. Base heightmap — fractal (fBm) OpenSimplex noise
  2. Island mask — radial falloff with noise-perturbed coastlines
  3. Hydraulic erosion — a droplet simulation that carves valleys and drainage networks
  4. Hydrology — flow routing over the eroded terrain; high-flow cells become rivers, filled depressions become lakes

Generation is fully deterministic for a given seed and option set, and runs on a dirty CPU scheduler so it never blocks the BEAM.

Examples

{:ok, terrain} = TerrainGenerator.generate(width: 512, height: 512, seed: 42)
TerrainGenerator.Terrain.height_at(terrain, 100, 100)
#=> 0.53

# render straight to a PNG file without keeping the data:
:ok = TerrainGenerator.render_png("map.png", seed: 42)

Options

All functions take the same option list; omitted keys use the defaults.

  • :width, :height — map size in cells (default 512 × 512), at most 4,294,967,295 cells in all
  • :seed — generation seed (default 0)
  • :sea_level — sea level in [0, 1) (default 0.08)
  • :octaves — noise octaves (default 8)
  • :frequency — number of large features across the map (default 2.5)
  • :lacunarity — frequency multiplier between octaves (default 2.0)
  • :persistence — amplitude multiplier between octaves (default 0.5)
  • :island — island diameter as a fraction of the shorter map dimension, true for the default size, or false to let terrain reach the borders (default 1.0)
  • :coast_noise — coastline perturbation strength; 0 gives a perfectly round island (default 1.0)
  • :erosion — true/false, or a droplet count to override the default of one droplet per cell (default true)
  • :rivers — approximate fraction of land covered by rivers, true for the default density, or false to disable rivers and lakes (default 0.01)
  • :river_min_upstream — absolute river threshold in cells of upstream catchment; overrides :rivers when set (default false)
  • :archipelago — number of islands to place instead of a single island, or false for one island (default false)
  • :islands_size, :islands_variation, :islands_spread, :islands_spacing — archipelago island size, per-island size variation, how far centres spread, and minimum centre spacing (defaults 0.35, 0.35, 0.85, 0.22)
  • :breach_basins — carve outlets from closed basins larger than this fraction of the map so they drain instead of becoming inland seas, or false (default false)

All options are validated; invalid values raise ArgumentError with a descriptive message before any native code runs.

Summary

Functions

Generates a terrain and returns {:ok, %TerrainGenerator.Terrain{}}.

Generates a terrain and writes it to path as a PNG file.

Types

option()

@type option() ::
  {:width, pos_integer()}
  | {:height, pos_integer()}
  | {:seed, non_neg_integer()}
  | {:sea_level, float()}
  | {:octaves, pos_integer()}
  | {:frequency, number()}
  | {:lacunarity, number()}
  | {:persistence, number()}
  | {:island, number() | boolean()}
  | {:coast_noise, number()}
  | {:archipelago, pos_integer() | false}
  | {:islands_size, number()}
  | {:islands_variation, number()}
  | {:islands_spread, number()}
  | {:islands_spacing, number()}
  | {:erosion, boolean() | pos_integer()}
  | {:breach_basins, number() | false}
  | {:rivers, number() | boolean()}
  | {:river_min_upstream, number() | false}

Functions

generate(opts \\ [])

@spec generate([option()]) :: {:ok, TerrainGenerator.Terrain.t()}

Generates a terrain and returns {:ok, %TerrainGenerator.Terrain{}}.

Raises ArgumentError on unknown options.

{:ok, terrain} = TerrainGenerator.generate(seed: 7, width: 256, height: 256)
terrain.width
#=> 256

render_png(path, opts \\ [], style \\ :shaded)

@spec render_png(Path.t(), [option()], :shaded | :greyscale) ::
  :ok | {:error, String.t()}

Generates a terrain and writes it to path as a PNG file.

style is :shaded (biome colours with hillshading, the default) or :greyscale (plain heightmap).

Returns :ok, or {:error, reason} if the file cannot be written.

:ok = TerrainGenerator.render_png("map.png", seed: 3)
:ok = TerrainGenerator.render_png("height.png", [seed: 3], :greyscale)