Master the fundamental concepts of modern graphics apis (low level) through this focused micro-challenge.
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 worksOpenGL is a cross-platform API for 2D and 3D graphics. Despite being over 30 years old, its pipeline stages remain relevant because Vulkan, D3D12, and Metal expose the same flow with lower-level control.
The programmable pipeline stages:
OpenGL is stateful: you bind buffers, shaders, textures, and uniforms, then call glDrawElements. For example, a single triangle draw might bind a VAO, set the MVP uniform, activate a texture unit, and issue one draw call producing thousands of fragments from three vertices.
cLoading…
Modern APIs replace implicit global state with explicit pipeline state objects, but the stage sequence is identical. Debugging "why is my triangle invisible" almost always traces back to one of these stages.
You will simulate the OpenGL pipeline for a single colored triangle, printing what happens at each stage. This task asks you to trace vertex transformation, attribute interpolation, and final fragment color. Understanding this pipeline is the prerequisite for every Vulkan exercise in this subtrack.
Simulate the part of an OpenGL driver that turns API calls into vertices:
GL_ARRAY_BUFFER binding point;glVertexAttribPointer capturing the currently bound buffer;glDrawArrays, which reads each attribute from an interleaved buffer with a byte stride and offset;glGetError reads it.One call per line (// starts a comment):
cLoading…
glGenBuffers returns the next unused names, starting at 1 (at most 15 in total). A negative N gives GL_INVALID_VALUE and prints glGenBuffers: n must be >= 0.GL_ARRAY_BUFFER gives GL_INVALID_ENUM;GL_INVALID_OPERATION;GL_INVALID_OPERATION.GL_INVALID_VALUE;GL_INVALID_OPERATION;GL_INVALID_OPERATION;GL_INVALID_ENUM, and a negative first/count gives GL_INVALID_VALUE;glDrawArrays: no enabled attributes;offset + v × stride, where a stride of 0 means tightly packed (size × 4). If the last vertex's attribute ends past the buffer, print glDrawArrays: attribute A reads past the end of buffer B (needs N bytes, has M) for each such attribute, set GL_INVALID_OPERATION, and draw nothing.GL_NO_ERROR, GL_INVALID_ENUM, GL_INVALID_VALUE or GL_INVALID_OPERATION. Only the first error since the last read is kept.cLoading…
vert(ex|ices), then the number of whole primitives (count / 3, / 2 or / 1) with a singular or plural noun.%g.glBindBuffer: TARGET ID, glVertexAttribPointer: INDEX SIZE STRIDE OFFSET, …), and unknown calls print unknown call X.Input:
cLoading…
Output:
cLoading…
glVertexAttribPointer time is how VAOs work.Hidden tests cover two buffers feeding two attributes, a drawing range with FIRST > 0, reads past the end, invalid enums and values, the sticky first error, misaligned offsets, a pointer call with no buffer bound, and a draw with no enabled attributes.