Trayrace is a mini­mal Monte Carlo renderer, created with the help of Greg Turk at Geor­gia Tech as an inde­pen­dent study project for my senior year.

Trayrace short

Code avail­able at GitHub:

Trayrace was designed to (even­tu­ally) have the bells and whis­tles of an advanced phys­i­cally-based photo­re­al­is­tic renderer—like many render­ers, it’s based loosely on PBRT—but was imple­mented with uniquely little “from scratch” code, through judi­cious choice of off the shelf compo­nents:

  • Intel Embree—library that builds BVHs and traces rays. Its inter­face is very simple (though less so since I last visited it in summer 2011), extremely fast (it has a paral­lel build and the raytrac­ing uses SIMD heav­ily), and it’s also mostly self-contained, once you figure out the orga­ni­za­tion 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. Asyn­chro­nous or paral­lel code that leapfrogged across differ­ent func­tions are suddenly put into neat order with func­tional-style lambda closures, windy templated types suddenly become a short auto, and who doesn’t love emplace_back?
  • libc++—not to repeat myself, but the libraries in C++11 are amaz­ing. Finally, we have threads and timers and smart point­ers and <cstdint>.
  • Eigen—excel­lent vector math library used to repre­sent my geomet­ric data and trans­for­ma­tions. I would use light­weight wrap­pers around some classes, while other times I just used type­def to bring them into my code.
  • Pixel­Toaster—great float­ing-point, system-native frame­buffer library I use for most of my render­ing projects.

Here are some screen­shots, where I vary the radius of the disk light used to illu­mi­nate the dragon:
Screen Shot 2012-12-14 at 11.42.18 Screen Shot 2012-12-14 at 11.43.08

Trayrace was also writ­ten with mini­mal­ism in mind; the goal was to get pretty results as quickly as possi­ble, then engi­neer code as neces­sary. Each feature added would flesh out subsys­tems that were weak or nonex­is­tent (I didn’t even have trans­for­ma­tions for weeks after start­ing the project), so that all the code would be “battle-tested” by use as soon as it’s writ­ten. This sort of thing happens a lot when you don’t have time to write unit tests.