HW6: Raytracer

Due Sunday 2/28 @ 4:00pm.

Overview

In its current form, this assignment is extra credit. Your score (as a percentage) will be multiplied by 50% and then multiplied again by the maximum number of points that you lost on any one assignment.

To do the assignment, first download all the code below. Read over it all and work out the overall structure. Then fill in TODO comments. I'll post further instructions too, but I'm always happy to answer questions if you post to Piazza.

For each individual TODO comment in the starter code, you have the option of either filling it in yourself or emailing me to get the solution. You will not receive credit for TODOs for which I provide the answer.

In the end, you should be able to produce renders like these. The first one took 17 minutes to render; the second took 6 hours (since the sphere has so many triangles in it). Both images are 450x300. Consider that the render time for a brute-force raytracer like ours generally scales linearly with the product of the number of pixels, the number of triangles, and the number of lights.

Where & What to Hand In

Submit your work through Canvas. Hand in your copies of all the files listed below under “Starter Code” or “Recycled Code”. In addition, submit a PDF that shows at least one render whose shortest side is at least 100 pixels.

Code

Starter Code

Download the starter code and fill in the blanks.

Recycled Code

Please download these files and fill in the TODO comments based on your previous work.

Helper Code

Download new copies of the helper code, but don't modify them.

Tasks

    0. Recycled Code

    Fill in the TODO comments in each of these files by copying them over from your previous work. This does not count toward your score, and you're welcome to just ask me for solution files.

    1. meshes.py — Keep in mind that your meshes should produce vertices in homogeneous coordinates. You may wish to add shapes from our_shapes.py.
    2. transforms.py
    3. camera.py

    1. Test Scene

    1. main.py (0 TODOs) — Look over the code and take note of how it works. You can set the RENDER_WITH_MAYAVI flag to preview your scene in Mayavi. (Note that the zoom level / field of view may not match between Mayavi and your raytracer, but the camera pose should.)
    2. scene.py (1 TODO) — The starter code produces something very similar to the second scene above, which includes several lights and a sphere, and takes forever to render. (Specularity is a little different in the image.) Simplify the scene so that you can test your work more easily.

    2. Appearance

    Read both of the following files completely before filling in any of the TODOs. It's important to understand the distinction between the light falling on a particular position (and the direction of that light) versus the appearance of a surface at that position. Both files have loads of explanatory comments.

    1. lighting.py (6 TODOs) — This file defines an abstract base class Light and four subclasses: AmbientLight, PointLight, SpotLight, and ParallelLight.

      Take the time to read the big comment at the top of the file. It contains standard definitions for terms like “color” that are used throughout the assignment (especially in surface.py and raytracer.py).

      Each Light subclass has three public methods — ambiAt(), diffAt(), and specAt() — that define the color of the illumination that the light provides at a given point in space. Each subclass overloads one or more of these methods to provide its own particular lighting behavior.

    2. surface.py (5 TODOs) — This file defines the class Surface, which represents the appearance properties of the surface of an object. The appearance of an object depends on properties of the surface, the lights in the scene, the surrounding environment, and the position of the viewer.

      Fill in the reflect() function, then ambiAppearance(), diffAppearance(), and specAppearance(). Finally, fill in phongAppearance().

    3. Raytracer

    There are 8 TODOs in raytracer.py. Before you start, read over the entire file. There are some helper functions at the bottom that are used in the starter code. I'd suggest filling in the TODOs in the following order:

    1. renderRaster() (one TODO, though it involves calling the functions below, which you won't have filled in yet).
    2. makeViewVectors() (2 TODOs).
    3. triangleIntersect() (one big TODO).
    4. closestIntersection() (one big TODO).
    5. isBlocked() (one big TODO, but it's very similar to closestIntersection()).
    6. trace() (two little TODOs).

    Rubric

    This assignment is worth 20 points.

    CriterionPoints
    All files submitted, including PDF.1
    Recycled code, main program, and test scene.1
    lighting.py4
    surface.py5
    raytracer.renderRaster()1
    raytracer.makeViewVectors()1
    raytracer.triangleIntersect()2
    raytracer.closestIntersection()2
    raytracer.isBlocked()1
    raytracer.trace()2
    Total20