Hydraulic Erosion
Pure noise terrain looks like lumpy oatmeal. Real mountains have ridgelines, gullies, and valleys. They earned them: for a few million years, every raindrop that fell on them picked up a little dirt and dragged it downhill. We can fake the few million years in about fifteen seconds.
The demo on this page is a real simulation running in your browser, not a video. Press Run demo, then come back. Every slider in this article pokes the live terrain.
Start with noise
Every terrain here starts as a heightmap: a grid of numbers between 0 and 1, where 0 means valley floor and 1 means summit. The renderer pushes each point of the mesh up by its number.
To fill the grid we use fractal noise. Noise in this sense means smooth random bumps, not TV static. We stack several layers of it. The first layer makes a few big hills. Each layer after that adds smaller bumps on top, so the big shapes pick up fine detail. Those layers are the "octaves" below. Try the sliders. The terrain rebuilds as you drag:
One trick worth knowing: raise every height to a power. With an exponent above 1, the middle elevations sink and only the peaks stay tall. With an exponent below 1, everything puffs up into rolling plateaus.
Notice what is missing at every setting: drainage. Each point of noise is computed on its own, with no knowledge of its neighbors, so nothing connects the bumps into watersheds. That is the job of the rain.
A single raindrop
The algorithm is gloriously simple. A droplet is just five
numbers: position, direction,
velocity, water, and
sediment. Drop it somewhere random and loop:
for life in lifetime: # ~30 steps
grad = gradient_at(pos) # bilinear, sub-texel
dir = dir * inertia - grad * (1 - inertia)
pos += normalize(dir) # move one texel
dh = height(pos) - height(old_pos)
# ... erode or deposit (next section) ...
vel = sqrt(max(0, vel² - dh * gravity))
water *= 1 - evaporation
Press Step under the demo a few times to follow one droplet. A line traces its path, and the readout shows its water, speed, and sediment after every move. The trail starts blue while the droplet runs clean, then turns rust orange as it picks up dirt.
Inertia is the personality knob. At 0, the droplet always rolls straight downhill and zigzags into the first pit it finds. Near 1, it plows straight ahead and ignores the terrain. A small amount, around 0.05, lets it swing wide around bends the way real water does:
Carrying capacity
The heart of the model is one line. It decides how much sediment a droplet can hold:
capacity = max(-dh, min_slope) · velocity · water · capacity_factor
Fast water on a steep slope can carry a lot. Slow water on flat ground can barely carry anything. After every move, the droplet compares its load against this limit:
- Room to spare? It erodes the ground under it. The dig is capped at the height it just descended, because digging deeper would stamp a pit. It is also spread over a soft brush radius, so channels become valleys instead of one-pixel scars.
- Overloaded, or moving uphill? It drops sediment. This one rule builds floodplains and river deltas at valley mouths for free.
All of these knobs feed the same loop. Early droplets carve a channel, the channel funnels later droplets, and those droplets deepen it. That feedback is why the result looks organized rather than sandblasted.
The full storm
Now press Play and rain tens of thousands of droplets. The simulation spends a few milliseconds per frame and then yields, so the page stays smooth while the terrain erodes as fast as your machine allows. Toggle the erosion tint to see the bookkeeping: red where ground was removed, blue where it was laid down.
Things to try:
- Crank inertia to 0.9 before the storm. You get long straight gouges, like glacier scars.
- Set erode rate high and deposit rate low for badlands. Reverse them for soft, silted hills.
- Set valley sharpness low to make a plateau world, then watch the rain invent a branching river network anyway.
Notes & further reading
- Hans Theobald Beyer, Implementation of a method for hydraulic erosion, the bachelor's thesis this droplet model comes from.
- Sebastian Lague, Coding Adventure: Hydraulic Erosion, the video that made this model famous, with a compute-shader implementation.
- Amit Patel, Terrain from noise, the source of the height redistribution trick and the spiritual ancestor of this whole site.
- Nick McDonald, Procedural Hydrology, a natural next step: particle erosion extended with real stream and pool dynamics.
This demo simulates individual droplets, which the literature calls the Lagrangian approach. The other family is pipe-model erosion, where water sits in every cell and flows between neighbors (Eulerian). That one maps beautifully onto GPU shaders and is a likely future experiment here.