Assignment 1: Ray Tracer


Overview

In this project, which is broken up into two milestones, you will build a program that will generate ray-traced images of complex scenes using the Whitted illumination model. You will implement the core ray-tracing algorithm with basic shading, including computing ray-triangle intersections and casting secondary reflection, refraction, and shadow rays, texture mapping, and build an acceleration data structure to dramatically improve the performance of the ray-object intersection tests.

Getting Started

Starter Code

(Note: these test scenes are for both project milestones. Some scenes will not produce sensible output if you have only completed Milestone I.)

We have provided as starter code a C++ skeleton that includes a GUI for the ray tracer, extensive support code for parsing scene files, reading and writing images, etc, and tools to help you debug your code. To install the starter code, unzip the files and follow the instructions below. The executable resulting from a successful build opens a GUI but doesn’t trace any rays yet; clicking on a point on the screen casts a single ray where the pixels are shaded only by the diffuse terms of the material at the ray intersections, and this only for non-polygon-mesh objects. For polygon meshes, it doesn’t even compute intersections.

This skeleton consists of a very large collection of files and object-oriented C++ code. Fortunately, you only need to work directly with a subset of it. However, you will probably want to spend a bit of time getting familiar with the layout and class hierarchy at first, so that when you code you know what classes and methods are available for your use. Basic linear algebra operations are provided by the OpenGL Mathematics (glm) library. Documentation for the library (which unfortunately leaves something to be desired) can be found at https://glm.g-truc.net/0.9.8/api/index.html.

To get started, look at comments about where to put your code in RayTracer.cpp, trimesh.cpp, light.cpp, and material.cpp. The starting point for where ray tracing begins, and where you will be needing to add a lot of functionality, is in the RayTracer.cpp file. This is a good place to start studying to explore what methods get called and what they do. In addition, the ray tracer features a debugging window that allows you to see individual rays bouncing around the scene. This window provides a lot of visual feedback that can be enormously useful when debugging your application. A more detailed explanation of how to use the debugging window is available online at Don Fussell’s course page.

The starter code can run in both text mode and gui mode. Running without any arguments will execute the program in the gui mode. For usage see ray -h.

Platform and Dependencies

We have tested the starter code on Linux (Ubuntu 16.04), OS X High Sierra, and Windows 10 (MSVC 2019). The reference binaries are built on these machines and may not run on other systems.

The starter code depends on FLTK, glm and OpenGL to compile/run. UTCS basement machines already have them installed. For your own system you may need to install them through the corresponding package manager, such as Apt (Debian) or Homebrew (macOS).

It is your responsibility to write code that compiles using the provided build system in a platform-independent way, and to work with the TA to resolve any build issues with your submission. We have provided two scripts to help you do ensure you turn in a gradeable solution. First, raycheck.py will attempt to run it on the provided examples. Your binary should terminate within 180 seconds, for all scenes except those involving large triangle meshes.

Second, the sancheck.py script will identify some common problems with how you’ve packaged your source code for submission (see Details of Grading below).

These scripts will help you identify some, but not all, problems. It is your responsibility to ensure you submit complete and correct code and functioning build scripts. The TAs can help you check your code for build problems, if you ask for help prior to the deadline.

Configuration on Windows

  1. Download and install Microsoft Visual Studio (with C++ Compiler) and CMake.

  2. Clone or download VCPKG

  3. Follow the install instruction for VCPKG. In particular you need to perform the following steps:

3.1. Open up a command prompt in administrator mode (click the Windows icon, type “cmd”, then right-click on “Command Prompt” and click “Run as administrator”).

3.2. Navigate to the folder where you extracted VCPKG.

3.3. Run the following commands:

.\bootstrap-vcpkg.bat
.\vcpkg integrate install
  1. Install the project dependencies:
.\vcpkg install glew:x64-windows
.\vcpkg install glm:x64-windows
.\vcpkg install zlib:x64-windows
.\vcpkg install libjpeg-turbo:x64-windows
.\vcpkg install libpng:x64-windows
  1. Add VCPKG_ROOT to your environment variables. Click the Windows icon, type “env”, and click on “Edit the system environment variables”. Click the “Environment Variables” button. Under “User variables,” click “New…” and add:
  1. You will also need to install FLTK. Unfortunately, the VCPKG package for FLTK is buggy, and you will need to build FLTK from source. Clone or download FLTK from GitHub.

6.1. Open CMake. Set the paths for FLTK:

6.2. Hit “Configure”. Use the default native compilers, and pick x64 (not x86) as the target platform. You should not get any errors. Keep hitting “Configure” until the red lines are all white.

6.3. Hit “Generate”.

6.4. Hit “Open Project”. This will launch Visual Studio with your project open.

6.5. Compile FLTK. You will want to compile the code in both Debug and Release configuration, if you want to be able to run your own ray tracing code in Debug mode.

