Computing Science CMPT 361 Fall 2019
Assignment #3
Due date: November 27th at 11:59 pm.
Ray Tracing
You will write a basic ray tracer. The entire assignment can be completed in Euclidean
space; there is no need for homogeneous coordinates. There are 25 points available.
(a) [1 point] Window setup
Use OpenGL to set up a window with a 400 x 400 pixel drawing window. Use a symbolic
constant rather than 400 so that you can change resolution by changing the constant.
(b) [2 points] Viewing
The eyepoint is the origin, and the view is down the negative z-axis with the y-axis pointing
up. The coordinate system is right-handed.
Have a constant or a procedure call that defines the Field of View in the Y-direction (fovy), in
degrees. The field of view is the angle between the top of the view volume and the bottom
of the view volume. It is illustrated in the following image, but note that we will have no
near or far clipping planes. Note that since we have a square window (400 x 400) the field of
view in the x-direction (fovx) is equal to fovy.
(image from learnwebgl.brown37.net)
Assume that the virtual screen is on the plane at z = -1.
Design an object called Ray to hold a ray, which consists of a start point p0 and a vector v
and represents the ray p(t) = p0 + tv for t ≥ 0.
Computing Science CMPT 361 Fall 2019
In a routine named render, write a loop nest that will generate the initial rays for each of the
pixels. These initial rays start at the origin and have a vector v = (vx, vy, -1). Your job here is
to figure out the correct vx’s and vy’s given fovy. At this point, the body of the loop nest
should just create a ray object.
(c) [2 points] Primitives
You will have two types of objects that you will be making images of: spheres and planes.
Define an object for each of these primitives, e.g. a Sphere and a Plane. Design ways of
creating these objects so that they are put on a globally-accessible list (array, vector, etc.) of
CMPT 361作业代写、代做system留学生作业
objects. You may either keep one such list or two (which would be one for Spheres and one
for Planes).
When creating an object, specify its geometry and its material/surface properties. For
example, you might have:
new Sphere(1.0, 2.0, -3.0, 1.25, 0.1, 0.8, 0.8, 0.9, 0.9, 0.9, 32, 0.5, 0.0, 1.5)
which is quite hard to figure out. It’s better if you have objects that group the parameters,
such as a Point and a Color:
new Sphere(Point(1.0, 2.0, -3.0), 1.25, Color(0.1, 0.8, 0.8),
Color(0.9, 0.9, 0.9), 32,
0.5, 0.0, 1.5)
This is still a long parameter list, but it is meant to represent:
Center of sphere: (1.0, 2.0, -3.0)
radius of sphere: 1.25
kd: Color(0.1, 0.8, 0.8)
ks: Color(0.9, 0.9, 0.9)
q: 32
kr: 0.5
kt: 0.0 (no refraction)
index of refraction: 1.5
One can perhaps simplify the parameters farther by defining an object Material consisting of
all the material properties.
Material* aqua = new Material(Color(0.1, 0.8,0.8), Color(0.9, 0.9, 0.9), 32, 0.5, 0.0, 1.5)
…
new Sphere(Point(1.0, 2.0, -3.0), 1.25, aqua);
Computing Science CMPT 361 Fall 2019
Instructor: Tom Shermer Simon Fraser University
The object Plane should be similar, with the first four parameters denoting A, B, C, and D of
the plane equation Ax + By + Cz + D = 0:
new Plane(0.0, 1.0, 0.0, 1.0 , aqua);
This is the plane y = -1 given the ‘aqua’ material properties.
(d) [1 point] Lights
The lights you will be using are simple local point light sources with no falloff.
Define an object Light and a way of creating them so that they are put on a globallyaccessible
list (array, vector, etc.) of lights. Each light should have a location and a color
intensity:
new Light(Point(-100.0, -100.0, -20.0), Color(2.5, 2.5, 2.0))
Note that the “Color” here is color intensity and can contain values greater than 1.0; normal
colors (kd and ks) have channels that range between 0.0 and 1.0.
(e) [1 point] Scene setup and command-line argument
Your program must be capable of displaying one of four different scenes depending on a
command-line argument (which will be a number, 1 to 4). Each scene should set up lights,
primitives, camera (fovy), and also set a depth limit for the ray tree, an ambient light
intensity, and a background light intensity. You should have one subroutine for each scene
to display. Here’s roughly what a scene subroutine should look like, if you use the Material
object:
void scene2() {
Material* aqua = new Material( … );
Material* greenGlass = new Material(…);
Material* chrome = new Material(…);
fovy(40);
rayTreeDepth(4);
ambient(new Color(…);
background(new Color(…);
new Light(…);
new Light(…);
new Sphere(…);
new Sphere(…);
new Plane(…);
render();
}
Don’t slavishly copy that; you may have other syntax for creating your objects, or differentlynamed
subroutines, etc.
Computing Science CMPT 361 Fall 2019
Instructor: Tom Shermer Simon Fraser University
(f) [3 points] Ray-primitive intersections
As member functions of the primitive objects (Plane and Sphere), implement a routine which
will intersect a ray with the object. It should take the ray as a parameter and return the
smallest positive t value at which the ray intersects the primitive. If there is no such t value,
it returns a negative number. (This is an overloading of the return value but in this case
speed is important so we’ll forgive ourselves.) These computations have been covered in
lecture.
(g) [7 points] Ray tracing
Implement a function trace that takes a ray and a depth of tracing as parameters, and
returns a color intensity.
If the depth of tracing is 0, then trace should return the background color intensity.
If the depth of tracing is greater than 0, then trace should intersect the ray with all primitives
in the scene and determine which one has the smallest positive t where it intersects. This is
the object the ray hits. If the ray hits no object, then trace should return the background
color intensity.
If the ray hits an object, then let p(t) be the point where it hits. At this point, apply the
lighting formula
𝐼 = 𝐼𝑎𝑘𝑑 + 𝐼𝑟𝑘𝑟 + 𝐼𝑡𝑘𝑡 +∑𝑆𝑖
𝐼𝑖(𝑘𝑑𝑁 ∙ 𝐿𝑖 + 𝑘𝑠(𝑅𝑖∙ 𝑉)𝑞)𝑚
𝑖=1
Ir and It are obtained by recursively tracing the reflected and refracted rays, respectively. Be
sure to decrement the depth-of-tracing parameter by 1 when you make the recursive call.
SI should be 0 or 1 and is obtained by a ray cast from p(t) in the direction of light source i.
The view vector V is the reverse direction of the incoming ray that hit the surface at p(t).
You will need to find the normal vector to your primitive at p(t), and also Li and Ri. You’ll also
have to find the directions of the reflected and refracted rays; the refracted one is more
difficult but that is a problem I leave for you to solve. Do not generate reflected or refracted
rays if kr or kt is zero.
Modify your render subroutine so that it traces the rays that it generates. When it gets a
color intensity back from trace, it should first convert that color so that all channels lie
between 0.0 and 1.0 ( because the intensity you get may be out of range). You choose how
to do this. Then it should write that color to the appropriate pixel on the OpenGL display.
See the programs in section 23-1 of your text if you are unsure how to do this…it’s done with
code like:
glColor3f(r, ,g, b);
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
Computing Science CMPT 361 Fall 2019
Instructor: Tom Shermer Simon Fraser University
(h) [8 points; 2 points each] Four scenes
Each scene should contain at least three spheres and one plane.
Scene 1 should convincingly demonstrate that you have basic Phong lighting controls
implemented. I want to see diffuse and specular effects. Be sure to include surfaces with
different values of q, the specular exponent. Be sure the image clearly shows an effect from
the changing q.
Scene 2 should convincingly demonstrate that you have reflection and shadowing working.
Scene 3 should convincingly demonstrate that you have refraction working.
Scene 4 is your choice. Design a nice scene and impress us with what your ray-tracer will do.
Extras
No extra credit is available, but you can implement extra functionality if you would like. For
instance, have a function to call from a scene function that will set the resolution of the
render (rather than 400 x 400). Or you could implement extra primitives, like polygons,
quadrics, or CSG. Or you could implement light attenuation. Or texture-map the plane like
a checkerboard. On the structural side, you could implement bounding volume hierarchies.
These are just some ideas in case you’d like to expand this project.
Note that you can include these extras in your scenes, particularly in scene 4.
Submission:
• All source code,
• a Makefile to make the executable called rayT (the make command should be
simply “make”),
• four images called S1.jpg, S2.jpg, S3.jpg, S4.jpg that show the images that result
from running your program with arguments 1, 2, 3, and 4, respectively,
• and a README file that documents any steps not completed, additional features,
and any extra instructions for your TA.
因为专业,所以值得信赖。如有需要,请加QQ:99515681 或 微信:codehelp