Code

Image

darts is a minimalistic skeleton for a Monte Carlo ray tracer, written in C++17. The name is an acronym for The Dartmouth Academic Ray Tracer Skeleton while also being a nod to the random dart-throwing-like process involved in Monte Carlo ray tracing. It runs on recent versions of Windows, Linux, and macOS and provides the foundation for the programming assignments we'll be doing in this class.

Design philosophy

The primary goal of darts is educational. As such, its design aims to balance several educational objectives

  • minimize "time to first pixel" – allowing you to start producing images quickly
  • don't provide many rendering features "out of the box", instead allow you to learn by implementing these yourself while steering you towards a modern full-featured ray tracer design
  • keep the core rendering-related code base small but extensible, while relying on a few, self-contained libraries for supporting code
  • keep the build system simple and reliable across major platforms

You can think of darts, and the accompanying assignments, as filling the gap between the simplicity of Peter Shirley's Ray Tracing in One Weekend series of books, and the complexity and completeness of more sophisticated research-oriented renderers like PBRT or Mitsuba.

The assignments are designed to help you explore and extend the darts code, while simultaneously progressing through the Shirley books and towards the PBR book. In the first few assignments, you will fill in empty methods left in the starter code, and test them using the tools provided with each assignment. In latter assignments, you will need to figure out what functions and classes you will need to add to the code to accomplish the tasks.

While darts cannot (yet) produce images, after stepping through the assignments you will steadily add features that allow you to render images like the ones below, with the photorealistic lighting characteristic of ray tracing:

Image
Image
Image
Image
Image
Image
Image
Image
Image
Image

Features

Darts provides many features that are tedious to implement from scratch, including:

  • A JSON-based scene file loader
  • A nice command-line interface with option parsing, and a text-based progress bar for long operations
  • Basic color/vector/matrix/ray/bounding box classes
  • A high-quality pseudorandom number generator
  • Support for loading and saving images in a variety of formats (.png, .jpg, .exr, .hdr, etc.)
  • Support for loading Wavefront OBJ files

Code organization

The codebase has the following high-level structure:

DirectoryDescription
include/dartsContains the header files for the core classes, algorithms and data structures of darts
src/The core C++ source files, as well as most added files will go here
scenes/Example scenes and test datasets to validate your implementation
reports/The skeletons for webpage reports for each of the assignments
documentation/The source and configuration files for this course website, and the Doxygen documentation
CMakeLists.txtThe main CMake build file which specifies how to compile and link the code
cmake/Additional CMake files (you likely won't have to look at this)

Darts uses modern CMake, and the CPM.cmake package manager for a particularly clean and simple build set up. At configuration time, the CMake build system automatically downloads (from other GitHub repositories) several open source libraries, including:

DependencyDescription
cli11Command line parser for C++11
filesystemA tiny self-contained library for manipulating paths on various platforms
flipA tool for visualizing and communicating errors in rendered images
fmtA modern formatting library/replacement for C's printf and C++ streams
linalgSingle header C++11 vector math library inspired by the syntax of shading languages
nanothreadA minimal thread pool library for task parallelism
nlohmann-jsonA JSON parsing library for modern C++
pcg32A tiny self-contained pseudorandom number generator
spdlogFast C++ logging library
stb_imageHeader-only public domain library for image loading and saving.
tinyexrTiny OpenEXR image loader/saver library
tinyobjloaderTiny but powerful single file wavefront obj loader

Darts organizes the above libraries and functionality into a few core modules:

ModuleDescription
MathFixed-size vectors/colors, matrices, transforms, rays, orthonormal bases, and other mathy things.
UtilitiesPrinting utilities, command-line parsing, and other conveniences.
ParserJSON serialization/deserialization, the darts plugin factory, and scene parser.
RandomRandom number generation, generation of points and directions, Monte Carlo utilities.
ParallelConstructs to aid task-based parallelism.

Initially darts does very little beyond accepting some command line parameters and immediately returning. During the course of the term you will extend dart's functionality by implementing various plugins. These include:

PluginDescription
SurfacesGeometric surfaces in the scene which can be intersected by rays.
MaterialsBSDFs and phase functions attached to Surfaces to define how they interact with light.
TexturesProcedural and raster 2D and 3D textures used to drive spatial variation of certain Material parameters.
IntegratorsAlgorithms that solve the rendering equation in different ways.
SamplersGenerate the random number stream used by Integrators to perform Monte Carlo integration.
Participating mediaDefine the behavior of light within the volumes between surfaces.

Next steps

Take a look at our Getting started guide before working through our programming Assignments. You may also optionally want to step through our Discovery cluster tutorial, which shows how to build and run darts on Dartmouth's discovery cluster to render images on many computers at once.