Home
Contact Information
Office Hours
Announcements
LMS
Syllabus
Prerequisites
Textbook
Grading
Assigned Readings
Calendar
Lecture notes
Lab materials
Homework
Test reviews
Homework
Collaboration Policy
Compilers
gcc/g++ notes
GL/glut notes
Homework Late Policy
Electronic Submission
Final Project
Spring '11 Projects
Spring '10 Projects
Spring '09 Projects
Spring '08 Projects
Spring '07 Projects
Academic Integrity
|
Assignment 4: Using the Stencil Buffer & GPU
The goal of this assignment is to become familiar with both
classic graphics hardware (the stencil buffer) and the modern GPU
(using programmable geometry & pixel shaders).
Tasks
- First, download and compile the provided files. The basic
program will load an .obj into a scene. An appropriately sized quad
that represents the floor is placed beneath the object and an
appropriately sized quad that represent the mirror is placed to the
left of the object. A yellow point above the object represents the
position of a point light source. Pressing 'a' will toggle animation
of this light, moving it in a circle above the object. Pressing the
space bar will move the light one step along this path.
./render -input bunny_1k.obj
-
Press 'm' to toggle stencil buffer mirror rendering, which is
incomplete. You need to write code to "duplicate" and render the
geometry of the mirrored object and floor as they appear to exist,
reflected in the mirror. Pressing 'r' will toggle a visualization of
the reflected geometries, rendered in blue. If everything is working
with your stencil buffer, the mirror visualization should then work as
shown in the picture below. The objects in the mirror are tinted
slightly blue for effect.
If you study the resulting imagery closely, you'll notice that the
lighting is decidedly incorrect. The bunny in the mirror has
different local shading than the physical bunny. Which light source
should that bunny be lit by? For extra credit, describe the
problem in your README.txt file and improve the local shading on the
mirrored bunny. (Actually, the lighting on the physical bunny is
wrong too and can be improved!)
- Next, let's implement shadow volumes. The first step is to
determine the silhouette edges in the model. These are edges that have
one neighboring triangle facing toward the light source, the other
triangle facing away from the light source. Pressing 'e' will toggle
the visualization of these edges in red, as shown below. You need to
write the code to determine which edges are silhouettes and render this
geometry.
Once these edges are found, we can construct the polygons that
form the "sides" of the shadow volumes. These polygons are extrusions
of the silhouette edges away from the light source, towards infinity.
Pressing 'p' will toggle the visualization of these polygons in green,
as shown below, using blending so you can partially see through these
polygons and see the depth complexity of the multiple layers of shadow
volume polygons. You need to write the code to construct and render
these polygons.
- The last step is to do the multi-step rendering to create the
shadows. This involves juggling the frame buffer, depth buffer, and
stencil buffer. The basic idea is to first render the scene without
lighting. Then, we do a special rendering pass of the shadow volume
polygons: everywhere the depth buffer passes, we will increment (if
the shadow volume polygon faces toward the camera) or decrement (if
the shadow volume polygon faces away from the camera) the stencil
buffer. Finally, we render the scene a second time with the lights
on, but only where the stencil buffer is zero. The shadow rendering
mode is toggled by pressing 's'.
An excellent stencil buffer tutorial written by Mark Kilgard at NVIDIA:
http://developer.nvidia.com/object/Stencil_Buffer_Tutorial.html
(alternate link)
gives more detail on each step of the method.
- There are several extensions to the basic shadow volumes code
that you can do for extra credit, including: handle non-closed
objects, improve the efficiency of the method, make the shadow volumes
and mirror rendering methods work together (the same shadows should
appear in the physical scene and the mirror), or implement "Z-fail"
shadow volumes so that the rendering is correct when the camera is
inside of a shadow volume (create a new scene to demonstrate this
extension). Also, for extra credit you can mirror the light source.
Both the real object and the reflected object should be lit by two
light sources, the real and the reflected light. Describe any
extensions you make in your README.txt file.
- Next... let's experiment with GLSL shaders. The first step is
to find a computer system capable of compiling and running these
shaders. You'll need to rebuild the base code with an extra compile
flag:
make clean
make EXTRA_DEFS=-D__HW4_SHADERS__
The code has been tested on OSX & Linux (with NVidia graphics cards).
If the code does not build out of the box on your system, try to solve
the problem. You may need to try another computer system if your
graphics card doesn't support GLSL.
Once it builds successfully, try the examples below. Once loaded,
press the 'x' key to initialize the shaders. Pressing 'x' again will
disable the shaders.
./render -i cube.obj -v checkerboard.vs -f checkerboard.fs
./render -i sphere.obj -v orange.vs -f orange.fs
If your system supports GLSL and the noise function, the models
should render like the images below.
If the checkerboard looks good, but the orange is missing the bump
map, you card doesn't support the noise function (but you can still do
some interesting things with shaders for the homework). Be sure to
press 'n' to render with per-vertex smoothed normals.
If you get it working quickly... great! However, if after a
reasonable amount of effort (use Google, etc.) you are unable to get
a working setup either on your own machine or a borrowed machine (try
the VCC), then write up what you tried, and what errors you were
seeing in your README.txt file. You can submit carefully written and
commented but untested code for the remaining portion of this homework
assignment and will receive full credit for your effort.
- First, poke around at the vertex & fragment shaders for these
two examples. Make small modifications to the code and see what
happens. You don't have to quit & restart the program when a shader
changes, you can just press 'l' to recompile, relink, and reinitialize
the shaders. Note: if you make a syntax error in the GLSL code, the
program will most likely crash without giving you an informative error
message. Thus, it's recommend to frequently test your code after
writing each line or two, so you know exactly where the error was
introduced.
- Once you're comfortable with the provided examples, start your
own vertex & fragment shader to simulate wood grain. To start, mimic
the rings of tree growth along a primary axis with alternating
cylindrical bands of color. Then, you can use a noise function to add
geometric variations to the bands to look more natural (so they aren't
perfect circles). Experiment with subtle variations in the color as
well. Finally, you can add variations in the normal to represent the
ridges in the grain visible in the specular highlight of polished
wood. In addition to the code, submit screenshots of your wood grain
shader. Include references to any online resources you used for this
portion of the homework.
- For extra credit, create another complex shader and submit that
code and screenshots of the results. In your README.txt file describe
your target result and what was necessary to create the result.
Yet another option for extra credit is to mix the shaders with the
stencil mirror and/or stencil shadows.
- Basic Code
(Makefile,
argparser.h,
boundingbox.cpp,
boundingbox.h,
camera.cpp,
camera.h,
glCanvas.cpp,
glCanvas.h,
main.cpp,
matrix.cpp,
matrix.h, and
vectors.h)
Similar to the previous assignments.
- Half-Edge Quad Mesh Data Structure (edge.cpp,
edge.h,
hash.h,
mesh.cpp,
mesh.h,
triangle.h, and
vertex.h)
Similar to the triangle half-edge data structure you implemented in
assignment 1.
- Rendering (render.cpp)
The code for rendering the mesh with stencil buffer tricks.
- Shaders
(load_shaders.cpp,
orange.fs,
orange.vs,
checkerboard.fs, and
checkerboard.vs)
The code for loading, linking, & initializing GLSL shaders, and two
example shaders.
- Test meshes (bunny_1k.obj,
bunny_200.obj,
bunny_40k.obj,
cube.obj, and
sphere.obj)
Please read the Homework information page again before submitting.
|