Trayrace is a minimal Monte Carlo renderer, created with the help of Greg Turk at Georgia Tech as an independent study project for my senior year.
Code available at GitHub: https://github.com/GHF/trayrace
Trayrace was designed to (eventually) have the bells and whistles of an advanced physically-based photorealistic renderer—like many renderers, it’s based loosely on PBRT—but was implemented with uniquely little “from scratch” code, through judicious choice of off the shelf components:
- Intel Embree—library that builds BVHs and traces rays. Its interface is very simple (though less so since I last visited it in summer 2011), extremely fast (it has a parallel build and the raytracing uses SIMD heavily), and it’s also mostly self-contained, once you figure out the organization of the source code.
- C++11—newest and mostly-unadopted version of the C++ language, it’s almost a distinct tool in its own right in how much support it can provide to a new project. Asynchronous or parallel code that leapfrogged across different functions are suddenly put into neat order with functional-style lambda closures, windy templated types suddenly become a short
auto, and who doesn’t love
- libc++—not to repeat myself, but the libraries in C++11 are amazing. Finally, we have threads and timers and smart pointers and
- Eigen—excellent vector math library used to represent my geometric data and transformations. I would use lightweight wrappers around some classes, while other times I just used typedef to bring them into my code.
- PixelToaster—great floating-point, system-native framebuffer library I use for most of my rendering projects.
Here are some screenshots, where I vary the radius of the disk light used to illuminate the dragon:
Trayrace was also written with minimalism in mind; the goal was to get pretty results as quickly as possible, then engineer code as necessary. Each feature added would flesh out subsystems that were weak or nonexistent (I didn’t even have transformations for weeks after starting the project), so that all the code would be “battle-tested” by use as soon as it’s written. This sort of thing happens a lot when you don’t have time to write unit tests.