CS 315 Homework 5 - Under a Street Lamp (Part 1)
Due Sun Nov 02 at 11:59pm
Overview
How about a scary scene for Halloween?
For this assignment, you will be using further rendering techniques in order to build a simple animated scene. In particular, your scene will make significant use of lighting and shading to improve its appearance. Furthermore, you'll be working with bigger, more complex models--such as those you might construct through a 3D-modeling application like Blender.
This assignment should be completed individually.
Objectives
- Practice creating and working with 3D meshes (especially those created by others!)
- Be able to apply illumination models (i.e., Phong) and different light sources in shading a scene
- Be able to write complex GLSL shaders
- Review working with transformations and animation
The Scene
You will be modeling and rendering an animated scene of some object under a street light. Maybe it is a robot or an alien. Maybe it is an inanimate object. Maybe it is someone enjoying the Tacoma rain. It could be anything--you never know what you might find on a street corner!
Your scene will need to include a couple of elements (more details can be found below)
- You will need a model for your streetlamp. You should model and export this as a mesh from Blender.
- You will also need a model for the object to stand beneath the street lamp. You can use any object you wish for this, but you'll either need to model this yourself or download a mesh from the internet.
- You will additionally need to include at least one other object that is not directly under the light (e.g., a bench, a tree, a dog, a cube, etc).
- I also recommend including an additional model for the "ground" for your objects to stand on, but this could just be a simple plane.
- I also also recommend having a cube sitting in your scene somewhere, both for testing and as a demonstration of the scene's lighting.
- Feel free to be creative with this! The more interesting scenes, the better.
Overall, your scene will need to include at least 3 objects total.
A significant component of the scene will be how the objects in the scene are lit and shaded. This lighting will change over time--your scene should "animate" in a loop over a 60 second period.
-
During the first 30 seconds your animation should show a "daylight" scene, lit by a primary directional light (the sun). This light should move across the sky from one side of the screen to the other; the direction of the light should be obvious from the lighting highlights on the models.
- You can of course model the sun as an additional object in your scene if you wish :)
- During the day time you should also have addition lighting (e.g., ambient light or additional directional lights) "fade up" and "fade down"--make it look like it gets bright for the day and then dims for the night!
-
The second 30 seconds of your animation will be at "night". At night, the streetlamp turns on, acting as a spotlight on the object standing under it. Note that your third object should not be (entirely) lit by the lamp!
- Alternatively, you can have your streetlamp act as a point light with attenuation--that is, filling a small circular area.
- You can include a tiny bit of ambient light at night if you wish, but the primary lighting should be from the street lamp.
Note that in the next assignment you will be adding further objects to your scene--particularly textured objects (in case you want to plan ahead).
Necessary Files
You will want a copy of the cs315-hwk5.zip file which contains some starter code for this assignment. At this point the file structure should be fairly familiar. Notable changes:
-
The OpenGL method calls (e.g., shader and draw calls) have moved back into the main JavaScript file
scene.js
. Lighting involves close interaction with the shaders, so best to keep the details front and center since you'll be making plenty of changes.- You are welcome to refactor this though if it makes your life easier.
-
We will be loading externally defined meshes into our scene--in particular, meshes defined in
Wavefront .obj
format. We will go over this format more in class.
-
I have included a
helper library
(
lib/webgl-obj-loader
) that will do the hard work of parsing the .obj file into a format we can use. This library defines a namespace OBJ that contains a method for "downloading" meshes (though you should be loading them from theassets/
folder), creating objects that have vertices, indices, and normals just like we've used before. (There is also a helper method to create thebuffers
for these objects). An example of using this library is included in the starter code. - Note that I have tested this library with a couple of models but not all possible ones--if you hit any errors, let me know!
-
I have included a
helper library
(
-
I have included the same (but renamed) vertex shader from the CubeBot; you will need to modify this shader significant for this assignment!
- I recommend making multiple vertex shaders as you go, so that you can easily revert to previous versions. You might even consider loading in multiple
shaderProgram
s and switching between them as you go!
- I recommend making multiple vertex shaders as you go, so that you can easily revert to previous versions. You might even consider loading in multiple
And of course, the zip file also contains a README.txt
file that you will need to fill out.
Assignment Details
This section includes some further details and tips for creating your scene:
Modeling the Scene
The first step of the assignment is to model your scene: decide what objects you want your scene to show, acquire meshes of those objects, and then make them show up on the screen!
-
Your street light should be modeled (by hand) in
Blender.
We'll have a lab day to work on this, though you should also consider looking at one of the
many
available
tutorials.
The official
documentation
can also be helpful for figuring out basic commands.
- You can start with a basic polyhedron (e.g., a cube or a cylinder) by selecting one from the Create tab on the right.
- Hit "tab" to go into edit mode; you can then select individual vertices or faces to move them around.
- You can extrude (duplicate) a face by selecting it or its vertices and hitting "E", and merge vertices together by selecting them and hitting "W" then selecting "merge" from the menu.
- You can also simply use a combination of basic polyhedra modified by our standard transformations (scale, rotate, translate) to "build" a streetlight--think of it like building with blocks!
-
Once you have modeled your street light, you can Export it to a
.obj
file that your program will be able to read. Select all of the meshes you wish to be part of your final mesh and select File > Export > Wavefront (.obj) from the menu.- When exporting, be sure and select the Write Normals and Triangulate Faces (the other options should be fine with defaults).
-
Important: Be sure and save your
.blend
scene file as well, so that you can re-export your mesh if needed (you will almost certainly need to do this for the next assignment).
- You should then be able to place the
.obj
file in yourassets/
folder and load it like the teapot. - This should be fun, but don't get too bogged down in the modeling!
-
You will also need a mesh for your spot-lit object. You can create something in Blender, but I recommend you instead find and download a mesh from the Internet. There are lots of 3D models made available for free online--indeed, being able to find and use these models (with proper credit) is a big step towards developing "real-world" graphics applications. You can Google for particular models, or peruse various repository sites (if you find particularly good ones, post on Piazza so everyone can benefit!)
- You'll want to search for ".obj" or "object" files as a format.
- Be careful to test that the provided loader code does what you expect. If your mesh doesn't appear correct, there may either (a) be a problem with it or (b) be a problem with the loader. Being able to debug these issues is part of demonstrating that you understand the format (though I'm happy to help of course)
-
Note that models often also come with material files (.mtl) that specify the color, lighting, textures, etc. for a model. The loader as provided does not yet support these specifications, though adding that functionality would be a handy extension (and welcome by the original developer I'm sure)!
- The challenging part of this extension is not parsing the .mtl, but dealing with the fact that a model might have multiple materials for different sets of faces! You won't be able to have just one indexBuffer, since each will get a different set of attributes passed to the shader. In effect, you'll need to load the
.obj
as a collection of different meshes.
- The challenging part of this extension is not parsing the .mtl, but dealing with the fact that a model might have multiple materials for different sets of faces! You won't be able to have just one indexBuffer, since each will get a different set of attributes passed to the shader. In effect, you'll need to load the
- For your last model (the thing outside the street light), you can use any form of mesh you wish. You could use the hard-coded cube model from the last assignment, or the sphere model from the lecture code.
- Overall, I recommend finding and loading a single model at a time, to make sure things work.
Materials and Shading
As we will discuss in class, we determine how to light and shade 3D objects by modeling some form of light reflectance. For this assignment, all of your objects should implement the Phong Reflectance Model. Each object will also need its own reflectance, allowing meshes to be shaded differently even under constant lighting.
-
You'll need to have a way to specify the "reflectance" of each different mesh--that is, different reflectance coefficients representing different materials. For example, one object may have coefficients that give more weight to its specular component, making it "shinier".
- There are a few different ways to choose different coefficients. One involves "playing" with the materials by testing different values to see what you get. There are interactive programs that may make this easier--for example, Nate Robins lightmaterial tutorial will let you play around with coeffients on a per-color basis.
-
You can also use Blender to play with material settings. You might find
This wikibook
informative, though Blender materials do not map directly to the coefficients of the class Phong model.
-
The
Wavefront .mtl
files that come with most
.obj
meshes specify this kind of information as well, and can be directly applied to the Phong model.
-
The
Wavefront .mtl
files that come with most
- You should make a set of "material" JSON objects that can store these parameters for each mesh. Then when you shade a model, pass these values in to your shader and use them to weight your reflectance calculations. That way each model can have a different reflectance (and hence a differet appearance!)
- Note that in the end your scene should use Phong shading (e.g., per-fragment shading). However, testing with Gouraud shading (e.g., per-vertex shading) may help with debugging.
Day Time
Once you've got a the meshes in place, you should start modifying the default lighting. Begin with "daytime" lighting: the object should be lit by the sun (a directional light) moving across the sky. The actual model of the sun isn't important--it can easily be off-camera (who wants to look at the sun anyway?), or simply a yellow sphere or even a very large point. What is important is that your light source moves in a circular arc around your scene--the direction of the light should be from the light's position to each of your vertices
- Consider the provided
gouraud_lit.vert
shader (which is the same "shading" you used in the last assignment). Notice that this has variables that represent two hard-coded light directions (as if from infinite distance away--like an orthogonal projection). -
Your task is to make the light direction vary over time--that is, it should be calculated each frame. So instead of hard-coding the variable, you'll want to pass it in as a variable to the shader--just like you did in Hwk 2.
-
Important question: should this position be an
attribute
of the vertex or auniform
variable? -
You will also need to modify the provided
drawMesh()
method, likely in all kinds of ways (e.g., maybe you want to pass a different set of arguments to it). Don't worry about changing the provided code--it is simple there to give you a place to start! -
You can calculate the directional vector by imaging the sun moving along the edge of a unit circle, and then calculating the direction between the origin and that arc (only the direction matters, not the distance)! Pass this direction in to your shader and use that to determine the amount of light that is hitting each vertex.
- You can use simple polar coordinates to determine where the sun is on a unit circle... or you could define a point (e.g., [-1,0,0]) and apply a rotation matrix to it using the glMatrix library!
- The calculation of the angle can be based on the
Date.now()
variable, just like you did with animation previously. UserequestAnimationFrame
to animate your sun!
-
Important question: should this position be an
-
Once this task is completed, you should be able to see evidence of the directional light changing (particularly in which vertices are light and where specular highlights are located). Make sure that at least one of your models has reflectance that makes the movement of the light source clear!
- Testing this with a simple model like the cube is a really good idea!
-
In addition to moving the sun, you'll want to add a little bit of additional lighting to make it look like it is day time. You should increase the amount of ambient light in your scene as the sun rises (and decrease it as the sun sets)
- Too much ambient light can "wash out" the rest of your shading, so don't go overboard! If you feel that you still nee more lighting you can add in additional directional lights (like a "back light" and a "fill light"). Just make sure the effect of your sun moving is still clear!
- You can also make it really clear that it is day time by changing the background color to a lighter shade... or even lighting a kind of "background" rectangle that fills the screen behind your scene (like a backdrop).
- You will need to pass the direction the sun is pointing, the level of ambient light, and possibly the level of the sun's brightness to the shader. You'll also probably want to pass some kind of sentinel about whether it is day or night. That's a lot of variables; you might consider if you can "compact" the information (such as by using a vector or matrix to store values like they were 1d or 2d arrays).
Night Time
Once you've got things looking good in the daytime, it's time to move into the night. During the night, the primary source of light should be from your street lamp, which should light up only a limited area of the scene (namely, the space under it).
- You can model the street light as either a spot light or a point light; either will have attenuation (that is, the light should cut off after a certain distance). Note that you can make the fall-off relatively "soft" if you'd like, but it should be clear what obejcts are inside the light and what aren't.
- In order to model these lights, you'll need to know their location and strength (and direction for a spotlight). Using this data, you can calculate the direction and distance to each vertex (or fragment!) of your mesh, and use that information to determine the lighting. See the textbook and the lecture notes for more details.
- Note that the spotlight has slightly more complicated math (in that there is an extra "if" statement), but will likely look better for your scene. You are welcome to use either approach.
-
Your streetlamp should only turn on if it is night; that is, your shader will need to make a decision about whether to include the light from the streetlamp or not (e.g., pass it a sentinel variable). You can also define a separate shader program and switch shaders when you move from night to day (by calling
gl.useProgram()
on the appropriate shader handle).- You might also want to have a separate model with very high reflectance (e.g., pure white) appear at night, to act like the "bulb" is on.
- You can also include a tiny amount of ambient light (representing the moon and stars) if you wish, but make sure that the light cast by your streetlamp is obvious!
Extensions
There are TONS of ways to extend this assignment. Additional components can be worth a point or two of extra credit.
- You could make your scene more complex, with additional meshes, light sources, and animations. How about the dancing robot under the street lamp? How about using Three-Point (Hollywood) lighting?
- You could even add extra details to your lighting: for example, it might be fun to have the street lamp "flicker" on!
- As mentioned in the assignment, including
.mtl
files in your scene would definitely be worth something. - If you want to get really advanced (going above and beyond the requirements), you can define a different BRDF for different objects. This is essentially writing a different illumination model (following the same principles as Phong). You might look at Disney's BRDF Explorer and the MERL database for examples of different BRDFs. Having a mesh that supports such a model would be amazing... but really might be a better goal for a final project!
- Other possibilities abound: if you're wondering about an option, check with me!
Submitting
BEFORE YOU SUBMIT: make sure your code is fully functional! Grading will be based primarily on functionality. I cannot promise that I can easily find any errors in your code that keep it from running, so make sure it works.
Upload your entire project (including the assets/
and lib/
folders) to the Hwk5 submission folder on vhedwig (see
the instructions
if you need help).
Also include the .blend file for your streetlamp mesh!
Finally, include a filled-in copy of the
README.txt
file in your project directory!
Important note: Be sure and modify the HTML file so that it the page includes sources for all models you use, giving proper credit.
The homework is due at midnight on Sun Nov 03.
Grading
This assignment will be graded out of 30 points:
- [2pt] Your scene includes a streetlamp (which has been modeled in Blender!)
- [2pt] Your scene includes a second mesh for an object "under" the streetlamp
- [1pt] Your scene includes a third object that is not under the street light
- [2pt] Each mesh is rendered with a different material (e.g., color).
- [3pt] Your meshes implement the Phong Reflectance Model (with identifiable diffuse and specular components)
- [1pt] Meshes are shaded using Phong Shading
- [2pt] Your scene models the sun as a directional light
- [2pt] Meshes are lit based on the direction of the sun's light
- [2pt] The sun is animated and moves in an arc across the sky, changing the direction of the light
- [1pt] The amount of ambient light in the scene increases in the morning and decreases in the evening
- [2pt] Your scene's animation cycles over an appropriate length of time
- [3pt] Your streetlight models either a point light or a spot light with attenuation
- [2pt] Meshes are lit based on their location relative to the streetlight
- [1pt] The streetlight is only on at night
- [1pt] The sun light is not present at night
- [2pt] Coding style (e.g., good use of helper methods, comments, etc--especially in the shaders!)
- [1pt] README is complete