Start with fractals. Let nature do the rest.
Build ridges, dunes, craters and strata. Carve drainage with hydraulic and stream-power erosion; soften slopes with thermal weathering. Sculpt directly onto the terrain in a separate, editable node layer.

A world of possibilities. Yours to shape.
From the first ridge to the last ray of light.
Procedural terrain, natural erosion and rich environments — together in one native studio.
Free for noncommercial use · Source available
01 / The creative toolkit
Connect a few nodes. Follow the water. Let the landscape tell you where the materials belong. Every part stays yours to refine.
Build ridges, dunes, craters and strata. Carve drainage with hydraulic and stream-power erosion; soften slopes with thermal weathering. Sculpt directly onto the terrain in a separate, editable node layer.
Use erosion, altitude, slope and facing to place rock, scree, grass and snow. Blend up to six layers with height-aware transitions, then add field-driven roughness, bump and displacement.
Set the sun by location and time. Shape volumetric clouds, atmosphere and haze. Add water with depth color and shoreline foam, then scatter imported trees and rocks across point clouds.
Compose with physical camera controls and film looks. Preview in OpenGL, render through optional path tracers, export render passes, or capture a panorama and an animated fly-through.
02 / Inside TerraForge
See the landscape and the decisions behind it. Dock panels, open multiple node editors, arrange up to eight viewports and save the layout that fits your workflow.

