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.
-
Note:
raycheck.py
compares your output to the reference solution, and as such requires access to the reference solution binary. It should work out of the box on Linux machines (and on the GDC machines, through SSH, if you are using a different operating system). It may also be possible to run raycheck on other operating systems, if you copy the reference binary into theray/
folder and rename itray-solution
. Note, though, that the script invokes several Linux command-line tools and you may need to make further modification (especially on Windows) to get the script to run. You may find it easiest to run raycheck.py over SSH once you are ready to test and submit your code. -
If
raycheck.py
does not work for you on the GDC machines due to Python package errors, try first running the following:python3 -m pip install --user colorama imageio
.
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
-
Download and install Microsoft Visual Studio (with C++ Compiler) and CMake.
-
Clone or download VCPKG
-
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
- 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
- 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:
- Variable Name: VCPKG_ROOT
- Value: the path to your VCPKG folder.
- 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:
- Where is the source code: /path/to/fltk
- Where to build the binaries: /path/to/fltk/build
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:
- Variable Name: FLTK_DIR
- Value: the /path/to/fltk/build
- You are now ready to compile the starter code. Open CMake. Set the paths for the starter code:
- Where is the source code: /path/to/ray
- Where to build the binaries: /path/to/ray/build
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:
- you will need to click on “ray” in the Solution Explorer and right-click->"set as startup project” if you want to debug the code from within Visual Studio.
- you can change between Debug and Release builds using the drop-down menu at the top of MSVC.
- to add new source files to the build, put them in the src folder, and run Configure and Generate again in CMake. Don’t add them using MSVC’s built-in GUI.
- to set the command-line arguments during debugging, right click on “ray” in the Solution Explorer and click “Properties”. Under “Debugging”, change the “Command Arguments”. Note that there are separate command-line argument for Release and Debug mode and you will need to set both.
- to check that your project is properly configured for grading, delete the entire “build” folder, and repeat all parts of step 7 above. Check that everything still compiles and runs.
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:
libfltk1.3-dev
libpng-dev
libjpeg-dev
libglew-dev
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:
- Your name;
- An explanation of any required features that you know are not working completely correctly, but would like to have considered for partial credit;
- 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
-
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 usesancheck.py
to identify some (but not all) potential problems with your submission. -
Do not include output
.png
s, core dumps, or other large extraneous files in your submission. -
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. -
During grading, the executable is built with
cmake -DCMAKE_BUILD_TYPE=Release
rather than the barecmake
, 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. -
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.