Ray Tracing 001: Introduction


This section is dedicated to my journey to learning how to build a ray tracer. Each post in this series will document one step in this journey.

I will begin with Peter Shirley’s excellent book Ray Tracing in a Weekend and his following two volumes Ray Tracing - The Next Week and Ray Tracing - The Rest of Your Life. I found the first book on Amazon Kindle some time ago, but it’s now available for free at raytracing.github.io.

But this will not be limited to these books alone. I plan to explore multi-threaded and parallel techniques, as well as more advanced topics with further papers, articles, tutorials and literature including the Ray Tracing Gems.

In the end I want to produce some animations, too. My goal is to complete a ray-traced animation of the Triadic Ballet in time for the 100th anniversary of its premiere in September 2022.

Eventually I want to enter the realm of physics-based animation and fluid simulations as well. But let’s start with a single simple image first. :)

As far as the code is concerned, I tested and compiled the code with the GNU compiler on Linux Mint and Windows with cygwin and Microsoft C++ (Visual Studio Code). It should work on other platforms as well, but let me know if it doesn’t work on Mac. I also want to look into cmake, but this will have to wait until it makes sense for the project.

Some chapters also contain an HTML file with a Javascript version. I’m sure that the ray tracer will eventually require more than what can be achieved in a pure Javascript implementation, but let’s see how far I can take this. I’m curious to find out what’s possible and what can be done to speed it up for the web. :)

WebAssembly, Emscripten and Rust are some options I want to explore here later as well.

Some of the first code snippets will be short enough to include in full length, but I’ll only highlight differences from one step (or episode) to another later on. The complete code is be available on GitHub here: github.com/celeph/ray-tracing.

For the original source code (the correct “master solution” so to speak), please visit Peter Shirley’s book repository.

The idea behind this is to document and further my own learning by trying to explain it to myself in my own words. I’ll begin quite literally at zero because I have not have much experience to build on. I hope it will make sense to someone else and that other beginners will find my notes helpful.

There’s always a chance I understood something wrong, made a mistake, or didn’t follow best practices or proper style. If you spot anything that’s wrong or could use some improvement, please let me know. Any feedback, suggestions, or bug reports are always appreciated!

At the bottom of each chapter you can find references to the books and resources the chapter was based on. Be sure to check them for more information and expert insights.

Let’s get started, and enjoy!


Simple Image with PPM

The Portable PixMap (PPM) is a simple text-based image format. No special libraries needed: create an image by simply writing pixel data to a text file.

// ppm-example.cpp
#include <iostream>

int main() {
  int nx = 200;
  int ny = 100;

  std::cout << "P3\n" << nx << " " << ny << "\n255\n";
  for (int j = ny-1; j >= 0; j--) {
    for (int i = 0; i < nx; i++) {
      float r = float(i) / float(nx); // left to right from 0 to 0.995
      float g = float(j) / float(ny); // top to bottom from 0.99 to 0
      float b = 0.2;

      int ir = int(255.99 * r); // left to right from 0 to 254
      int ig = int(255.99 * g); // top to bottom from 253 to 0
      int ib = int(255.99 * b); // always 51

      std::cout << ir << " " << ig << " " << ib << "\n";

Simple Image with Javascript and Canvas

The Javascript code below is almost identical with the C++ code but instead of a PPM file stream it renders each pixel in a 200x100 canvas element.

To keep the color gradient in the same direction as the PPM I reversed the y-direction in the fillRect() call.

Credits and Further Reading

Next Steps