GPU.js Graphical Mode Thread to Pixel Mapping

In GPU.js, enabling graphical mode transforms a kernel into a hardware-accelerated pixel shader that renders directly to an HTML5 canvas. Thread indices determine exactly which pixel on the screen is being processed by mapping the kernel's execution grid directly to the canvas's width and height. Because GPU.js relies on WebGL under the hood, this mapping follows a Cartesian coordinate system where thread index (0, 0) corresponds to the bottom-left corner of the canvas rather than the top-left standard seen in conventional 2D web graphics.

The Coordinate Grid Setup

When you configure a kernel with { graphical: true }, you define its output dimensions using setOutput([width, height]). GPU.js allocates a grid of threads matching these exact dimensions:

Each individual thread runs concurrently for a single pixel location defined by (this.thread.x, this.thread.y).

The WebGL Origin (Bottom-Left Orientation)

The most critical distinction when mapping thread indices to canvas pixels is the coordinate origin:

Standard HTML5 Canvas 2D contexts and DOM mouse events place (0, 0) at the top-left corner. If you are translating input data (such as image buffers or mouse click coordinates) into the graphical kernel, the Y-axis must be inverted:

// Converting standard top-left DOM coordinates to GPU.js graphical space:
const gpuY = canvasHeight - 1 - domY;

Emitting Pixel Colors

Instead of returning numerical values as standard kernels do, a graphical kernel writes to its mapped pixel using the built-in this.color(r, g, b, a) method. The arguments require normalized floating-point values between 0.0 and 1.0:

const renderKernel = gpu.createKernel(function() {
    // Normalize coordinates from 0.0 to 1.0
    const u = this.thread.x / this.output.x;
    const v = this.thread.y / this.output.y;
    
    // Outputs red along X-axis, green along Y-axis, fully opaque
    this.color(u, v, 0.0, 1.0);
})
.setOutput([800, 600])
.setGraphical(true);

renderKernel();

In this execution, this.output.x and this.output.y reflect the canvas dimensions (800 and 600). As this.thread.x traverses from left to right, the red channel increases. As this.thread.y traverses from bottom to top, the green channel increases, accurately reflecting the underlying WebGL coordinate space.