# Paint by Iteration Count

*Task 3 of 5 · [Escape-Time Fractals](https://gpu.rocks/learn/escape-time-fractals-0de4764c.md) · GPU.js Learn*

Those counts *are* the picture. Make the kernel graphical and let every
thread color its own pixel: points that hit the 100 cap are inside the set — paint them
**black** — and everything else gets a shade from its count. That's the whole
recipe behind every Mandelbrot poster ever printed.

This module's palette maps `t = count / 100` to
`this.color(t, t·t, 0.5 + 0.5·t, 1)` — fast escapes glow deep blue, slow ones
burn toward white near the boundary, where all the detail hides.

## Goal

**Goal:** same escape-time loop, but `graphical: true` —
interior pixels black, escaped pixels shaded by three cosines a third of a turn
apart — a full colour wheel across `t = count / 100`.

## Requirements

- Keep the guarded 100-pass loop from the last task (already in place)
- If `count` reached 100, paint black: `this.color(0, 0, 0, 1)`
- Otherwise compute `t = count / 100`, then `a = 6.28318 * t`, and paint `this.color(0.5 + 0.5 * Math.cos(a), 0.5 + 0.5 * Math.cos(a + 2.0944), 0.5 + 0.5 * Math.cos(a + 4.18879), 1)`

## Hint 1 — two kinds of pixel

Branch on the cap: `if (count < 100) { …shade… } else { …black… }`.
Both branches must call `this.color()` — a graphical thread always paints
exactly one pixel.

## Hint 2 — the shade branch

```js
const t = count / 100;
const a = 6.28318 * t;
this.color(0.5 + 0.5 * Math.cos(a), 0.5 + 0.5 * Math.cos(a + 2.0944), 0.5 + 0.5 * Math.cos(a + 4.18879), 1);
```

## Same idea elsewhere

Mapping a scalar to a color is a *transfer function* — in scientific
visualization and medical imaging it's usually a 1D texture the fragment shader samples
by value; here the colormap is three inline formulas. Same trick, WebGPU to Metal.

## Starter code

```js
// The counts become the picture: one thread paints one pixel.
const gpu = new GPU({ mode });

const paint = gpu.createKernel(function (xMin, yMin, step) {
  const x = this.thread.x;
  const y = this.thread.y;
  const cr = xMin + x * step;
  const ci = yMin + y * step;
  let zr = 0;
  let zi = 0;
  let count = 0;
  for (let i = 0; i < 100; i++) {
    if (zr * zr + zi * zi < 4) {
      const zrNext = zr * zr - zi * zi + cr;
      zi = 2 * zr * zi + ci;
      zr = zrNext;
      count = count + 1;
    }
  }
  // TODO: paint this pixel.
  //   count reached 100  → inside the set → black
  //   escaped            → t = count / 100 → this.color(t, t*t, 0.5 + 0.5*t, 1)
  this.color(1, 0, 1, 1);
}, { output: [128, 128], graphical: true });

await paint(-2.2, -1.6, 3.2 / 128);
render(paint.canvas);
```

---

Interactive version: https://gpu.rocks/learn/escape-time-fractals-0de4764c/3

[Previous task](https://gpu.rocks/learn/escape-time-fractals-0de4764c/2.md) · [Next task](https://gpu.rocks/learn/escape-time-fractals-0de4764c/4.md)
