Trayrace is a min­i­mal Monte Car­lo ren­der­er, cre­at­ed 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­al­ly) have the bells and whis­tles of an advanced phys­i­cal­ly-based pho­to­re­al­is­tic renderer—like many ren­der­ers, it’s based loose­ly on PBRT—but was imple­ment­ed with unique­ly lit­tle “from scratch” code, through judi­cious choice of off the shelf components:

  • Intel Embree—library that builds BVHs and traces rays. Its inter­face is very sim­ple (though less so since I last vis­it­ed it in sum­mer 2011), extreme­ly fast (it has a par­al­lel build and the ray­trac­ing uses SIMD heav­i­ly), and it’s also most­ly self-con­tained, once you fig­ure out the orga­ni­za­tion of the source code.
  • C++11—newest and most­ly-unadopt­ed ver­sion of the C++ lan­guage, it’s almost a dis­tinct tool in its own right in how much sup­port it can pro­vide to a new project. Asyn­chro­nous or par­al­lel code that leapfrogged across dif­fer­ent func­tions are sud­den­ly put into neat order with func­tion­al-style lamb­da clo­sures, windy tem­plat­ed types sud­den­ly become a short auto, and who does­n’t love emplace_back?
  • libc++—not to repeat myself, but the libraries in C++11 are amaz­ing. Final­ly, we have threads and timers and smart point­ers and <cstdint>.
  • Eigen—excellent vec­tor math library used to rep­re­sent my geo­met­ric data and trans­for­ma­tions. I would use light­weight wrap­pers around some class­es, while oth­er times I just used type­def to bring them into my code.
  • Pix­el­Toast­er—great float­ing-point, sys­tem-native frame­buffer library I use for most of my ren­der­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 min­i­mal­ism in mind; the goal was to get pret­ty results as quick­ly as pos­si­ble, then engi­neer code as nec­es­sary. Each fea­ture added would flesh out sub­sys­tems that were weak or nonex­is­tent (I did­n’t even have trans­for­ma­tions for weeks after start­ing the project), so that all the code would be “bat­tle-test­ed” by use as soon as it’s writ­ten. This sort of thing hap­pens a lot when you don’t have time to write unit tests.