This repository contains my implementation of the ray tracer described in the wonderful Ray Tracing in One Weekend book as a standalone library. The code here uses C++23 and utilises as much of C++20 modules and other modern C++ features as possible.
The code has been tested using Apple macOS Sonoma 14.4.1, Clang 17.0.6, Ninja 1.11.1 and GNU Bash 5.2.26.
To integrate the code into your own executable, create a directory with a main.cxx
that imports the appropriate modules from the RTIOW
pseudo-namespace:
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <memory>
import RTIOW.Camera;
import RTIOW.Color;
import RTIOW.HittableObjectList;
import RTIOW.Material;
import RTIOW.Utility;
import RTIOW.Sphere;
import RTIOW.Vec3;
int main()
{
// World
HittableObjectList world{};
auto const ground_material{ std::make_shared<Lambertian>(Color(0.5, 0.5, 0.5)
) };
world.add(std::make_shared<Sphere>(Point3(0, -1000, 0), 1000, ground_material)
);
for (int a{ -11 }; a < 11; ++a) {
for (int b{ -11 }; b < 11; ++b) {
auto const choose_material{ random_double() };
Point3 const center(
a + 0.9 * random_double(),
0.2,
b + 0.9 * random_double()
);
if ((center - Point3(4, 0.2, 0)).length() > 0.9) {
if (choose_material < 0.8) {
// Diffuse
auto const albedo{ Color::random() * Color::random() };
auto const material{ std::make_shared<Lambertian>(albedo) };
world.add(std::make_shared<Sphere>(center, 0.2, material));
} else if (choose_material < 0.95) {
// Metal
auto const albedo{ Color::random(0.5, 1) };
auto const fuzz{ random_double(0, 0.5) };
auto const material{ std::make_shared<Metal>(albedo, fuzz) };
world.add(std::make_shared<Sphere>(center, 0.2, material));
} else {
// Glass
auto const material{ std::make_shared<Dielectric>(1.5) };
world.add(std::make_shared<Sphere>(center, 0.2, material));
}
}
}
}
auto const material_1{ std::make_shared<Dielectric>(1.5) };
world.add(std::make_shared<Sphere>(Point3(0, 1, 0), 1.0, material_1));
auto const material_2{ std::make_shared<Lambertian>(Color(0.4, 0.2, 0.1)) };
world.add(std::make_shared<Sphere>(Point3(-4, 1, 0), 1.0, material_2));
auto const material_3{ std::make_shared<Metal>(Color(0.7, 0.6, 0.5), 0.0) };
world.add(std::make_shared<Sphere>(Point3(4, 1, 0), 1.0, material_3));
Camera camera{};
camera.aspect_ratio = 16.0 / 9.0;
camera.image_width = 1200;
camera.samples_per_pixel = 500;
camera.max_depth = 50;
camera.vertical_field_of_view_in_degrees = 20;
camera.look_from = Point3(13, 2, 3);
camera.look_at = Point3(0, 0, 0);
camera.v_up = Vec3(0, 1, 0);
camera.defocus_angle_in_degrees = 0.6;
camera.focus_distance = 10;
camera.render(world);
return EXIT_SUCCESS;
}
and create a CMakeLists.tx
file using FetchContent
:
cmake_minimum_required(VERSION 3.29)
include(FetchContent)
FetchContent_Declare(
RTIOW
GIT_REPOSITORY https://github.com/neuroevolutus/RayTracingInOneWeekend.git
GIT_TAG main
)
FetchContent_MakeAvailable(RTIOW)
project(test CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(main main.cxx)
target_link_libraries(main RTIOW::raytracer)
Initialise your CMake build with cmake -B release -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_CXX_COMPILER=$(which clang+)`. Then, build the project with `+cmake --build release
.