Building the pipeline by hand.
The course supplied starter code and test scenes. Each project asked for the part that libraries usually hide: transformations, meshes and their normals, and how light reaches a pixel.
The warm-up was a recursive triangle fractal, seven levels deep. Moving the mouse up and down changes how large each level is relative to its parent.
A cow from boxes.
The modeling project asked for an object assembled from 3D primitives under a light. I built a Minecraft-style cow from dozens of boxes: body, head, nostrils, ears, legs, hooves, and each patch of its coat, positioned with nested transformations so the whole animal moves as one.
Smooth tubes from flat quads.
The mesh project built shapes from quadrilaterals with a normal at every vertex, so lighting reads as a smooth surface. I wrote cylinders between two points, then tubes that follow a cubic Bézier curve, computing each ring of vertices from the curve’s position and derivative. Joining tube segments end to end produced the knot.
One ray per pixel, then many.
The ray tracer cast a ray from the eye through each pixel and shaded the nearest sphere it hit. The second part added disks, shadows from point lights, area lights that soften those shadows, and colored lights.
Area lights need many samples per pixel. Supersampling on a grid, then jittering each sample within its cell, trades render time for smoother edges and penumbras.