3D Software Renderer from Scratch
"Building a full 3D rendering pipeline in C using SDL2 — from window initialization to triangle rasterization and memory cleanup."
1. Bootstrapping the Engine
The journey begins with raw SDL2 initialization: creating the window, renderer, color buffer, and allocating memory manually. No OpenGL. No hardware acceleration. Just pixels in memory and full control over the pipeline.
At this stage, the foundation is simple: initialize SDL, allocate buffers, define a left-handed coordinate system, and prepare the render loop.
2. The Main Loop
Everything revolves around the classic game loop: process input, update state, render frame. Timing control ensures consistent frame updates while keeping the architecture deterministic and predictable.
while (is_running) {
process_input();
update();
render();
} SDL handles keyboard events, while all math and rendering logic remain fully custom.
3. Building the Rendering Pipeline
From 3D to 2D: vertices are transformed using 4x4 matrices, projected with perspective division, and converted into screen space coordinates.
The engine implements:
- OBJ file loading for mesh import
- Back-face culling for visibility optimization
- Painter’s algorithm (with Z-buffer in progress)
- Triangle rasterization for solid rendering
4. Rasterization & Control
Triangle filling is handled manually scanline by scanline. Rendering modes can be toggled at runtime: wireframe, filled, combined modes, and back-face culling enable/disable.
This phase was critical in deeply understanding how GPUs abstract what is fundamentally just math and memory writes.
5. Clean Exit
When the loop ends, every allocated buffer is freed manually, SDL resources are destroyed, and memory is returned properly. No leaks. No undefined behavior.
From window creation to memory cleanup, the entire lifecycle is explicitly controlled — reinforcing low-level discipline.
"Understanding graphics begins when you stop relying on the GPU."