Skip to content

o7q/minitracer

Repository files navigation

minitracer

a single-header, multi-threaded software raytracer.

This is a ray-tracer I designed and wrote from scratch over the course of a few weeks. It's entirely self-contained within a single C header file and requires absolutely zero 3rd-party libraries. (example source files use raylib to display a window)

I started this project as a way to learn about the intricacies of ray-tracing and how it's optimized. I am quite pleased with the result and I want to share it with you.



cornell_box.c


suzanne.c


balls.c (Camera 1)


balls.c (Camera 2)


balls.c (Camera 3)


infinite.c


Features

  • A multi-threaded renderer
  • A STL model importer
  • A sky system
  • A BMP exporter
  • Reflective, refractive, and emissive materials
  • Simulated depth of field
  • BVH optimization

Building

Notice: This project uses pthread.h for multi-threading, which is not native to non-UNIX systems such as Windows.

To compile on UNIX-based systems, first make sure you have CMake and G++ installed. Then simply use the provided build.sh or run.sh file. If you'd like: you can specify which example to build inside of the CMakeLists.txt file under the EXAMPLE variable.


Example Usage

#include "./minitracer.h"

int main(void)
{
    int width = 1280;
    int height = 720;

    MT_World *world = mt_world_create(1000);
    MT_Environment *environment = mt_environment_create();
    environment->brightness = 1;
    mt_world_set_environment(world, environment);

    MT_Camera *camera = mt_camera_create();
    camera->position.z = 4;
    camera->position.y = -0.5f;

    MT_Renderer *renderer = mt_renderer_create(width, height, 4);
    mt_renderer_set_world(renderer, world);
    mt_renderer_set_camera(renderer, camera);
    mt_renderer_set_samples(renderer, 64);
    mt_renderer_set_bounces(renderer, 4);
    mt_renderer_enable_progressive(renderer, 0); // disable progressive rendering
    mt_renderer_enable_antialiasing(renderer, 1);
    mt_renderer_enable_bvh(renderer, 0); // disable bvh optimization, bottlenecks small scenes

    MT_Material *mat_diffuse = mt_material_create();
    mat_diffuse->color = (MT_Vec3){1, 0, 0};
    MT_Material *mat_glossy = mt_material_create();
    mat_glossy->roughness = 0.1f;

    MT_Mesh *floor = mt_mesh_create_plane((MT_Vec3){0, 0, 0}, (MT_Vec3){0, 0, 0}, (MT_Vec3){50, 1, 50}, mat_glossy);
    mt_world_add_object(world, floor, MT_OBJECT_MESH);
    MT_Mesh *cube = mt_mesh_create_cube((MT_Vec3){0, -0.5f, 0}, (MT_Vec3){0, MT_PI / 4.0f, 0}, (MT_Vec3){1, 1, 1}, mat_diffuse);
    mt_world_add_object(world, cube, MT_OBJECT_MESH);

    mt_world_recalculate_bvh(world);

    mt_render(renderer);

    MT_Vec3 *pixels = (MT_Vec3 *)malloc(sizeof(MT_Vec3) * width * height);
    mt_renderer_get_pixels(renderer, pixels, 1.0f, 1);
    mt_bmp_write("render.bmp", pixels, width, height);

    mt_renderer_delete(renderer);
    mt_world_delete(world);
    mt_camera_delete(camera);
    mt_material_delete(mat_diffuse);
    mt_material_delete(mat_glossy);
    
    return 0;
}

You must manually free all objects manually using the provided delete functions. World objects that have been added to a world will automatically be freed upon calling world_delete().


Resources Used

Ray Tracing in One Weekend
Sebastian Lague's Ray Tracing Coding Adventure

About

a single-header, multi-threaded software ray tracer.

Resources

License

Stars

Watchers

Forks

Languages