Part 1: Fragment Shaders: Beginner's Guide

Fragment Shaders: The Foundation of Graphics

Fragment shaders are tiny programs that run on your GPU, determining the color of every single pixel on the screen. If you've ever marveled at computer-generated art, glowing effects, or wild procedural visuals, chances are fragment shaders made it possible.

How Fragment Shaders Work

The GPU graphics pipeline works by drawing geometry (shapes made of triangles) to the screen. Here's what happens:

  1. Vertex Processing: Your vertices (corner points of triangles) are processed and positioned
  2. Rasterization: The GPU figures out which pixels are covered by each triangle
  3. Fragment Shader: For each pixel covered by geometry, the fragment shader runs to determine that pixel's color

The fragment shader is a function that runs once for every pixel covered by your geometry. It receives information about the pixel's position, time, textures, and other data called uniforms, then outputs a color.

Coloring Different Shapes

Fragment shaders can color any shape—spheres, cubes, complex models—as long as that shape is made of triangles (which everything is in 3D graphics). Each pixel that falls inside a triangle gets processed by your fragment shader.

Two Triangles That Fill the Screen

For this series, we'll use the simplest possible geometry: two triangles arranged to fill the entire screen. This is perfect for learning because:

  • Every pixel on screen runs through our shader
  • We don't need to worry about 3D math or camera transforms
  • All the visual complexity comes from the shader code itself

Think of it like having a blank canvas where we can paint anything using math. The triangles are just the surface—what we draw on them is up to us.

Basic Example: Gradient

Here's a simple shader that creates a gradient based on pixel position:

#version 300 es
precision highp float;
out vec4 fragColor;

uniform vec2 u_resolution;

void main() {
  // Normalize pixel coordinates (0.0 to 1.0)
  vec2 uv = gl_FragCoord.xy / u_resolution;
  
  // Use UV coordinates as colors (red increases left to right, green bottom to top)
  vec3 col = vec3(uv, 0.0);
  fragColor = vec4(col, 1.0);
}

Try it out below—notice how the color changes based on position:

Preview

Visualizing the Two Triangles

Normally you'd never see the triangles themselves—they're just a surface for the shader to run on. But here's what they look like with outlined edges:

Preview

Key Concepts

  • gl_FragCoord: The pixel coordinate being processed.
  • uniforms: Values sent in from the CPU, like time (u_time) or resolution (u_resolution).
  • vecN: A vector of N floats (e.g., vec2, vec3, vec4) used for positions and colors.
  • Math functions: Use functions like sin, cos, and mix to generate patterns and animations.

What's Next?

In later posts, we'll build on this knowledge to:

  • Make glowing shapes and gradients
  • Simulate lighting and 3D with just math
  • Combine multiple shaders into a single effect
  • React to mouse input and audio

Whether you're making games, interactive art, or generative graphics, mastering fragment shaders is the first step. Happy shading!