6.6. Add FLTK_DIR to your environment variables. Click the Windows icon, type “env”, and click on “Edit the system environment variables”. Click the “Environment Variables” button. Under “User variables,” click “New…” and add:

  1. You are now ready to compile the starter code. Open CMake. Set the paths for the starter code:

7.1. Hit “Configure”. Use the default native compilers, and pick x64 (not x86) as the target platform. You should not get any errors. Keep hitting “Configure” until the red lines are all white.

7.2. Hit “Generate”.

7.3. Hit “Open Project”. This will launch Visual Studio with your project open.

Additional Tips:

Configuration Instructions (OS X)

You will need to install the X-code command line tools, as well as the libraries on which the ray tracer depends. You can get the libraries using Homebrew:

brew install fltk glm glew glfw jpeg libpng zlib

Configuration Instrutions (Linux)

You will need to install the project dependencies using your distribution’s package manager (i.e. apt on Ubuntu). For distributions based on Debian, the following packages should suffice:

You will also need to install CMake and the g++ toolchain (if not already present), as well as OpenGL. (One easy way to get the OpenGL libraries on Ubuntu is to install freeglut3-dev).

Build Instructions (Linux and OS X)

From the project root directory, the following commands will create a directory named “build” and build the starter code within this directory.

mkdir build
cd build
cmake ..
make -j8

When finished, the binary called ray will be placed in the build/bin/ directory.

Submission Instructions

All submissions must be uploaded to Canvas by the project due date and time. In exceptional cases where Canvas is not working, you may turn in the assignment by emailing the TA a Dropbox link, handing him a USB stick, etc, but there will be no exceptions to the project due date–late submissions will be penalize per the syllabus late policy.

Submit your project as a single .tgz or .zip file. In addition to your complete source code, the archive should include a README file containing, at minimum:

  1. Your name;
  2. An explanation of any required features that you know are not working completely correctly, but would like to have considered for partial credit;
  3. Anything the milestone-specific specs below ask you to include.

Tip: after uploading your files to Canvas, it is not a bad idea to download them onto a different computer and check that it still compiles and runs, in case you accidentally leave out some important files from the .tgz. It is also wise to try to upload to Canvas well ahead of the final deadline: again, there will be no exceptions to the lateness policy, not even for technical difficulties.

(Important) Technical Details of Grading

  1. The submitted package should include everything needed to build your project, including CMake configuration files like CMakeLists.txt. We will dock points on submissions that do not build correctly “out of the box.” Please use sancheck.py to identify some (but not all) potential problems with your submission.

  2. Do not include output .pngs, core dumps, or other large extraneous files in your submission.

  3. The ray tracer is graded using the COMMAND LINE UI (with the -r 5 recursion option). Please make sure the command line UI produces the same image as your GUI version does.

  4. During grading, the executable is built with cmake -DCMAKE_BUILD_TYPE=Release rather than the bare cmake, which enables optimizations. Please make sure the ray tracer does not segfault and still generates correct images with this build type. Some bugs are invisible in Debug builds and only appear when the code is compiled in Release mode.

  5. When grading, we will terminate programs that take longer than 180 seconds (in Release build). 300 seconds should be ample unless your implementation is egregiously inefficient. Please make sure your code is not too slow to finish complicated scenes like dragon.ray within the time limit. (trimesh*.ray scenes are exceptions. These are very large scenes and may not finish in 300 seconds).

Required Features

Additional Technical Comments

Remote Rendering

Unfortunately, due to security reasons indirect GLX rendering was disabled a while ago and there is no way to re-enable it on the public UT CS machines. You must physically sit in the labs to run the GUI version of your programs on those machines (the command line UI version still works through SSH).

Adding New Files to the Build

In most cases you do not need to modify the build system manually to add new files. The build system will automatically add source files under the following directories to your project.

src/
src/fileio/
src/parser/
src/scene/
src/SceneObjects
src/ui/

However, since EVERY source file in these directories will be added to the project to build, it is not a good practice to add random files, say a “HelloWorld.cpp”, under these directories, which will cause linking errors due to multiple main functions.

On the other hand, files outside of these directories will NOT be added to the project automatically. For example, if you created a directory called src/kdtree/, and added your kd-tree implementation under this directory, these kd-tree source files would NOT be built until you modify the CMakeLists.txt as well.

Tools that help you read the code

This starter code includes many features and lots of files, and usually it is troublesome to jump over these files. For these cases, a source indexer helps you a lot.

cscope and rtags are two recommended ones. Cscope is included in most distributions, while rtags requires build from source. However rtags understands C++ more precisely because it uses the Clang compiler front-end.

Coding Style

The starter code is formatted with this clang-format file.

Compiler Options

C++17 is required to compile the code and is enabled by default.

glm

The build system will clone the 0.9.9.7 version from the official repository if glm is not present or the system glm version is lower than 0.9.9.7, because old versions of glm do not work with recent GCC distributions.

Acknowledgement

This starter code is modified from a codebase originally developed by Don Fussell.