C Ray Tracer

An educational project to build a ray tracer's core components, including multiple shading models, reflections, and a BVH acceleration structure.

More About the Project

C | 3D Graphics | Ray Tracing

This project, part of a 'Graphics and Game Technology' course, involved implementing the fundamental algorithms of a ray tracer from a provided C framework. I implemented the initial camera ray generation and various shading models, including Matte, Blinn-Phong, and recursive reflections, complete with shadow casting. A major component was performance optimization, where I implemented an efficient traversal algorithm for a Bounding Volume Hierarchy (BVH) to accelerate ray-triangle intersections for complex 3D models. Finally, I added anti-aliasing to improve final image quality.

Rendered Images

1 / 3

My Contributions

Core Ray Tracing and Optimization

Shader and Lighting Implementation

Image Quality

Matte Shader

shade_matte(intersection_point ip)
{
    float c = 0;
    float shadow_ray_origin_offset = 1.0e-3;
    vec3 normal = ip.n;

    for (int i = 0; i < scene_num_lights; i++) {
        light scene_light = scene_lights[i];

        float intensity = scene_light.intensity;
        vec3 direction = v3_normalize(v3_subtract(scene_light.position, ip.p));

        float point_light_contribution = 0;

        vec3 shadow_ray_origin = v3_add(ip.p, v3_multiply(direction, shadow_ray_origin_offset));

        if (!shadow_check(shadow_ray_origin, direction)) {
            point_light_contribution = intensity * fmax(0, v3_dotprod(normal, direction));
        }

        c += point_light_contribution;

        if (c >= 1) {
            c = 1;
            break;
        }
    }
    c = fmin(1, c + scene_ambient_light);
    return v3_create(c, c, c);
}

Part of Phong Shader

light scene_light = scene_lights[i];

float intensity = scene_light.intensity;
vec3 direction = v3_normalize(v3_subtract(scene_light.position, ip.p));

vec3 halfway_vec = v3_normalize(v3_add(ip.i, direction));

float diffuse_contribution = 0;
float specular_contribution = 0;

vec3 shadow_ray_origin = v3_add(ip.p, v3_multiply(direction, shadow_ray_origin_offset));

if (!shadow_check(shadow_ray_origin, direction)) {
    diffuse_contribution = intensity * fmax(0, v3_dotprod(normal, direction));
    specular_contribution = intensity * powf(v3_dotprod(normal, halfway_vec), alpha);
}

c_diffuse += diffuse_contribution;
c_specular += specular_contribution;