Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Raytracer

A CPU raytracer written in C++23. Reads a plain-text scene description and renders it to a PPM image file (output.ppm).

Features

Primitives

  • Sphere — defined by centre, radius, and flat colour
  • Plane — defined by a point on the plane, a surface normal, and flat colour; double-sided (normal is flipped for back-face hits)

Lights

  • AmbientLight — constant intensity multiplied by the surface colour
  • DirectionalLight — Lambertian (cosine-weighted) diffuse shading with hard shadow rays; occluded surfaces receive no contribution from that light

Rendering

  • Closest-hit traversal with an epsilon bias (0.001) to avoid self-shadowing
  • Sky gradient background (white at the horizon, light blue at the zenith) when no primitive is hit

Scene format — plain-text .cfg file with # line comments (see below)

Build — CMake, C++23, no external dependencies

Build

cmake -S . -B build
cmake --build build

The binary is placed at ./raytracer (the repo root), not inside build/.

Default build type is Release. To build in debug mode:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build

Run

./raytracer <SCENE_FILE>

The rendered image is written to output.ppm in the current working directory. It is not written to stdout.

./raytracer scenes/spheres.cfg
# result is in ./output.ppm

To display the result, open output.ppm with any viewer that supports PPM/P3 (GIMP, feh, Preview on macOS, ImageMagick's display, etc.) or convert it:

convert output.ppm output.png

Usage / help:

./raytracer --help
./raytracer -h
USAGE: ./raytracer <SCENE_FILE>

Exit codes follow the Epitech convention: 0 on success, 84 on error.

Scene file format

Scene files use a custom plain-text block syntax. Comments start with #. Fields end with ;. Blocks use { }. Lists use ( ).

# scenes/mixed.cfg — spheres on a ground plane

camera = {
    resolution = { width = 800; height = 600; };
    position   = { x = 0; y = 0; z = 0; };
    rotation   = { x = 0; y = 0; z = 0; };  # parsed but not yet applied
    fieldOfView = 90.0;                        # degrees, must be in (0, 180)
};

primitives = {
    spheres = (
        # { x y z } = centre, r = radius, color = { r g b } in 0–255
        { x = 0; y = 0; z = 5; r = 1.0; color = { r = 220; g = 60; b = 60; }; },
        { x = -2.5; y = 0.6; z = 7; r = 1.2; color = { r = 60; g = 200; b = 90; }; }
    );
    planes = (
        # { px py pz } = point on plane, { nx ny nz } = surface normal
        { px = 0; py = -1.5; pz = 0; nx = 0; ny = 1; nz = 0;
          color = { r = 80; g = 80; b = 100; }; }
    );
};

lights = {
    ambient = 0.2;   # intensity in [0, 1]; 0 disables ambient entirely
    diffuse = 0.8;   # intensity applied to each directional light
    directional = (
        # { x y z } = light direction vector (normalised automatically)
        { x = -1; y = -1; z = 1; }
    );
};

Bundled example scenes

Scene What it shows
scenes/spheres.cfg Three spheres, one directional light
scenes/planes.cfg Ground plane lit by a directional light
scenes/lights.cfg Two spheres lit by two directional lights
scenes/shadows.cfg Hard shadows cast by spheres onto a ground plane
scenes/mixed.cfg Spheres and a ground plane together

Project layout

src/
  main.cpp               entry point
  app/
    App.{hpp,cpp}        top-level run() function, orchestrates parse→render→write
    Args.{hpp,cpp}       CLI argument parsing (-h / --help / <scene_file>)
  io/
    PpmWriter.{hpp,cpp}  writes PPM P3 format to a file
    scene/
      SceneLoader.{hpp,cpp}     reads the .cfg file and drives all parsers
      SceneSyntax.{hpp,cpp}     block/list/field extraction helpers (regex + charconv)
      CameraParser.{hpp,cpp}    parses the camera block
      PrimitiveParser.{hpp,cpp} parses spheres and planes
      LightParser.{hpp,cpp}     parses ambient and directional lights
  math/
    Vec3.{hpp,cpp}       3-component vector with arithmetic operators, dot, cross
    Ray.{hpp,cpp}        origin + direction, ray.at(t)
    Color.{hpp,cpp}      RGB double, clamped() for PPM output
  render/
    Camera.{hpp,cpp}     generates primary rays from (position, FOV, resolution)
    Renderer.{hpp,cpp}   per-pixel shade() with closest-hit + shadow rays
  scene/
    Scene.hpp            flat aggregate: CameraConfig, Primitives, Lights
    CameraConfig.hpp     POD struct for parsed camera settings
    HitRecord.hpp        intersection result: distance, point, normal, colour
    primitives/
      IPrimitive.hpp     pure-virtual hit(ray, tMin, tMax) → optional<HitRecord>
      Sphere.{hpp,cpp}
      Plane.{hpp,cpp}
    lights/
      ILight.hpp         pure-virtual contribution(hit) + directionFrom(point)
      AmbientLight.{hpp,cpp}
      DirectionalLight.{hpp,cpp}
scenes/                  example .cfg files

Authors

Group project — Epitech OOP module (4th semester).

Origin

Originally developed as part of the Epitech curriculum. The project subject (PDF) is not redistributed here per Epitech policy.

About

A CPU raytracer in C++23 with spheres, planes, ambient & directional lighting.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages