Ray Tracing S01E01


Introduction

The following series of posts will document my learning journey to building a ray tracer.

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.

This series will not be limited to these books alone. I plan to explore multi-threading and parallel computing options to speed it up, and dive into more advanced topics with further papers, articles, tutorials and literature including the Ray Tracing Gems.

In the end I want to produce some animations. 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 hereL github.com/celeph/ray-tracing.

For the original source code (the correct master solution), 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 hope it makes sense to someone else as well, but I will probably not have much time to edit and polish my writing very much. 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 that helped me through this journey. Be sure to check them for more information and expert insights.

I hope you find this material interesting and helpful.

Gerrit

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.

Coming next: S01E02 - Other Image Formats with stb_image.h

Credits and Further Reading