Mapping this.thread.x and this.thread.y in gpu.js
In gpu.js, 2D kernels execute concurrently across a grid of parallel
threads where this.thread.x and this.thread.y
serve as the unique spatial indices for each thread. When defining a 2D
output dimensions array, gpu.js utilizes a standard Cartesian coordinate
system where (0, 0) begins at the bottom-left corner rather
than the top-left corner commonly used in standard web canvas and DOM
operations. Understanding how these thread indices correspond to matrix
dimensions, rows, and columns is critical for accurate data
transformation, image processing, and mathematical computations.
The Dimension Grid
When creating a 2D kernel in gpu.js, you define the output dimensions
via an array passed to setOutput([width, height]).
- The first element represents the size along the X-axis
(
width). - The second element represents the size along the Y-axis
(
height).
Inside the kernel function, gpu.js maps threads across this 2D plane:
this.thread.x: Represents the horizontal column index, ranging from0towidth - 1(moving left to right).this.thread.y: Represents the vertical row index, ranging from0toheight - 1(moving bottom to top).
Cartesian Orientation (Bottom-Left Origin)
Because gpu.js runs on top of WebGL, it inherently follows the OpenGL
texture coordinate convention. The origin (0, 0) is located
at the bottom-left of the output array:
this.thread.x = 0, this.thread.y = 0points to the bottom-left corner.this.thread.x = width - 1, this.thread.y = 0points to the bottom-right corner.this.thread.x = 0, this.thread.y = height - 1points to the top-left corner.this.thread.x = width - 1, this.thread.y = height - 1points to the top-right corner.
Mapping to 2D Arrays and Matrices
In standard JavaScript, 2D arrays are commonly indexed as
array[row][column], which conceptually treats
(0, 0) as the top-left element. When reading from or
writing to a traditional 2D array or matrix inside a gpu.js kernel:
- Columns correspond to
this.thread.x. - Rows correspond to
this.thread.y.
To access an element matching Cartesian coordinates:
const value = inputMatrix[this.thread.y][this.thread.x];If your input data assumes the top-left corner is (0, 0)
(such as standard image pixel data or typical nested arrays) and you
want to maintain that orientation in the output, invert the Y-axis
coordinate:
const invertedY = (height - 1) - this.thread.y;
const value = inputMatrix[invertedY][this.thread.x];Flattening to 1D Buffer Indices
When working with flattened 1D arrays (such as an ImageData buffer or
a flattened matrix of size width * height), convert the 2D
thread coordinates into a single linear index using the following
formula:
const index = (this.thread.y * width) + this.thread.x;For RGBA image buffers containing four values per pixel:
const pixelIndex = ((this.thread.y * width) + this.thread.x) * 4;
const red = imageBuffer[pixelIndex];
const green = imageBuffer[pixelIndex + 1];
const blue = imageBuffer[pixelIndex + 2];
const alpha = imageBuffer[pixelIndex + 3];