# Which Way Is Down

*Task 2 of 6 · [Hydraulic Erosion: Carving Terrain by Accumulation](https://gpu.rocks/learn/hydraulic-erosion-07165ca1.md) · GPU.js Learn*

Rain has landed. Where does it go? Downhill — but "downhill" on a grid needs
spelling out, and two details decide whether this simulation ever grows a river.

**One: the surface is rock plus water.** A puddle sitting in a hollow
raises the level the next drop has to climb; keep filling it and the puddle spills over
the rim by itself. Route on `height` alone and hollows become bottomless
traps. So every comparison below is between `height + water` values — call
that `H`.

**Two: square the drops.** This pass adds up
`d²` over the neighbours that are *below* this cell, and the next task
will hand each of them `d²/total` of the water. Weighting by the plain drop
smears the flow across every neighbour that is even slightly lower and no channel ever
forms; squaring makes a cell commit to the steep side. That one exponent is the
difference between a damp hillside and a river.

## Goal

**Goal:** complete `dropTotal` so each cell returns the sum
of `d²` over its four neighbours, counting only the ones the water can
actually fall to.

## Requirements

- Build the surface as `height[y][x] + water[y][x]`, not `height` alone
- For each neighbour, `d = here − there`; add `d * d` only when `d > 0`
- All four neighbours, with the same wrap-around the starter already set up

## Hint 1 — one neighbour at a time

The starter writes the left neighbour out in full. The other three are the
same two lines with different indexes:

```js
d = here - (height[y][xr] + water[y][xr]);
if (d > 0) total += d * d;
```

## Hint 2 — why the if matters

`d * d` is positive whether the neighbour is above or below, so the
square destroys the very information you are selecting on. The `if (d > 0)`
has to come first, or an uphill neighbour ends up "receiving" water.

## Same idea elsewhere

Deciding a flow direction per cell and then normalising by a per-cell total is
the multiple-flow-direction (MFD) router every terrain and hydrology package ships —
GRASS, TauDEM, Houdini's erosion nodes. The exponent this task fixes at 2 is a tuning
knob in all of them; 1.1 gives braided sheets, ∞ gives single-thread rivers.

## Starter code

```js
// How much "downhill" does each cell have to give away?
const gpu = new GPU({ mode });

const dropTotal = gpu.createKernel(function (height, water) {
  const x = this.thread.x;
  const y = this.thread.y;
  let xl = x - 1; if (xl < 0) xl = this.constants.size - 1;
  let xr = x + 1; if (xr > this.constants.size - 1) xr = 0;
  let yd = y - 1; if (yd < 0) yd = this.constants.size - 1;
  let yu = y + 1; if (yu > this.constants.size - 1) yu = 0;

  const here = height[y][x] + water[y][x];
  let total = 0;

  let d = here - (height[y][xl] + water[y][xl]);
  if (d > 0) total += d * d;
  // TODO: the other three neighbours — xr, yd, yu

  return total;
}, { output: [64, 64], constants: { size: 64 } });

const drop = await dropTotal(terrain, water);
console.log('steepest cell has a drop total of', Math.max(...drop.map(row => Math.max(...row))));
```

---

Interactive version: https://gpu.rocks/learn/hydraulic-erosion-07165ca1/2

[Previous task](https://gpu.rocks/learn/hydraulic-erosion-07165ca1/1.md) · [Next task](https://gpu.rocks/learn/hydraulic-erosion-07165ca1/3.md)
