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.
- Scene 1 - the scene described in driver01.txt. It demonstrates
the effect of smoothing. Expected output is below.
- 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.
- 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.