# Plot a Function

*Task 3 of 4 · [Pixels from Scratch](https://gpu.rocks/learn/pixels-from-scratch-d2869039.md) · GPU.js Learn*

How do you plot `y = f(x)` when no thread can draw a line? Flip the
question: every pixel decides *for itself* whether it lies on the curve. Thread
`(x, y)` evaluates the function at its own x, measures the vertical distance to
that height, and paints amber if the distance is under 2 pixels — background otherwise.

This per-pixel *"how far am I from the shape?"* question is one of the great
tricks of computer graphics. Today it draws a sine wave; the same idea, pushed further,
draws the fractals of **Escape-Time Fractals** and the ray-marched scenes of
**Ray-Marched Metaballs**.

## Figures

- **no thread draws the line — each pixel just answers: am i near it?**

## Goal

**Goal:** plot one full period of
`y = 64 + 40 · sin(2πx / 128)` as a thin amber curve on the dark background.

## Requirements

- Compute the curve height for this thread's x: `64 + 40 * Math.sin(x * 2 * Math.PI / 128)`
- Light the pixel when `Math.abs(this.thread.y - curveY) < 2`
- Keep the amber-on-dark colors from the starter

## Hint 1 — one line changes

The distance test and both colors are already written. Only
`curveY` is wrong: it's a constant, so you get a flat line instead of a
wave.

## Hint 2 — the curve

```js
const curveY = 64 + 40 * Math.sin(x * 2 * Math.PI / 128);
```

`Math.sin` and `Math.PI` both work inside kernels.

## Same idea elsewhere

Distance-to-shape rendering is how GPUs draw crisp text and vector art at any
zoom (signed distance fields), and it's the engine behind every Shadertoy graph you've
seen: a WGSL or Metal fragment shader evaluating `f(x)` per fragment, exactly
as here.

## Starter code

```js
// A plot is a per-pixel question: how far am I from the curve?
const gpu = new GPU({ mode });

const plot = gpu.createKernel(function () {
  const x = this.thread.x;
  // TODO: make this a real curve —
  //   y = 64 + 40 * Math.sin(x * 2 * Math.PI / 128)
  const curveY = 64;
  if (Math.abs(this.thread.y - curveY) < 2) {
    this.color(1, 0.85, 0.3, 1);      // on the curve — amber
  } else {
    this.color(0.06, 0.07, 0.1, 1);   // background — near black
  }
}, {
  output: [128, 128],
  graphical: true,
});

await plot();
render(plot.canvas);
```

---

Interactive version: https://gpu.rocks/learn/pixels-from-scratch-d2869039/3

[Previous task](https://gpu.rocks/learn/pixels-from-scratch-d2869039/2.md) · [Next task](https://gpu.rocks/learn/pixels-from-scratch-d2869039/4.md)
