Master the fundamental concepts of gpu architecture through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksModern GPUs render images through a multi-stage pipeline. Early GPUs used fixed-function stages; today most stages are programmable shaders, but the data flow remains the same.
The standard pipeline in order:
The rasterizer is the bridge between the vertex-centric and fragment-centric worlds. For example, one triangle with three vertices can generate thousands of fragments on a large screen area.
Vertex shaders run once per vertex. Fragment shaders run once per fragment. Attributes like color and texture coordinates are interpolated across the triangle surface using barycentric coordinates during rasterization.
cLoading…
Vulkan, Direct3D 12, and Metal expose this same sequence as explicit pipeline state objects. Engines from id Tech to Unreal execute billions of these stage transitions per frame.
You will simulate the pipeline for a single triangle, printing what happens at each stage from vertex input through fragment output. This task asks you to trace attribute interpolation and show how three vertices become many fragments. Getting rasterizer barycentric interpolation right here is the prerequisite for the software rasterizer subtrack.
Push triangles through a miniature graphics pipeline, with every stage in exact integer arithmetic:
# starts a comment.
cLoading…
area2 = (x1-x0)(y2-y0) - (y1-y0)(x2-x0).
cull back, back-facing triangles are culled. With cull none, swap vertices 1 and 2 of a back-facing triangle before rasterizing.maxx <= 0, maxy <= 0, minx >= W or miny >= H, the triangle is outside and clipped. If the box extends past the screen, it is scissored: clamp the box to [0, W] × [0, H].minx ≤ px < maxx and miny ≤ py < maxy, compute E(a→b) = (bx-ax)(py-ay) - (by-ay)(px-ax) for edges v0→v1 (w2), v1→v2 (w0) and v2→v0 (w1). The pixel is covered if all three are ≥ 0. An edge with E = 0 counts only if it is a top edge (ay == by && bx > ax) or a left edge (by < ay).z = round(Σ wᵢzᵢ / Σ wᵢ), and the same for R, G and B. Round half up, with Σwᵢ = 2·area2 on the doubled grid.z < depth, and then it writes the colour, the depth and its triangle's letter.cLoading…
, partly outside (scissored) before the fragment count.primitive assembly: N leftover vertex|vertices ignored after the vertex list.x*2-4)... probe reports background for them.viewport: W (1-40) H (1-24)transform: SX SY TX TY (it resets to the identity)cull: back|nonevertex: X Y Z(0-999) R G B(0-255), vertex: at most 30 verticesprobe: X Y inside the viewportunknown command XInput:
cLoading…
Output:
cLoading…
Hidden tests cover two triangles sharing a diagonal (watertight coverage), back-face culling on and off, a small triangle in front, an off-screen triangle, a degenerate triangle, a leftover vertex, a scaled and translated triangle that is scissored, a depth-test failure, and argument errors.