Chapter 10 · Shaders

The GPU's tiny
programs.

Chapter 04 said the GPU runs millions of little jobs. Here's the secret: those jobs are two tiny programs you can write. One places corners. One colors pixels. Together they're every material, every light, every cartoon outline you've ever seen.

press play — 90 seconds ↓
▶ watch rgbguy's original — Game Engine EP2 — the shader part
The lesson · a 90-second movie you can touch

Press play. It explains itself.

Plays like the video — one caption at a time, the picture animating under it — and it pauses when it's your turn. Skip around with the dots or arrow keys. The full lab comes after.

skip the lesson ↓
90 seconds · it pauses when it's your turn
Lab 1 · The pixel function

color = f(x, y, time)

A fragment shader is a function the GPU calls once per pixel, handing it that pixel's coordinates. Whatever color the function returns, the pixel becomes. Pick a recipe, then bend it with the sliders — everything you see is being recomputed for every pixel, every frame, exactly like the real thing.

every pixel runs the formula ↓

Recipe

Bend it

10
1.0
this frame, per pixel:
c = sin(x·10 + t)
≈ 19,800 pixels · 60×/s
Lab 2 · Lighting = the dot product's day job

Drag the sun around the sphere

Every point on a surface has a normal — the arrow pointing straight away from it. Lighting is one line: brightness = max(0, N · L) — the dot product from chapter 01, asking "does this point face the light?" Slide bands down to 3 and you've invented toon shading.

drag the ☀ anywhere

Shading

0.12
34
per pixel:
d = max(0, N·L)
c = ambient + d · albedo
light at (0.7, −0.5)
Lab 3 · Post-processing — the video's PPquad

One more shader, over the finished frame

The video's engine has PPQuadVertex/Fragment.glsl — a shader pair that runs over the already-rendered frame, once per screen pixel: picture in, tweaked picture out. That's every Instagram filter, every night-vision mode, every retro CRT look. Click an effect and read what it does to each pixel.

a tiny rendered scene, re-shaded ↓

Effect

per screen pixel:
out(x,y) = in(x,y) — pass-through
runs AFTER the whole scene is drawn
The real code · from the video's engine

Two programs, whole pipeline

This is real GLSL — the same shape as the files in the video's engine (basicvertex.glsl, basicfragment.glsl, toonShading…). The vertex shader runs once per corner; the fragment shader runs once per pixel. Everything in this course meets here.

// vertex shader — runs once per VERTEX (chapter 03 + 04)
#version 460 core
layout (location = 0) in vec4 aPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void)
{
    gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition;
}
// fragment shader — runs once per PIXEL (chapter 01's dot product, at work)
in vec3 normal;  in vec3 lightDir;
out vec4 fragColor;
void main(void)
{
    float d = max(0.0, dot(normalize(normal), normalize(lightDir)));
    // toon shading — the video's toonShadingFragment.glsl, in one line:
    // d = floor(d * 3.0) / 3.0;
    fragColor = vec4(albedo * (0.12 + d), 1.0);
}
the fancy ones (cook-torrance, post-processing) are this + more math — same two slots ✎
Spot it in the wild
where you already meet shaders, daily —
  • Toon games. Zelda, Fortnite comic modes, anime games — the same N·L, snapped into 2–3 bands. You built it in Lab 2.
  • Every photo filter. Instagram filters are fragment shaders: color-in, tweaked-color-out, once per pixel. Post-processing (the video's PPquad) is the same trick over the whole finished frame.
  • Minecraft shader packs. Realistic water, clouds, sunsets — every pack you've downloaded is literally this code, swapped in. Water, lava and portals are pixel functions of time — you bent one in Lab 1.
See it in 3D · orbit it like Blender

This one is NOT a simulation

Everything above imitated a shader in canvas. This torus knot runs a real GLSL fragment shader, compiled by your actual GPU — the very N·L, bands and specular you just built, in the real language. Toggle toon and read the shader line doing it.

drag to orbit · scroll to zoom

Material

running on your GPU, per pixel:
float d = max(dot(N, L), 0.0);
uBands = ∞ · Blinn specular on
The source · rgbguy's original

Watch the video, jump by section

Click any moment on the right — it takes you straight there (in place when this site is served over http, on YouTube when opened as a local file).