Module 02

Vectors & trig, rebuilt for shaders

A point and a vector are not the same vec2

GLSL happily lets you subtract two positions, add a direction to a point, or add two points together — it's all just vec2 to the compiler. But it's not all the same idea, and mixing them up is where confusion starts. When you think location, think a dot on the screen. When you think displacement, think an arrow — it has a length and a direction, but no fixed position of its own.

gl_FragCoord.xy is a point. uv - 0.5 is a vector — "how far and which way from center." Subtract two points and you always get a vector, never a point: offset = mouseUV - center tells you the direction and distance from the center to the mouse, and it stays exactly the same if you slide both mouseUV and center by the same amount, because a shared shift cancels out in the subtraction.

The dot product is just "how aligned"

dot(a, b) looks like arithmetic trivia the first time you see it — multiply the matching components and add them up — until you normalize both vectors first. Do that, and dot(normalize(a), normalize(b)) always comes out between -1 and 1, and it tells you exactly one thing: how aligned the two directions are. 1 means pointing the same way, 0 means perpendicular, -1 means dead opposite.

That one number shows up constantly once you're past this course's fundamentals — it's the basis of lighting calculations (how much a surface faces a light), and you'll lean on the same "how aligned" intuition again when one-point reflection shows up in Module 06.

sin and cos turn time into motion

cos θ sin θ θ
This graph, then vec2(cos(theta), sin(theta)) in the shader below — same idea, twice. If the picture makes sense, the code will too.

Quick refresher, because it matters more here than it ever did in school: a point moving around the unit circle at angle θ sits at (cos θ, sin θ). Feed in u_time as the angle and you get free, continuous motion — no keyframes, no easing curves, just a wave.

Rotating a whole shape uses the same two functions, packaged as a 2×2 matrix: mat2(cos(a), -sin(a), sin(a), cos(a)). But here's the part that trips people up the first time: to make a shape appear to spin clockwise on screen, you rotate the sampling coordinate by the shape's angle — you're not moving the square, you're asking "where would this pixel have come from before the square turned?" It's the same "transform the space, not the shape" idea you'll see formalized with SDFs in Module 04.

Predict the output

You compute dot(normalize(a), normalize(b)) and get back a value very close to 1.0. What does that tell you about a and b?