examples.gpu-shaders · shader ·

Make choices per pixel

Use integer cells and a branch to paint a crisp two-color checker.

complete-programcomputegpuimageshaderyeho

Every pixel can make its own decision. A GPU branch is still ordinary if logic, subject to the compute provider’s admitted subset.

[gpu] compute Paint(buffer of int pixels, int width, int height, float time)

Status: native-metal-example

03 / Make choices per pixel

Use integer cells and a branch to paint a crisp two-color checker.

gpu · shader · image · type checked

[gpu]
compute Paint(buffer of int pixels, int width, int height, float time)
{
    int index = compute.index
    if index >= pixels.count { return }
    int row = index / width
    int column = index - row * width
    float u = Math.IntToFloat(column) / Math.IntToFloat(width - 1)
    float v = Math.IntToFloat(row) / Math.IntToFloat(height - 1)
    int cellX = column / 16
    int cellY = row / 16
    int sum = cellX + cellY
    float r = 0.02
    float g = 0.04
    float b = 0.08
    if sum / 2 * 2 == sum
    {
        r = 0.08
        g = 0.9
        b = 0.7
    }
    int red = Math.RoundToInt(Math.ClampFloat(r, 0.0, 1.0) * 255.0)
    int green = Math.RoundToInt(Math.ClampFloat(g, 0.0, 1.0) * 255.0)
    int blue = Math.RoundToInt(Math.ClampFloat(b, 0.0, 1.0) * 255.0)
    pixels[index] = red * 65536 + green * 256 + blue
}

// CPU: allocate an image and submit one GPU invocation per pixel.
int width = 128
int height = 128
buffer of int pixels
pixels.Resize(width * height)
computeTask job = dispatch Paint(pixels, width, height, 0.0)
wait job
if job.failed { Console.Error(job.error.message) Process.Exit(1) }

// CPU: save the completed RGB pixels as a portable PPM image.
text image = "P3\n" + Text.From(width) + " " + Text.From(height) + "\n255\n"
for row from 0 < height
{
    text line = ""
    for column from 0 < width
    {
        int pixel = pixels[row * width + column]
        int red = pixel / 65536
        int green = (pixel - red * 65536) / 256
        int blue = pixel - red * 65536 - green * 256
        line = line + Text.From(red) + " " + Text.From(green) + " " + Text.From(blue) + " "
    }
    image = image + line + "\n"
}
File.WriteText("shader.ppm", image)
Console.Log("Wrote shader.ppm")
project.mech
manifestVersion = "2"
package = "learning.shaders.gpu_checker"
version = "0.1.0"
languageEdition = "yeho-core-2026.1"

[app]
kind = "headless"
Expected output
Wrote shader.ppm
Notes and source

Change both divisors from 16 to 8. Try replacing the teal values with a warm orange.

The dedicated shader verifier executes this program on Metal and compares every output channel with a separate CPU reference. Evidence: https://demonhunterlabs.com/learning/gpu-shaders/verification.json

The program writes shader.ppm in its current directory. Native image generation is separate from presenting frames in a game window.

demonhunterlabs/app/lib/yeho-gpu-shaders.ts