Task 4 of 6
Water alone does nothing to rock. What carves is load: fast, deep water can hold sediment, slow shallow water cannot, and the ground pays the difference. That is one number per cell:
capacity = carry * Math.sqrt(drop) * water
√drop is the size of the downhill gradient — the drop total was a sum of squares, so its square root is the slope — and multiplying by depth is the classic stream power product: steep × wet. Compare it with what the cell is already carrying and you get one signed exchange:
delta = load < capacity
? Math.min(pickUp * (capacity - load), maxCut) // cut
: -settle * (load - capacity) // fill
Then height − delta and sediment + delta. That
maxCut ceiling is the same kind of guard as move ≤ 1 next door:
cut a cell too deep in one step and its neighbours are suddenly steeper, so they cut
harder, and the feedback runs away.
Two kernels need the same delta and there is no way to hand a value from
one to the other — so both recompute it from the same snapshot. That is not waste. On a
GPU, arithmetic is close to free next to a round trip through memory; recomputing beats
communicating almost every time.
moveSediment adds it to the water's load, erode takes it out of
the rock. The routing half of moveSediment is already there.capacity = carry * Math.sqrt(drop[y][x]) * water[y][x] in both kernelsMath.min(pickUp * (capacity − load), maxCut); over-loaded water settles −settle * (load − capacity)erode returns height − delta; moveSediment returns the routed sediment + deltaconst capacity = this.constants.carry * Math.sqrt(drop[y][x]) * water[y][x];
const load = sediment[y][x];
let delta = -this.constants.settle * (load - capacity);
if (load < capacity) delta = Math.min(this.constants.pickUp * (capacity - load), this.constants.maxCut);
Paste the identical four lines into both kernels.
erode ends return height[y][x] - delta; and
moveSediment ends
return sediment[y][x] + this.constants.move * (taken - given) + delta;.
Rock loses exactly what the stream gains, which is what the conservation test checks.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.