Skip to content

Latest commit

 

History

History
133 lines (101 loc) · 4.06 KB

README.adoc

File metadata and controls

133 lines (101 loc) · 4.06 KB

Ray Tracing in One Weekend

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.

Tested Platforms / Required Tools

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.

Utilising the Library

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:

main.cxx
#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:

CMakeLists.txt
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)

Building Your Project

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.

Generating the PPM Image File

In your CMake project, simply run release/main > image.ppm. You should get an image file that looks like the one below:

A Ray-Traced Scene