Skip to content

leonmavr/freestyle_raytracer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

260 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C/C++ CI

My first fully working ray tracer, running on the CPU.
I wrote it by relying on various sources without faithfully following any of them, often relying on my own intuition - hence the name.
It is not physically based as it uses the Phong lighting model and some easy to compute approximations.

Features

  • Phong lighting model (ambient, diffuse, specular light)
  • Shadows with softness heuristics
  • Reflection and refraction
  • Various solids and shapes (sphere, block, quad, triangle)
  • Texture mapping
  • Moving camera
  • Emissive materials (only spheres currently)
  • Misc: background image/color, gamma correction, minimal rendering of OBJ files

Future ideas:

  • Matte materials via Lambertian
  • Cylinders
  • Pinhole camera with spherical projection surface (instead of plane)
  • Perlin noise textures

Build instructions

Show build instructions

You can build this project with or without (by default) textures.

You will need GNU make (make) and a C++17 compiler.

Optionally (to render textures), you will need imagemagick to convert the pre-rendered textures to .ppm.

Without textures

Each demo is found at src/demoXX.cpp. The binaries are found at build/demoXX. To target a specific demo, set make's DEMO variable (by default demo00). You can execute:

make                 # by default builds demo00
make run             # by default builds and runs demo00
make DEMO=demo01     # change the target to demo01
make run DEMO=demo01 # build and run demo01

You can run it manually as:

./build/demoXX

Demo files also accept command like arguments, such as the camera position and rotation - read their source for more.

Other commands:

make clean            # remove objects and executables
make rebuild          # clean and build

The outputs are generated as .ppm files.

With textures

Some demos (demo00, demo04) can run with texture mapping enabled. Texture files are large so first you will need to fetch them from git LFS. To install git LFS if you haven't already:

Arch-based Debian-based
pacman -S --noconfirm git-lfs apt-get install -y git-lfs
git lfs install git lfs install

If everything is installed, update LFS and fetch textures:

git lfs fetch --all
git lfs checkout

At this stage, most files will be fetched as jpg/png. You will need imagemagick installed to convert them to .ppm, so with imagemagick installed run:

make convert # calls ./scripts/textures2ppm.sh

Then you can continue by following the instructions from the previous subsection but with use-textures appended to the arguments, i.e.:

make DEMO=demoXX run use-textures

If you're having trouble, you can refer to how the CI pipeline does it.

Running the demos and moving the camera

If everything went fine, you will build your binary at ./build/demoXX. Most demos are run with optional command like arguments as:

./build/demoXX <output_file.ppm> <camera_x> <camera_y> <camera_z>
               <camera_rotation_x_degrees> <cam_rot_y_deg> <cam_rot_z_deg>

They will write their output as PPM.

Building tips:

  1. If you want to gain performance at the expense of resolution decrease the camera's depth, or define non-reflective/non-transparent materials.

How this implementation works

Implementation details

In a nutshell, when a ray hits an object, the resulting color consists of the sum of direct light D (which is modelled as the sum of ambient, diffuse, and specular light and it's straightforward), the reflectiion, and the refraction. To compute the reflection and the refraction, we keep a depth counter d (maximum number of ray bounces) and recursively trace the ray by reflecting it about the normal and refracting it into the new medium (Snell's law) respectively, decrementing the depth counter. The reflection, refraction, and direct lights are weighed and summed to compute the final color.

The excerpt below formulates the idea skipping several details (you can ignore the fancy T (tint) operator).

Algorithm cheat sheet

More technical information in docs/tutorials.

Demo scenes

demo name description textures
demo00 Challenging scene with objects floating above a plane, overlap between an object and the plane, various materials, reflectivities and transparencies. Textures can be toggled.
demo01 Smaller scene with objects enclosed in a huge box; try moving around the camera to spot reflections on the inner walls.
demo02 Minimal .obj file renderer. Handles vertices and faces only, ignoring normals and textures.
demo03 Text rendered as tightly packed spheres.
demo04 Emissive spheres in a randomly generated arrangement of cubes.

Gallery

demo00
demo01
demo02
demo03
demo04 * **

* Background color was changed to (97, 24, 0).

** The crystal flower (magnolia) is not in the original scene. Found it here.

Below I rendered some precomputed trajectories in the scene of demo00, demo02 and demo04:

demo00.mp4
demo02.mp4
demo04.mp4

References

  1. G. Gambeta's "Computer Graphics From Scratch"
  2. Reflections and Refractions in Ray Tracing - B. de Greve
  3. Fresnel equations derivation P263
  4. Pfister's slides
  5. D. Sokolov's tinyraytracer

About

Simple and easy to understand but full-featured ray tracer from scratch on the CPU in C++17.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors