← All Posts

Why I Started Writing aRay Tracer in C

C Graphics Low-level

Most ray tracer tutorials go straight for C++ or even Python. I wanted to understand what was actually happening at the memory level — no classes, no smart pointers, no hidden constructors. Just structs, function pointers, and raw math.

The decision wasn't about masochism. It was about precision. When I read code in a high-level language, I'm always one abstraction removed from the actual computation. C strips that away. Every allocation is explicit. Every pointer is mine to manage. If something breaks, the blame is local.

The Geometry Problem

Writing a ray tracer forces you to think geometrically at every step. When you trace a ray and compute an intersection, there's no abstraction hiding the dot products and vector normalization. You feel every calculation. It's uncomfortable at first, then clarifying.

A ray is just an origin point and a direction vector. An intersection test for a sphere is just solving a quadratic equation. When you write it yourself — no glm::vec3, no Ray::intersect() — you remember it. The formula becomes yours.

typedef struct { float x, y, z; } Vec3;

float dot(Vec3 a, Vec3 b) {
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

int ray_sphere(Vec3 ro, Vec3 rd, Vec3 center, float r, float *t) {
    Vec3 oc = { ro.x-center.x, ro.y-center.y, ro.z-center.z };
    float a    = dot(rd, rd);
    float b    = 2.0f * dot(oc, rd);
    float c    = dot(oc, oc) - r*r;
    float disc = b*b - 4*a*c;
    if (disc < 0) return 0;
    *t = (-b - sqrtf(disc)) / (2.0f * a);
    return 1;
}

The BVH Problem

The biggest lesson so far: the BVH (Bounding Volume Hierarchy) is where naive implementations die. Without it, your scene complexity is O(n) per ray. With it, it drops to O(log n). The difference between a 10-second render and a 100ms one is almost entirely this data structure.

Building it without a library means building the AABB intersection test by hand, the recursive tree split, and tuning the surface-area heuristic. It's tedious. It's also the only way I've ever truly understood a BVH. Reading about it and implementing it are entirely different experiences.

What I'd Tell Myself Before Starting

Start with spheres and a fixed camera. Get a pixel on screen. Don't think about BVH, materials, or lights until you can see a grey circle on a black background and know exactly why it's there. The rest follows naturally.

Also: floating point is your enemy and your only tool. Get comfortable with it early.

Next Post Learning by Building →