Motivation

In this assignment, you will add two features into your raytracer:

  • Refraction through spheres.
  • Polygonal smoothing using shared vertices of faces in a model.

Data Formats

The driver files used for this assignment are the same as in previous assignments with the following modifications:

  • Spheres have one additional field - their refractive index - that is an additional number at the end of a sphere line. Spheres are now sphere x y z r Ka_r Ka_g Ka_b Kd_r Kd_g Kd_b Ks_r Ks_g Ks_b Kr_r Kr_g Kr_b Ni where Ni is the refractive index. A refractive index of 0 corresponds to no refraction, and in that case rays should not be passed through the sphere. In any other case, the transparency of the object (what proportion of the light passes through the object) should be 1 minus Kr.
  • Model lines in a driver file will have an additional field called 'cutoffAngle' - corresponding to the angle cutoff for smoothing. If this value is 45, the normal for a face's vertex will be calculated as the average of the adjoining faces with angle between their "true" normals and this face's "true" normal less than 45. A value of 0 corresponds to no smoothing. Besides, we won't ask you to apply refraction through polygons, that means the 'Ni' in mtllib file won't be used.

A few notes on the implementation of smoothing:

  • You will need to know the beta and gamma values when you calculate the smoothed normal for a point. As such, it may be helpful to have your collision methods return the calculated normal vector.
  • Ensure that all calculated normal vectors are normalized.
  • You will need to build a relational data structure of some sort to record which faces share any given vertex and consequently how to average the face normals at that vertex. This can get complicated, you have a SageMath notebook to fall back upon as one example of how to correctly manage this data and compute averaged normals at vertices and also to interpolate across triangle faces.

A few notes on the implementation of refraction:

  • If the transparency and reflectivity of an object sum to more than one, the object may appear brighter than intended.
  • Whenever you shoot a ray that collides with a refractive object, you will refract through it and if it is reflective also reflect off it. These values are combined into the color according to the object's transparency and reflectivity. If in doubt about details model your codes behavior after the refraction and reflection for spheres SageMath notebook.
  • The refractive index outside of any objects is 1.0.
  • When a ray refracts through an object, the recursion level should decrease.
  • There are multiple ways to implement refraction through objects. One method will be presented in class, but you are welcome to implement it in whatever way you wish, as long as it results in similar results
  • For this assignment, do not worry about having objects that intersect. This means that if you have a large refractive sphere, you do not have to worry about the fact that it could have another object inside of it that rays could interact with.
  • Getting an intuitive sense of what refractive objects should look like is hard. It's recommended that you focus your testing on scenes where you can work out and predict the expected result.

A few notes on speeding up your program:

  • Common slowdowns come from doing work multiple times unecessarily - for example, if you compute the average vertex normal across all faces at a vertex every time you calculate the smoothed normal, your program will run slowly. Instead, calculate the vertex normals for each vertex once at the beginning of your program, then interpolate between them using beta and gamma. One way to determine what is causing timing issues in your program is to use a profiler.
  • Allocating extra memory can result in slowdowns. Ideally, your program would allocate memory at the start, then each pixel would allocate memory only for new rays. Implementing this can be difficult if aren't experienced with memory allocation strategies.

Task

This assignment intentionally builds on the previous assignment. It is recommended that as you complete this assignment, you simplify and improve your code where possible to make these and upcoming changes easier.

In this assignment you will construct three scenes: they are described in the three driver files given to you Your code will be tested with one additional driver file, for a total of four files. If your code takes longer than 15 minutes to run on any of these driver files, submit with them a .ppm file of the result of the driver and include in your readme the maximum resolution that lets that driver render in under 15 minutes. All driver files should be able to be rendered in under 15 minutes.

One additional thing to note is that the behavior of your raytracer does not have to exactly match the behavior of the given images. As long as it is clear that your raytracer has physically realistic output, matching what is expected for a driver file, you will recieve credit. There are many similar ways to implement refraction (with slightly different outputs), all of which are valid solutions for this assignment

​ ​
  • Scene 0 - the scene described in driver00.txt. It does not use any of the features of this assignment, but demonstrates complex reflection. Expected output is below.
    driver00.png
  • Scene 1 - the scene described in driver01.txt. It demonstrates the effect of smoothing. Expected output is below.
    driver01.png
  • Scene 2 - the scene described in driver02.txt. It demonstrates the effect of refraction and is inspired by variants of the classic Cornell Box. Expected output is below.
    driver02.png
  • Scene 3 - The GTAs will be providing scene 3 which will be used for grading. It may include any features from this or the previous assignment.

In all cases the camera view, lighting, and object placement should result in a well rendered final image. The image should be written in PPM format as described in P2.

Submission

Submit a tar file via the CANVAS assignment page that includes: ​ ​

  • Your source files
  • Your driver files
  • Your model and material files
  • Libraries if you use any
  • A makefile if appropriate
  • README.txt file that explicitly contains (1) A command to ​ compile your program and (2) A command to execute it and (3) ​ a description of the maximum resolution that any driver files ​ should be rendered at if they take longer than 10 minutes to render.
  • .ppm output for any drivers that take longer than 15 minutes ​ to render.

If you are using C++, your executable should be named 'raytracer'. If your are using java, the main executable class should be named 'Raytracer'. Notice the change in case for the first letter between C++ and Java. It is necessary for this assignment to take exactly two arguments as described above.

​ ​ ​ ​