
Don't see the menu?
|

EECS 487 PA2: Scene Graphs and Shaders
EECS 487 PA2: Scene Graphs and Shaders
This assignment is due on Tuesday 21 Feb 2012
at 12:01 pm (one minute after noon).
Plain Page for Printing
Overview
In this assignment you will work on a simple model/scene
viewer view3D that uses a simplified X3D scene graph as
well as two simple programmable shaders. The provided
view3D parses as input a scene description file in the
X3D format, partially
constructs a scene graph with various X3D nodes, and passes the scene
to the renderer. The full X3D file format is described in
the X3D Specification. Most of your tasks will be modifying the source
file scene.cpp. Look for words YOUR CODE
HERE to locate where to work. You will also modify the GLSL
vertex and fragment shader files: phong.vs along
with phong.fs, and
interesting.vs along with interesting.fs.
You're not required to read most of the X3D documentation
reference herein. Actually, you may find it more helpful to simply
read the class definitions in scene.h and glace
over the provided code in
scene.cpp relevant to the class of interest. The
one exception is the X3D Lighting Specification referenced below,
which you do need to read carefully.
The provided code has been tested to compile under Linux, Mac OS X,
and Windows. However, CAEN Linux workstations do not have great
graphics drivers and the programmable GPU shaders will not work
there. If you have a Linux machine with good drivers you can use
the Makefile provided. I haven't been able to get
shader support to work with Cygwin/X under Windows 7. If you manage
to get it to work, please let me know. For further help with the
support code, please see details below.
Graded tasks overview (100 points total)
- Implement rendering of
a Cylinder
node modifying
X3Cylinder::Render()
function. (5 pts)
- Implement simple camera navigation ("examine mode") by writing
a couple of
X3Viewpoint methods. (25 pts)
- Implement proper
modeling Transformation
sequence by modifying
X3Transform::Render()
function. (10 pts)
- Setup Point
Lights by modifying
X3PointLight::SetupLights()
and X3Transform::SetupLights() functions. (10 pts)
- Setup
the Material
properties by modifying
X3Material::Render()
function. (5 pts)
- Compute the normals and render
the IndexedFaceSet
(mesh) node, modifying methods
of
X3IndexedFaceSet::Render()
and X3IndexedFaceSet::Add(). (15 pts)
- Implement per-pixel Phong shading that matches the
fixed-function per-vertex rendering (modify
the
phong.vs and
phong.fs files). (15 pts)
- Implement Blinn-Phong variant of per-pixel shading (5 pts)
- Implement some interesting shader (modify
the
interesting.vs and interesting.fs
files). (10 pts)
Implementation details
We provide several X3D scene descriptions files in
the scenes folder. All the X3D files refered to below can
be found in this folder. As is, the skeletal view3D
provided can only display the X3D files 00-cube.x3d and
00-cone.x3d. If you try to view any of the other
files, you will simply get a blank blue window.
Cylinder rendering
Modify the X3Cylinder::Render() function to
render Cylinders
using all the provided data fields of the cylinder node. It may help
to look at how the same function is implemented for
the Cone
primitive. After you're done with this task,
your view3D should be able to
display 01-cylinder.x3d.
Camera examine mode
The simple X3D viewer and parser included with the project does not
include a camera class. All the viewing information is stored within
the X3Viewpoint
node. Our view3D uses only the position attribute
of X3Viewpoint. It specifies where the camera is
positioned. The camera is required to always points toward
the origin of the world coordinate system, with its
positive y-axis pointing up. I've added an up_
vector as a member of the X3Viewpoint class to help you
keep track of the up direction. The world coordinate space is also set
up with positive y pointing upward. You will need to implement
dollying in and out (mapped to dragging the mouse up and down with
the right button pressed---fyi, vanilla GLUT doesn't support
the mouse wheel). You will also need to implement camera tracking
along the latitudes and longitudes of a spherical space around the
world. Dragging the mouse left and right with the
left button pressed causes the camera to track along the
current latitude, with the camera oriented towards the origin of the
world coordinate system at all times. (You can also think of this as
the camera tracking along the current latitude without changing its
gaze relative to the world, and then panning back towards the origin
of world space after it has reached its target position.) Dragging
the mouse up and down with the left button pressed causes the
camera to track along the current longitude without changing its gaze
relative to the eye coordinate system (or, to track along current
longitude without changing gaze relative to the world, and then tilt
up/down at target position). You will need to write
the X3Viewpoint methods track_latlong() and
dolly. Feel free to add private members to
the X3Viewpoint class in scene.h to
cache frequently computed values. When rotating one of the eye's
coordinate system, you must be careful to avoid letting one axis
``pass another,'' e.g., when you rotate the gaze vector, make sure
that it does not crosses over the top vector. Hence, rotate the
top vector too. Once you have interactive camera control,
examine the 01-cylinder.x3d again to verify that you have
set up the top and bottom sides of the cylinder correctly. If you
view 00-cube.x3d again you'll see that it really is a
cube, not just a square. Similarly, you can now "fly" about
02-ds9.x3d, to see the space station, you
first need to "undock" and "fly away."
Modeling transformation hierarchy
The scene graph represents the scene as a directed acyclic graph
(it is not a simple tree since some nodes can be reused multiple times)
and the traversal of this
graph is performed when the scene is rendered. Grouping nodes such as
X3Scene,
Group,
and Transform
traverse their children so that each child renders
itself. The Transform node adds the ability to specify
the transformation between the child coordinate system and the parent
coordinate system so that children can be specified with respect to
their parent nodes.
Implement X3Transform::Render() following the
inline instructions. The inline comments pretty much give you the
solution to this task, so think of it as a chance to practice your
knowledge of OpenGL API calling conventions. Practice and drill.
The reward though is that you can now view 03-bikeframe.x3d,
03-desklamp.x3d, and 03-desktop.x3d.
Lighting setup
We will support only point lights in view3D. We will
assume each point light effects the whole scene, and therefore a
separate pass is needed to setup light positions and other light
parameters before the scene is rendered. Each point light can be
located anywhere in the scenegraph. A light attached to a child node
is transformed by the modeling transformation of the child's parent(s),
allowing a light to be "attached" to a particular
object. The X3Scene::SetupLights() method recursively
calls the SetupLights method of children nodes down
the scenegraph hierarchy. Each node's SetupLights should
be implemented very similar to the node's Render method.
Implement the X3Transform::SetupLights() method to do this.
Then in the X3PointLight::SetupLights() method set up OpenGL
lighting parameters for
PointLight
to match
the X3D
Lighting Specification (you need to read this lighting
specification). In our simplified viewer we have no fog and no spot
light, so ignore those parameters. Be careful to match X3D lighting
parameters onto OpenGL's parameters. If no lights are specified
within the X3D file, a default light is added to the scene
(in display()). Make sure to assign properties to the
light with the proper id: GL_LIGHT0 + light_index. You
can now see the effect of lighting on 03-bikeframe.x3d,
and 03-desktop.x3d. But to really put a shine on the
surfaces, you need to finish the next task.
Material setup
You set up the
Material
properties of your surface inside
the X3Material::Render() method. Lights are setup once
before rendering the whole scene whereas materials vary from node to
node. Be careful to match X3D material properties onto OpenGL's
material properties, for instance, shininess in X3D gets multiplied by
128, so check that the resulting colors and intensities are what you
intended. Now you can
view 00-cone.x3d, 00-cube.x3d,
01-cylinder.x3d, 03-desklamp.x3d,
03-bikeframe.x3d, and 03-desktop.x3d in
their glorious colors.
Computation of mesh normals and mesh rendering
IndexedFaceSet
represents a polygonal mesh node in the form of a list of vertex
indices. Each entry in the vertex index list refers to an entry
in the list of vertex coordinates.
Our simplified X3D
parser supports only triangle and quad meshes. From an X3D file, the
parser extracts two separate lists: one of quads and the other of
triangles (see the X3IndexedFaceSet class and the
comments in X3IndexedFaceSet::Add()). The parser also
assumes only coordinates are given (no normals or colors, for
example). In order to compute lighting, you need to compute a normal
for each vertex. The normal of a vertex is the average of the normals
of the polygons sharing the vertex. To compute the normal of a
vertex, you need to first compute the normal for each polygon. Each
vertex then accumulates the normal computed for each of its incident
polygon. After all the polygons have been processed, average out the
normals of the vertices by normalizing them. Vertex normal
computation is to be done in the X3IndexedFaceSet::Add()
method.
You will also need to implement mesh rendering within
the X3IndexedFaceSet::Render() method. For each
triangle, draw triples of vertices in a loop within
the GL_TRIANGLES rendering mode. Remember to
specify glNormal() before each call
to glVertex(). Similarly for quads. Recall your
X3Cylinder::Render for an example, but specify a separate
normal for each vertex. Once you are done with this task you will be
able to display the famous graphics teapot
model, 04-teapot.x3d but check out the
04-coolcube.x3d! Other files you can now view:
04-eight.x3d, 04-fish.x3d, and
04-torch.
GLSL shaders
These last three tasks will be done in GLSL. Before starting this part
of the assignment, you may want to review the GLSL syntax in the
lecture slides on Programmable Shaders. The provided support code reads
and compiles shader files. The shader files must be in the same folder
from where view3D is run (if you're using an IDE, this could
be where the project file is). The program compiles the shaders into
GPU-executable program objects. The code in shaders.cpp
performs these tasks. You are encouraged to read it to see how it
traps errors and notifies the user of failed compilation and linkage.
You can mix and match compatible vertex and fragment shaders. By
default, the program uses OpenGL fixed-function pipeline.
You will first need to implement a per-pixel version of the lighting
model where most of the work will be done in the fragment shader
phong.fs, but the vertex
shader phong.vs must first prepare the data for it. The
final color in the fragment shader should be assigned to the
vector glFragColor.rgb. Compute the per-pixel shading
using the original Phong algorithm. You would want to use the
built-in uniform variables gl_FrontMaterial
and gl_LightSource[] (see lecture notes). The view3D
application passes the number of lights in each scene to the shaders
using the uniform variable numlights.
You should use this variable to compute the contribution of all
lights in a scene in your shaders. Be sure to compute all components
of the lighting formula, including emission, ambient, and
attenuation. View the effect of your Phong shaders
on 01-cylinder.x3d, 04-coolcube.x3d,
03-desktop.x3d, and 04-torch.x3d;
compare the images to the ones created using only the standard
Gouraud shading (GL_SMOOTH).
Next copy your phong.fs to blinn.fs and make the
slight modification that implement the Blinn-Phong variant of the
per-pixel lighting (view3D will quietly reuse your
phong.vs). Now view 04-torch.x3d and
03-desktop.x3d again and marvel at the difference
such a slight modification to the formula can achieve.
The "interesting" shader task is an open-ended task and you can
implement any nice or weird looking shader. Examples of interesting
shaders may include the brick procedural texture or some cartoonish
looking textures (note that the
provided interesting.[vf]s already implements some simple
cartoon shading so you need to come up with something a bit more
interesting). Be original; do not simply take some random dot product,
multiply by 4, take the square root, and convert to rods per
hogshead. Think it through and make sure to explain and understand the
choices that you made.
Support Code and Required Libraries
Download the assignment archive from
/afs/umich.edu/class/eecs487/w12/FILES/pa2.tgz.
The program view3D should be called with one
command-line argument--the name of the X3D scene file. We have
included some in the scenes sub folder--there are many
other on the web, and some graphics packages can export to X3D. A few
of the models provided have non-planar surfaces in their indexed face
sets. This will cause them to have a small number of polygons missing,
such as 04-fish.x3d having a small hole in its
cheek. This is ok. It is caused by view3D supporting
only a subset of X3D than is in the sample scenes. e.g., we throw away
the provided normals and colors and we only recognize triangles and
quads.
The following keyboard shortcuts are defined
for view3D (you may bind other operations to keys
in view3D.cpp:kbd(), but do not change these
predefined keys):
- 'q' or ESC: quits the program
- '@': resets the camera
- 'p': activates the per-pixel Phong shaders.
- 'b': activates the per-pixel Blinn-Phong shaders.
- 'i': activates the interesting shaders.
- 'n': disables shaders (default, no shader, fixed-function pipeline mode).
The provided code needs to be linked against
GLEW, the OpenGL
Extension Wrangler, and the Expat XML Parser libraries,
in addition to the usual OpenGL, GLU, and GLUT libraries. GLEW is provided in the common
sub folder. The expatcommon folder. The expat library
should be completely transparent to you and you don't need to study it.
To build view3D, you need the header files for GLEW and expat and you need
to link against both.
Mac OS X Xcode 4 Project Setup:
- We'll call the folder where you put your PA2 files, e.g.,
/Users/you/Desktop/pa2, your PROJECT_DIR.
Double check that the common and scenes folders
are in your PROJECT_DIR.
- Start Xcode 4, create a new Command Line Tool project following the
instruction on
Installing
and Using GLUT and OpenGL course note and add all the .cpp
files and "common/src/glew.c" that come with the support code. The
Installation course note has been updated to account for Xcode 4.
- Under "Build Phases→Link Binary With Libraries", hit the '+' at
the bottom of the list. Scroll down the list of frameworks that comes
up until you see "libexpat.1.5.2.dylib" (your version may vary). Select
"libexpat.1.5.2.dylib" and click "Add". (Don't forget to add the OpenGL
and GLUT frameworks also.)
- Under "Build Settings" for view3D, double click to
the right of "Header Search Paths" and type "$(PROJECT_DIR)/common/include/"
- From the menu, click "Product→Edit Scheme". Go to "Run" and go to the
"Info" tab. Click on the menu for "Executable" and go to the folder that
contains your project. Select view3D. Go to the "Arguments" tab
and click the plus below "Arguments Passed On Launch". Type
$(PROJECT_DIR)/scenes/00-cone.x3d, or any other file in the scenes
folder you wish to display.
- You're all set. Click "Run" and you should see a window come up.
Windows Visual Studio 2010 Project Setup:
- We'll call the folder where you put your PA2 files, e.g.,
C:\Users\you\Desktop\pa2, your PA2DIR. We'll
call PA2DIR\common your COMMONDIR.
Wherever you see PA2DIR or COMMONDIR below, replace
it with the actual path name, don't enter PA2DIR, COMMONDIR.
- Start VS10, create a new Win32 Console project following the
instruction on
Installing
and Using GLUT and OpenGL, putting your project/solution file in
your PA2DIR. In addition to all the .cpp files that come with
the support code, also add "common/src/glew.c".
- Copy the scenes folder to PA2DIR\Release\.
- In VS10, right click on the solution and select Properties at the
bottom of the menu.
- When the "Property Pages" shows up, at the top, set the
"Confugration:" drop down menu to "All Configurations".
- Under "Configuration Properties", the second item in the left pane:
- Click on Debugging and set:
- Command Arguments: scenes\00-cone.x3d
Replace 00-cone.x3d with the name of the other files in the
scenes folder to view the other scenes.
- Environment: PATH=%PATH%;COMMONDIR\libexec
This tells Windows where to find our additional DLLs.
Be careful not to add a space between the semicolon and
your COMMONDIR.
- Click Apply.
- Click on "VC++ Directories" and set:
- Include Directories: $(IncludePath);COMMONDIR\include
This tells Windows where to find our additional header files.
Be careful not to add a space between the semicolon and
your COMMONDIR.
- Library Directories: $(LibraryPath);COMMONDIR\lib
This tells Windows where to find our additional static library files.
Be careful not to add a space between the semicolon and
your COMMONDIR.
- Click Apply.
- Click on "Linker→Input" and
- add to "Additional Dependencies:" the
following: "libexpat.lib",
in addition to "opengl32.lib;glu32.lib;glut32.lib".
- Click Apply.
- Hit CTRL+F5 to run the program without the output window vanishing
right after program completion. Ignore all compiler warnings about sscanf.
If build fails due to corrupted build state, do a
"Build→Rebuild Solution"
(or hit CTRL+ALT+F7) to rebuild everything. If build fails again, talk
to me. Otherwise, you should be able to run the program with CTRL+F5.
Submission Guidelines
As with PA1, to incorporate publicly available code in your
solution is considered cheating in this course. To
pass off the implementation of an algorithm as that of another is also
considered cheating. For example, if the assignment asks you to
implement sort using heap sort and you turn in a working program that
uses insertion sort in place of the heap sort, it will be considered
cheating. If you can not implement a required algorithm,
you must inform the teaching staff when turning in your
assignment, e.g., by documenting it in your writeup.
Test the compilation! Your submission must
compile without errors and warnings on CAEN
machines. Code that does not compile
will be heavily penalized.
Create a writeup in text format that discusses:
- Your platform and its version -
Linux, Mac OS X, or Windows.
- Anything about your implementation that is noteworthy.
- Feedback on the assignment.
- Name the file writeup-uniqname.txt.
For example, the person with uniqname
tarukmakto would create
writeup-tarukmakto.txt.
Your "PA2 files" then consists of your writeup-uniqname.txt,
phong.vs, phong.fs, blinn.fs, interesting.vs,
interesting.fs, scene.cpp, and, if
modified, scene.h.
To turn in your PA2:
- Email the GSI the SHA1's of your PA2 files. Use
"EECS487: PA2 Submission" as your email's "Subject:" line. Once
you've sent in your SHA1's,
don't make any more changes to the files, or your SHA1's
will become invalid.
- scp your PA2 files to your pa2 folder
on IFS:
/afs/umich.edu/class/eecs487/w12/FOLDERS/<uniqname>/pa2/.
This path is accessible from any machine you've logged into using
your ITCS (umich.edu) password. Or you can upload it
by pointing your web browser to
mfile.
Please report any problems to ITCS.
- Keep your own backup copy! Don't make any more
changes to the files once you've submitted your final SHA1's.
The timestamp on your SHA1 email will be your time of submission.
If this is past the deadline, your submission will be considered late.
You are allowed multiple "submissions" without late-policy implications
as long as you respect the deadline. Try not to email
your SHA1 to the GSI until you've finalized your code.
You don't want to annoy her.
To access the umich.edu AFS partition on CAEN machines,
you may first have to obtain AFS tokens. On Linux, this is performed
using the "gettokens" command on the terminal, followed by your ITCS
password. On Windows invoke the Start Menu -> All Programs ->
Communication Tools -> Open AFS -> Authentication which will
create a lock icon in your system tray. Click that to get the AFS
authentication dialog, click "Obtain New Tokens..." and enter your ITCS
uniqname and password for the umich.edu cell.
Turn in ONLY the files you have modified.
Do not turn in support code we provided that you haven't modified.
Do not turn in any binary files (object, executable,
dll, library, or image files) with your assignment.
Do remove all printf()'s or
cout's and cerr's you've added for debugging
purposes.
General
The
General Advice section from PA1 applies. Please review it if
you haven't read it or would like to refresh your memory.
|