For this project you will implement a ray tracer. Besides the basic scene file
parser, you will have to implement everything on your own. We suggest using the
libgfx
libraries for the mathematical functions that you will need.
One way to write pixels to the screen buffer is to first create a large enough
buffer in memory, write to it as you perform raytracing, then create a texture map
(GL_TEXTURE_RECTANGLE_NV) and fill it by glTexImage2D, then render it
to screen or save it to a file.
You can create your own scenes to show off the raytracer in action; however, you
will have to implement a simple command-line interface and support a common scene
format so that we can test your code. The code to parse the Simple Scene
Description Format is provided for you (rt_parse.h/cpp
). A
simple example can be found here.
The (informal) grammar for the simple scene description format is as follows:
scene :: = background lights materials group background ::= Background { color Vec3f ambientLight Vec3f } lights ::= Lights { light * } light ::= Light { position Vec3f color Vec3f ( attenuation float float float ) ? } camera ::= Camera { eye Vec3f center Vec3f up Vec3f fovy float } materials ::= Materials { material * } material ::= Material { textureFilename string diffuseColor Vec3f specularColor Vec3f shininess float ( transparentColor Vec3f )? ( reflectiveColor Vec3f )? ( indexOfRefraction float )? } group ::= Group { object * } object ::= sphere | triangle | trimesh sphere ::= Sphere { materialIndex int center Vec3f radius float } triangle ::= Triangle { vertex0 Vec3f normal_vertex0 Vec3f materialIndex0 int s_t_tex_0 float float vertex1 Vec3f normal_vertex1 Vec3f materialIndex1 int s_t_tex_1 float float vertex2 Vec3f normal_vertex2 Vec3f materialIndex2 int s_t_tex_2 float float } trimesh ::= TriMesh { objfile file.obj materialIndex int } Vec3f ::= float float float
I(d) = | 1 |
ad2 + bd + c |
Your first step should be to create a backbuffer and setup OpenGL to display it. All other code you write will directly modify this buffer. You must implement the following features:
Make your ray tracer able to draw a sphere.
Make your ray tracer able to draw a single triangle.
Read a whole bunch of triangles from an OBJ file and ray trace them.
This will be really slow without a hierarchical bounding structure, so I suggest you start out by using a very low resolution model such as this 150 triangle bunny. You can use Qslim to simplify models.
Read image files and texture coordinates from OBJ files to add textures to your raytraced OBJ files. Use barycentric coordinates to calculate the texture coordinates at each pixel. You only need to be able to render triangle meshes (don't worry about quads or polygons with more points).
Support ambient, diffuse, and specular lighting in your renderer. Interpolate the normals of the vertices of the polygons to determine the normals at each pixel to be used for shading.
Add shadows by not illuminating surfaces by lights from which they are occluded.
Create a shiny surface and bounce rays off of it. To make sure the raytracer finishes in a reasonable amount of time, clamp the max bounces to 5.
Include a readme.txt file using this template. Make sure to describe any extra features your raytracer implements.
Use reasonably efficient and well-written code that can easily be graded.
Save a number of output pictures from the program to a directory labeled images
.
Include screenshots demonstrating all of the visible features of the
ray tracer (so shadows, textures, etc, but not bounding volumes). Also include one of the Simple Scene Description Format files in the main lab3 directory that you used to generate these images (it has to be different from test.ray!).
You can find the lab 3 starter code here. The submission guidelines remain the same as the previous labs. Make sure your project can be compiled by just going into the src directory and typing make.
Please include a copy of whatever models and textures you use when handing in your project as it makes life a lot easier to verify your features.