Task 1 of 4

Paint with Coordinates

Set graphical: true and a kernel stops returning numbers — instead every thread paints exactly one pixel by calling this.color(r, g, b, a), channels 0–1. The output shape becomes the canvas: output: [128, 128] is a 128×128 picture, 16,384 threads, one per pixel.

A solid color is one line — and the starter already paints one. The interesting part is that each thread knows where it is: this.thread.x counts columns from the left, this.thread.y counts rows from the bottom (GL convention). Divide either by the canvas size and you get a smooth 0–1 ramp, ready to feed straight into a color channel.

every thread knows where it stands — divide by 128 and position becomes color
Goal: turn the flat gray into a two-axis gradient — red rising with x, green rising with y, blue fixed at 0.5.

Requirements

Hint 1 — where am I?

this.thread.x runs 0…127 here, so this.thread.x / 128 runs 0…0.992 — a ready-made red ramp. Same move with this.thread.y for green.

Hint 2 — the one-liner

The whole kernel body:

this.color(this.thread.x / 128, this.thread.y / 128, 0.5, 1);

Same idea elsewhere

Normalized pixel coordinates are the uv every shader language starts from: WebGPU and Metal fragment shaders derive them from the fragment position, and CUDA image kernels divide thread indices by the image width the same way. The famous red-green "uv debug gradient" is exactly this kernel.

All tasks in Pixels from Scratch

  1. Paint with Coordinates
  2. Checkerboard Logic
  3. Plot a Function
  4. Ripples: Think in Polar

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.