By the end of this lab, you will:
In this lab, you will render BB-8 using the shading techniques we introduced this week. The primary objective is to implement the Phong Reflection Model and add shadows to the scene. An optional part is to make BB-8's eyes look like a mirror.
To access the lab template, please click the link in the Lab 3 Assignment Link
post on our Ed discussion board. When you preview the index.html
page (via the Go Live
button), you should see a blue background for the sky.
All of the code you will write will be in the renderer.js
file which contains a few class definitions. In particular, there are class definitions for a Ray
, Sphere
, and the Renderer
class. A lot of the setup will look similar to what we did last week in Lab 2.
The Renderer
class takes in (1) the canvasId
(string) of the canvas in which we would like to render our scene, (2) the vertical field-of-view (fov
), the objects in the scene and the light information: (1) the ambient color ca
, and (2) a light
object which as a position
and color cl
. The objects are all spheres (even the ground) and stored in an array of length 6 (planet, body, head, 2 eyes, and a remote droid).
The Renderer
class saves the incoming information (fov
, canvas
, objects
, ca
, light
), which is then used in the render
method to render the scene. Your job primarily consists of modifying the render
method as well as the intersect
method of the Sphere
class.
Before getting started, please have a look at the way the materials are setup in the index.html
file. There are 4 materials here for the ground, BB-8, eyes and remote. Each of these is described using JSON (similar to a dictionary/map) and contains fields for the different material properties. At the very least, each of these has a type
and the base material albedo (km
). The type
is a string which is either diffuse
, specular
or mirror
. For specular
and mirror
types, there is also a ks
field for the specular reflection coefficient.
This is a theoretical question which can be done at any time. I would suggest doing this part after the lab if you want to focus on writing code during the lab.
I've suggested normalizing the normal
As in Lab 2, please upload a picture of your derivation to your repository, or type it in the README.md
file using LaTeX.
Part 2A: Although this will feel a bit repetitive, it's a good idea to revisit the techniques we used to (1) create rays and (2) intersect these rays with spheres. For each pixel (i, j)
, please create a ray that passes through the pixel starting from the eye. We are still using the eye as the point (0, 0, 0) in this lab.
Part 2B: Next, complete the intersect
function in the Sphere
class. You can copy over what you had for the sun from last week's lab (or from the exercise) to get started, but please note that this function now returns something different. In particular, we need to return information about the intersection point: the surface point at the intersection, the normal to the surface at this point and which object is intersected (so we can retrieve the material
attribute).
Note that our Ray
class has been extended with an evaluate
function. Any point along the ray can be obtained as point = ray.evaluate(t)
for some Ray
object ray
. You will need this to calculate the 3d coordinates of the intersection point. You will also need to calculate the normal vector to the surface (please see the notes on how to do this for a sphere).
Part 2C: Next, please complete the hit
function of the Renderer
class. This function will loop over all the objects in the scene (this.objects
) and return the information about the closest intersection point. In other words, you should have a for
loop over this.objects
that finds the object with the minimum Sphere
intersect
function: surface point, surface normal and object).
Please ensure the 1e-5
) but using 0 should be okay for this lab.
Please complete the computeColor
function to account for the lighting sources and materials in the scene. You should model a single light (not a bidirectional light). When an intersection occurs, please add the ambient, ixn.object.material.type
property (check if this attribute is diffuse
or specular
). Materials that have the mirror
type should also have the specular (
To make sure this part works with the previous part, I would suggest starting by only returning the ambient color term:
Next add the diffuse and specular terms. Please use a shininess exponent of your choice and feel free to adjust some of the parameters in the material definitions (those in index.html
).
Finally, please add shadows by checking if a shadowRay
cast from the intersection point to the light.position
hits an object in the scene and only returning the computeColor
function.
There are two things we need to do to make BB-8 look more realistic:
head
object called cutoff
(try to find this in index.html
). In your Sphere
intersect
function please add the following line after finding tmin
:const point = ray.evaluate(tmin);
if (this.cutoff && this.cutoff(point)) return undefined;
km
for the head
and body
objects, let's make this a function. In fact, there is already a kmFunction
defined for these two objects that will return orange or grey, depending on the input surface point. In your computeColor
function, try using this variable km
value:let km = ixn.object.material.km;
if (ixn.object.kmFunction) km = ixn.object.kmFunction(ixn.p);
This part is optional, but you will need to add mirror reflections next week, so it's good practice. Please see the pseudocode in the notes for a description of how to reflect an incoming ray off of a mirror-like surface. Then call the computeColor
recursively with this new secondary ray. Whatever color is returned from the recursive call, I would suggest attenuating it by some factor (I used 0.25 below) before adding it to the final color. Try zooming in on the eyes to see the reflections of the planet and remote (look for the variable called zb
in index.html
and change this to -0.5
).
The initial submission for the lab is due on Thursday 3/13 at 11:59pm EST. Please see the Setup page for instructions on how to commit and push your work to your GitHub repository and then submit your repository to Gradescope (in the Lab 3 assignment). I will then provide feedback within 1 week so you can edit your submission.