Project 2: Ray Tracing
Overview
In this assignment you will implement a basic raytracer. To allow you
to focus on the nuts and bolts of the actual ray tracing, we provide you
with a host of data structures for managing the ray traced objects, linear
algebraic functions (vector and matrix objects and operations), a function
for loading scene graph files into a prescribed node tree structure, a BMP
image file importer/exporter (for images and textures, etc), and a couple
of supporting data structures for lights, materials, etc. This code
is available in /cs/cs155/proj2/src/ on the graphics machines.
The input format for the raytracer is a RAY file, which has a full
specification available here.
You can find UML for the skeleton code here; this may be useful to help acquaint you with the
codebase. Additionally, there is an explanation of some of the aspects
of the code that do not directly affect your implementation of the
required material (such as parsing or the OpenGL rendering) here - this information is not necessary for
any of the required functionality, but may become useful as you extend
your raytracer to do bigger and better things.
A full implementation of this raytracer is available for testing your
RAY files (binary only). It is available at /cs/cs155/proj2/rt and has a
manual here, which explains how to use it and
how its features were implemented.
A gallery of images created by previous semesters of this class is
maintained here for motivation.
What You Have to Do
The assignment is worth 25 points. The following is a list of features
that you may implement. The number in parentheses corresponds to how many
points it is worth. Options in bold are mandatory.
- (6) Basic Raycasting - this step will allow you to render
the most basic of
images. Modify RayFile::raytrace() to generate rays from the
camera's position through each pixel of the image, intersect these
rays with the scene hierarchy, and call RayFile::getColor() if an
intersection is found. (For testing purposes let RayFile::getColor() return
white.) Modify Group::intersect(), Sphere::intersect(),
and Triangle::intersect() to compute the closest intersection of the object
with a ray,
ignoring group transformations (for now). When this is done, you should
be able to render images with white circles and triangles.
- (1) Basic Material Properties - to get colors without lighting,
modify RayFile::getColor() to calculate color using a material's ambient
and emissive properties.
- (1) Diffuse Lighting - implement
DirectionalLight::getDiffuse(), PointLight::getDifuse() and
SpotLight::getDiffuse() to calculate the diffuse color contribution of a
light at an intersection point. Modify RayFile::getColor() to call these
functions.
- (2) Specular Lighting - implement
DirectionalLight::getSpecular(), PointLight::getSpecular() and
SpotLight::getSpecular() to calculate the specular color contribution of a
light at an intersection point. Modify RayFile::getColor() to call these
functions.
- (1) Basic Shadows - implement DirectionalLight::getShadow(),
PointLight::getShadow() and SpotLight::getShadow() to determine if an
intersection point is in shadow with respect to a light. Modify
- (1) Transformations - modify Group::intersect() to take into
account its local transformation. Use the transform to convert the ray
into local coordinates, find the closest intersection, and use the
transform to convert the intersection back into global coordinates.
- (1) Reflection - modify RayFile::getColor() to recursively
cast reflected rays at the point of intersection and then use this value
in the color calculation.
- (1) Transmission - modify RayFile::getColor() to recursively
cast transmitted rays at the point of intersection and then use this value
in the color calculation. For now, ignore the refractive index.
- (1) Snell's Law - modify RayFile::getColor() to use the index of
refraction and Snell's Law to calculate the correct direction of
transmitted rays through thick shapes (Spheres). Thin shapes (Triangles)
should be unchanged.
- (2) Texture Mapping - modify Triangle::intersect() and
Sphere::intersect() to calculate texture coordinates at the point of
intersection, and modify RayFile::getColor() to use the texture
coordinates in the color calculation. Use bilinear interpolation for the
texture samples.
- (1) Jittering - implement a jittered supersampling technique to reduce
aliasing by casting multiple rays per pixel, randomly jittered about the
center of the pixel, and averaging the colors.
- (1) Soft Shadows - treat each point and spot light as having some
finite volume and cast multiple rays for shadow tests. Modify
PointLight::getShadow() and SpotLight::getShadow() to return doubles
instead of booleans, and to return the average of these multiple shadow
tests. If you want, you can modify DirectionalLight:getShadow() to behave
similarly, but because a directional light doesn't have a position, good
results can be difficult to get.
- (1) Fuzzy Reflection and Transmission - for each reflection or
transmission ray, cast multiple randomly jittered rays and average their
results, to simulate the rough nature of real materials.
- (1) Box Primitive - add support for a Box primitive (get skeleton code
from /cs/cs155/proj2/src/extras/) with texture mapping
- (1) Cylinder Primitive - add support for a Cylinder primitive (get
skeleton code from /cs/cs155/proj2/src/extras/) with texture mapping
- (1) Cone Primitive - add support for a Cone primitive (get skeleton
code from /cs/cs155/proj2/src/extras/) with texture mapping
- (2) Torus Primitive - add support for a Torus primitive (get
skeleton code from /cs/cs155/proj2/src/extras/) with texture mapping.
Hard!
- (1) Color Projection - modify DirectionalLight::getShadow(),
PointLight::getShadow() and SpotLight::getShadow() to return Color3d's,
which represent the color of the shadow. If an intersection point is
occluded from the light by a transparent object(s), some light should
still hit the intersection point, just of a slightly different color.
Modify RayFile::getColor() to take the shadow color into account when
calculating the color of the intersection point.
- (2) Procedural Textures - add support for 2D and / or 3D procedural
textures. Check out this
website for information on Perlin Noise.
- (1) Bump Mapping - add support for bump mapping for all supported
primitives
- (1) Transparency / Cutout Mapping - add support for transparency and
cutout mapping for all supported primitives
- (1) Depth of Field - implement depth of field camera effects
- (1) Fisheye Lens - implement fisheye lens camera effects
- (2) Realistic Lens - simulate realistic camera lens behavior. You
must implement the procedure in this SIGGRAPH paper.
- (2) Bounding Boxes - speed up raytracing by implementing bounding
boxes. Create a bounding box class and modify each object so it knows
about its own bounding box for intersection testing.
- (2) Constructive Solid Geometry - add support for constructive solid
geometry for all the primitives you've implemented. Provide union, merge,
intersect, difference, and inverse operators.
- (?) Impress us with something we hadn't considered
By implementing all the required features, you get 17 points. There are
many ways to get more points:
- (?) Implement optional features
- (1) Submit a non-trivial model and image for the art contest
- (1) Submit an MPEG movie made from multiple raytraced images (see the
Movie FAQ for more information)
For images or movies that you submit, you also have to submit the
sequence of commands used to created them, otherwise they will not be
considered valid.
It is possible to get more than 25 points. However, after 25 points,
each point is divided by 2, and after 27 points, each point is divided by
4.
Deadlines
This project is due on Monday, October 28, 2003 at 11:59 PM. In addition,
you must demonstrate 8 points of work including Basic Raytracing in class on
Tuesday, October 8 and an additional 8 points on
Tuesday, October 15.
You have two late days you can use for this assignment. If you did not
use a late day for the image processing project,
that late day may also be applied to this project.
If you acquired an additional late day on project 1 that may be applied
to this project as well.
Failure to meet any deadline costs 2 point per day.
Getting Started
You should use the code available at /cs/cs155/proj2/src, on the
graphics machines, as a starting point for your assignment. We provide
you with the following files. Files in bold are recommended files to
modify to implement the required functionality. Of course, there are
multiple ways to implement any of these features, so your mileage may
vary.
-
camera.[cpp/h]: camera object handles movement commands, sets up OpenGL
matrices, viewpoint for raytracing.
-
common.h: useful definitions and a few common includes
-
control.[cpp/h]: handles OpenGL menu, mouse and keyboard input
-
directionallight.[cpp/h]: directional light object, inherits from
Light.
-
geometry.[icc/h]: geometry library code, with Point, Vector, Color,
TexCoord, Matrix, and Ray template classes, along with typedefs for common
instances of each (eg. a Point3d is a three dimensional point storing
doubles)
-
group.[cpp/h]: object to group multiple shapegroups together and
apply a local transformation. inherits from ShapeGroup.
-
image.[cpp/h]: image class, supports reading and writing PPMs and BMPs, as
well as a variety of OpenGL calls. Same as from project 1.
-
intersection.h: intersection structure to store all the relevant
information about a ray-shape intersection.
-
light.[cpp/h]: abstract light class which provides the basic interface for
all the supported light types
-
macro.[cpp/h]: macro class for pasting multiple instances of some geometry
in the scene hierarchy.
-
macroinstance.[cpp/h]: an instance of a macro, pasted into the scene
hierarchy. inherits from ShapeGroup.
-
main.[cpp/h]: sets up the OpenGL context and handles displaying and
resizing the image window. Also handles non-interactive mode
-
material.[cpp/h]: class to store all relevant material properties
about a surface. Features like texture mapping will involve this class.
-
parse.[cpp/h]: utility functions to handle reading text while ignoring
comments and flag parsing.
-
pointlight.[cpp/h]: point light object, inherits from Light.
-
rayfile.[cpp/h]: top-level class that stores the entire RAY structure,
including the scene hierarchy, and prefoms raytracing.
-
rayfile_render.cpp: two functions are defined here -
RayFile::raytrace() and RayFlile::getColor(). This is where most of your
initial work needs to be done.
-
rayfileinstance.[cpp/h]: class to handle importing and pasting the
contents of one rayfile into another. Inherits from ShapeGroup.
-
roots.[cpp/h]: utility second, third and fourth order polynomial root
finding functions. Useful for intersection testing.
-
rt.[dsp/dsw]: Visual C++ 6.0 project and workspace files, if you'd rather
do the project on a windows box. Remember though that your final code
will be graded on the graphics machines.
-
shape.[cpp/h]: abstract Shape class to unify the interface for the
supported primitives. Inherits from ShapeGroup.
-
shapegroup.[cpp/h]: abstract ShapeGroup class that unifies the interfaces
of shapes and groups of shapes, allowing the scene hierarchy to be
recursively defined.
-
sphere.[cpp/h]: class representing a sphere primitive in the scene
hierarchy. Inherits from Shape.
-
spotlight.[cpp/h]: spot light object, inherits from Light.
-
triangle.[cpp/h]: class representing a triangle primitive in the
scene hierarchy. Inherits from Shape.
-
win32.[cpp/h]: necessary code to keep the project running smoothly on
windows machines.
-
Makefile: GNU makefile with makedepend support
The Makefile supports a few operations...make will build
all necessary objects and the executable. make clean will
remove the executable and all object files. make depend will
create header dependency information. make fresh is the same
as make clean ; make depend ; make.
What to Submit
You should submit:
-
the complete source code for your version of rt,
-
a makefile,
-
your .ray and .bmp for your submission to the art contest (optional),
-
the .mpeg movie for the movie feature (optional), and
-
a writeup.
The writeup should be a HTML document called assignment2.html
which may include other documents or pictures. It should be brief,
describing what you have implemented, what works and what doesn't, how you
created the art contest images and/or movies, and any relevant
instructions on how to run your interface. Make sure that any linked
images/movies are world readable.
Make sure the source code compiles on the graphics machines.
If it doesn't, you will be in a world of hurt.
Remember our standing late policy and collaboration policy.
Notes
-
See the Project 2 FAQ for help.
-
Visit the POVRAY site, home of a popular freeware raytracer. Check out the
links to the still
competitions and animated competitions for
inspiration..
-
For information about the barycentric coordinate triangle intersection
test, check out Ray Tracing News issue RTNv5n3 which focuses
on various polygon/ray intersection methods.
-
Stay tuned for more notes
Links
Last Update: 7/17/02