Lab · hands-on
A mini cube rasterizer
A cube pushed through the same
model→view→projection→screen chain by a pure software rasterizer (barycentrics, no GPU). Turn the cube and the FOV, switch off the z-buffer — and watch far faces climb over near ones; turn on backface culling and flip between perspective and orthographic. Every toggle is one pipeline stage you can see with your own eyes.How to use this
Every frame all 12 triangles of the cube are rotated, projected (x_s = f·x/z) and filled pixel by pixel. The z-buffer: for each pixel we keep the nearest inverse depth 1/z and draw a fragment only if it is closer. Turn it off and the draw order starts lying to you. Backface cull uses the face normal to throw away faces turned away from us. Perspective divides by depth (far is smaller); orthographic does not (all faces the same size). The counters show: triangles drawn, backfaces culled, fragments rejected by the z-test.
What to notice: 1) turn off the z-buffer and backface cull at once and start auto-spin — the back faces punch through the front ones and the picture flickers with the draw order. Put the z-buffer back — correct again at any order. 2) turn off only backface cull (z-buffer on) — you can see that culling half the faces was never needed for correctness (the z-buffer sorted it out anyway), but the "drawn" counter doubled: culling was saving work. 3) switch to orthographic — the cube stops narrowing with distance, far and near faces are the same size (no divide by
z). 4) push the FOV toward 120° — heavy fisheye distortion at the edges; a narrow FOV is like a telephoto lens, the edges nearly parallel.🏠 What's next
Go back to the lesson, block "🔧 Run it and poke at it": in Godot, output DEPTH_TEXTURE onto a quad — you'll see the same depth this lab keeps in its z-buffer, but distributed nonlinearly (1/z): the near range stretched, the far range squeezed together. Put two coplanar faces flush against each other → you'll catch the z-fighting that a single cube can't show you here.
Connections
from the lesson
The 3D pipeline — the theory: the matrix chain, the perspective divide by
w, near-plane clipping, z-buffer vs painter.contrast
Doom and BSP — there the order comes from sorting geometry (BSP), here from a per-pixel depth buffer. The z-buffer switched off in this lab is exactly why Doom had to sort.
What to notice afterwards (observation checklist)
- z-buffer off + cull off → back faces punch through the front ones; z-buffer on → correct at any order. The buffer sorts pixels, not polygons.
- cull off (z-buffer on) → same picture, but "triangles drawn" doubles: culling is an economy, not a correctness measure (for a convex body).
- perspective → the far face is smaller than the near one (divide by
z); orthographic → all faces the same size. - wide FOV → distortion at the edges (fisheye); narrow → nearly a parallel projection.