Keep every decision editable. Bypass nodes, publish controls from reusable groups and undo changes across the scene.
Move between scales. Combine heightmaps with resolution-independent fields that compile to GPU shaders.
Bring your own world. Import heightmaps, SRTM tiles, uncompressed GeoTIFF DEMs and mesh assets.
03 / Made in TerraForge
Real terrain, real materials, real application captures. These landscapes are built from editable node graphs and photographed directly in the viewport.
04 / Your growing collection
Build up a personal collection of surfaces, terrain recipes and reusable nodes. Keep what works and carry it into your next scene.
Browse and download ambientCG CC0 PBR sets up to 8K: albedo, normal, roughness and ambient occlusion. Downloads are optional and cached locally.
Save material graphs with preview thumbnails. Load an independent copy into another scene and tune it without changing the original.
Explore layered materials ↗Group a network into a MetaNode, expose its key controls and save it under My nodes. Begin with terrain style presets or the included example projects.
Browse the node reference ↗Beyond the heightmap
Build spherical worlds with their own surface graphs. Combine procedural fields and eroded terrain, shape the horizon with a real radius, and explore the surface from close-up to orbit.
Point clouds and paths extend the scene: distribute mesh instances, carve a river route or send a camera along a spline.
Explore planets & infinite terrain ↗
05 / How it actually works
Nothing here is a black box. The solvers are the ones from the literature, the numbers are the ones the application reports, and the source is open to read.
The raster domain holds buffers — neighbour-aware, where erosion lives. The field domain evaluates a single point in 3D and is therefore resolution-independent. Rasterize and Sample bridge them, so a procedural field can be baked for erosion and an eroded heightfield read back by a field graph.
A field network is transpiled to GLSL and evaluated on the GPU, sharing its noise implementation with the planet renderer. CPU and GPU results are verified to agree within 1.3 × 10-5 across 20,480 samples.
Six independent solvers, each reporting what it did as reusable masks:
E = K·Am·Sn, explicit or implicit (Braun–Willett) with tectonic uplift and rock hardness.D8 flow accumulation measures how much water passes through each point. The wetness index — ln(a / tan b) — is the standard measure of where water collects: high in flat hollows fed from above, low on steep ground. Both are ordinary graph outputs, so a moss or vegetation mask sits where hydrology says it should.
ErosionLayers turns a simulation's side channels into a priority-ordered stack of masks — bedrock, scree, soil, grass, sediment, riverbed, snow — that always sum to one, and packs them into two splat textures.
The terrain is subdivided to what the camera needs, not to a fixed grid: 64×64 patches, each edge subdivided by that edge's length in pixels, from an effective 512 across — exactly the fixed grid it replaces, so it is never coarser — up to 2048 where the camera is close.
Levels are chosen per edge from its two endpoints, so adjacent patches always agree and no crack can open. Spacing is fractional, so a patch's level changes continuously rather than popping.
A layer's distribution answers where the material belongs — by altitude, steepness and which way the ground faces, each with a soft band. The criteria multiply, so a material sits where every condition holds: "rock, on the steep bits, below the snow line."
Because distribution reads the surface after displacement, slope and facing come from the shaded normal — so the material follows detail finer than the heightmap carrying it. Each layer carries its own albedo, normal and roughness, and decides whether its relief adds to the layer beneath (lichen on rock) or replaces it (snow flattening what it covers).
A planet is a pure parameter block — radius, relief, seed, sea level, snow line, colours, atmosphere — generated on the GPU every frame. No textures, no meshes, no caches, so a hundred planets cost the same memory as one.
Radius is a real length from a tenth of a millimetre to a billion kilometres. Single-precision positions resolve a globe to about a millionth of the tile width — 1 cm at the default 5 km tile. Sub-pixel planets are skipped, sphere meshes swap through three LODs with hysteresis so they never flicker, and surface shading always evaluates two octaves finer than the geometry.
The full graph vocabulary, from a noise primitive to a render pass. Every node reports its own timing and preview, and any node that turns terrain into terrain takes a mask input from the graph itself.
Read the node reference ↗.hgt tiles, uncompressed GeoTIFF DEMs, 8- and 16-bit PNG heightmaps05 / Under the surface
A native C++20 application with a local project workflow, deterministic terrain solvers and an inspectable source code repository.
OpenGL PBR shading, adaptive tessellation, per-vertex displacement, shadows, volumetric clouds and a live camera preview.
Send terrain, materials, cameras, lights and instances to Mitsuba 3, Blender Cycles or LuxCoreRender. These optional engines require a separate installation.
Import OBJ, STL, PLY and OFF. Inspect mesh issues, repair geometry, reduce triangle counts, split shells and export — with measured before-and-after diagnostics.
Use an optional local Ollama model to turn a description or reference image into editable scene actions. Automate the same workflow through Python, JSON actions or the MCP server.
The same actions the interface performs are available as JSON documents, a Python API and an MCP server — so an agent, a build script or a batch job drives the studio exactly as a person would.
Every scripted edit is a single undo step, and the graph can be read back as well as written: nodes(), links() and state() return what is actually in the scene, which is what makes automation debuggable rather than write-only.
from studio_api import Studio
s = Studio()
s.graph({"nodes": [
{"id": "n", "type": "Noise", "attrs": {"type": 1, "octaves": 9}},
{"id": "hy", "type": "Hydraulic", "attrs": {"particles": 1400}},
{"id": "sp", "type": "StreamPower", "attrs": {"method": 1, "uplift": 0.008}},
{"id": "el", "type": "ErosionLayers", "attrs": {"snowline": 0.86}},
{"id": "out","type": "TerrainOutput"},
], "links": [["n","output","hy","input"], ["hy","output","sp","input"],
["sp","output","el","input"], ["el","output","out","heightmap"]]})
s.set_resolution(2048)
s.set_sun(azimuth_deg=118, altitude_deg=12, intensity=5.2)
s.render(engine="mitsuba", width=2560, height=1440, samples=256)TerraForge is C++20 and links a deliberately small set of permissively licensed components. Every licence here is MIT, BSD, Apache-2.0, zlib, MPL-2.0, CC0 or public domain: no GPL or LGPL code is present anywhere, because a copyleft licence must grant downstream commercial freedom that a noncommercial licence cannot.
EIGEN_MPL2_ONLYManifold and QuadriFlow are optional: the application builds and runs without either, reporting that stage as unavailable. The offline renderers — Mitsuba 3, Blender Cycles and LuxCoreRender — are separate installations, not bundled code. Material sets downloaded from ambientCG are CC0 and are fetched at your request, never redistributed.
Read third-party notices ↗Built by Geekatplay Studio
TerraForge is created by Vladimir Chopine, co-founder of Geekatplay Studio. It brings the procedural landscape workflow behind years of environment-art teaching into a connected native application.
The inspiration comes from the classic landscape studios artists grew up with: the joy of shaping terrain, experimenting with light and finding a world inside a few connected ideas.
Your next landscape starts here
Free for personal, hobby and educational use.
Commercial work requires a separate license.
Windows · macOS · Linux — see the install guide for platform setup and available builds.
A supported 64-bit desktop system and OpenGL 4.3 graphics, or OpenGL 4.1 on macOS. Building from source needs CMake 3.20+, Ninja and a C++20 compiler. Python and external renderers are optional additions; consult the install guide for your platform.
A commercial license is required for paid production and business use. See the commercial licensing information. Personal and educational use is covered by the PolyForm Noncommercial license.
The terrain studio works locally. AI assistance is optional and uses a separately installed Ollama model. Material downloads need an internet connection; scripts and third-party integrations may have their own requirements.
Keep in touch
We’d love to hear what you’re making.
For reproducible bugs and feature requests, open an issue on GitHub ↗