This session is to help you get started with the third project: a raytracer.
Starting the Project
Wow! You're about about to write part of a raytracer. Raytracers are often big programs. They're very much the compilers of the graphics world: they compile some sort of scene description into an array of colours. Fortunately, this raytracer is actually pretty small. The current project is less than 5000 lines of code. Furthermore, a lot of that is user interface overhead that you can safely ignore. In fact, to complete all the basic project requirements, you need only change one file!The first thing to do is download the skeleton project. Unpack it, and build it. Now run it. You get a window with two viewing panes. The left one shows you an OpenGL-rendered preview of the current scene. The right one will show you the final raytraced scene. Under the options menu, you'll be able to set a couple of important parameters to the raytracer, such as the maximum recursion depth and the size of the preview and raytrace panes. Changing the size of the raytrace pane can have a dramatic effect on tracing time. For big scenes, it might be useful to first try your raytracer with a really small output image to see that it appears to be working.
Run the skeleton application on "simple.out" in the scenes directory. What do you get? What does this tell you about the parts of the ray tracing that are already implemented? Also, be sure to try running the sample executable on the same scene, to get a n idea of what you're shooting for.
Converting VRML Files to Raytracer Files
At some point, it would be great to be able to render not just some planes and spheres, but a real VRML model, like your articulated model from project 2. On the main project description page, you can find out aboutvrml2out
, a script available on blue to convert VRML files for you.We're also attempting to provide an easier way to convert files. Try the following:
This directory is a "watched" directory. If you copy
- Using "map network drive...", map
\\blue\projects
.- Go into the
instr\cse457\vio
subdirectory.filename.wrl
into this directory, a remote process will wake up and runvrml2out
on it. The output will be placed in the same directory asfilename.out
. Additionally, any errors reported during conversion will appear asfilename.err
.Be sure to copy your files into that directory, don't move them. The remote process consumes your copy, so if you don't save the original, you'll lose it.
Also, the process isn't very robust with respect to naming. Try not to copy in a file with a name that may conflict with others. My suggestion is to prefix all files you put in there with your initials. That reduces the chances of a conflict.
Important Files
Remember -- don't get bogged down with the details of all the files in this project. You can and should safely ignore most of them unless you're adding a complex bell and need to really dive in.Here's a rundown of some of the more important files:
Vector3f.h
- Some functions that allow you to manipulate three dimensional vectors. Unfortunately, this abstraction would be much better implemented in C++. Oh well. Get really familiar with this interface, because almost everything you do will be in terms of Vector3f objects.
SceneIO.h
- You don't necessarily need to interact directly with the structures and functions defined in this file, but it's good to know what's in there. This file defines the
SceneIO
struct, which contains all the information about what's in the universe you're tracing. The associated.cpp
file contains the routines that read and write.out
files, so if you're thinking of extending the file format to add extra geometry or material parameters, you'll have to look in there.
Intersect.{h,cpp}
- These files define the ray-object intersection tests. In the past, students have had to write all this by hand, but we feel that it's a painful experience without much educational benefit, so we've written the code for you!
You don't need to worry that much about these files at first. You may eventually find it useful to call the
Intersect
function yourself. Also, if you're thinking about adding arbitrary indices of refraction, you will have to modifyIntersect.cpp
.
Raytrace.cpp
- Finally, we come to the most important file of all. Open this file and scroll down to the line in the
Shade
function that says "/* You will need to fill this in */". That's basically where your work goes. You need to flesh out this function to return to the caller the colour of this point on the given object's surface as seen from the given viewpoint.
Important Data Structures
Here's a slightly different view of the project: the data structures you'll care about when filling in yourShade
function.
Ray
struct Ray {
Point3f P;
Point3f D;
}
A ray has an originP
and a directionD
.
MaterialIO
struct MaterialIO {
Color3f diffColor;
Color3f ambColor;
Color3f specColor;
Color3f emissColor;
float shininess;
float ktran;
}
Instances of this struct get associated with objects in the world. These fields essentially give you all the properties of the surface that you need to implement the Phong shading model.
RTParameters
struct RTParameters {
float rayeps;
float minweight;
int maxlevel;
}
The fields in this struct are used to help terminate the recursion in yourShade
function. You might not use all three fields.
Important Functions
When you hit the "raytrace scene" menu item, here's what happens:
CTraceView::RaytraceScene()
is called. This does some MFC magic and calls...
CTraceView::RenderScreen()
. This is where raytracing as you have come to love it begins. For each pixel in the viewing plane, this function constructs a vector that passes from the viewpoint through that pixel. It then passes that vector to...
TraceRay()
. This function actually does the computation for a single ray.TraceRay()
fires the ray off into the world and retrieves the first intersection with geometry. If there was no intersection, it callsShadeBackground()
and stops immediately. Otherwise, it obtains all necessary information about that intersection point and calls...
Shade()
.Shade
is responsible for figuring out the colour of this point on the object with respect to the given viewpoint. It takes many parameters:
scene
contains information about the lights, objects and camera in the scene.level
indicates the current level of recursion.weight
can be used to do adaptive recursion on transmitted and reflected rays.P
is the point on the object where the intersection occured.N
is the normal atP
I
is a vector that points from the viewpoint toP
intersect
contains information about the intersection point. When implementing refraction,intersect->prevIndex
holds the index of refraction of the medium the ray is coming from andintersect->nextIndex
holds the index of refraction of the medium the ray is entering.color
is an "out" parameter into which you should place the colour you want the viewer to perceive at this point on the surface.
Additional Information
- When you are viewing scenes rendered with your solution, the scenes may appear washed out. Try scaling the factors in your code until the ray traced image looks roughly similar to the output of the sample solution.
- For (semi-)transparent surfaces, you should probably multiply the diffuse and ambient terms by (1-ktran). Otherwise, the diffuse and transmitted rays will add up and the surface will become washed out.
- For the basic assignment (without any bells or whistles for refraction), the refractive index may be set to 1.5.
- For ns, use shininess*128 (where shininess is the scene's shininess output between 0 and 1.)
- For attenuation of light sources, use the attenuation equation presented in class with a0 = 0.25, a1 = 0.1 and a2 = 0.01. You can try fiddling with these parameters. They're like physical constants, only in some alternate universe that obeys Phong's model. Change the constants and light behaves differently (and maybe better).
Note that secondary rays (reflected and transmitted) should not be attenuated.
- It might be a good idea to have your project looked over by a TA before starting to add bells and whistles.
- Don't feel like you have more work to do just because you haven't used all the fields provided in all the data structures. They potentially store more information than you need.
- Unfortunately, the raytracer is currently a bit limited in terms of what kinds of geometry it can display. As it says in the handout, spheres lose any transformations on them and appear perfectly spherical. Also, VRML primitives like cones and cylinders are triangulated during conversion, so they look faceted, i.e. bad. The good news is that we're trying to rewrite part of the code to fix this problem, in a way that doesn't interfere with your project. Watch for an announcement about a fix.
Send questions or comments about the help session and handouts to Craig.