CS155 Computer Graphics
Cheesy Shadow Labs
OpenGL does not have built-in support for shadows but there are several
methods for creating them. One is to project the vertices of
each of your objects onto the ground then use those vertices for a new
primitive that is colored black.
Today you'll implement this approach for a simple scene.
-
Download the project folder shadow.zip.
Compile the program and run it. You'll see a red floor, a blue cube, and a white background.
-
The next step is to draw a basic shadow. To do so you need to
- Create the shadow projection matrix. There is actually a routine that does this for you, all you need to do is call it.
- Next push the current matrix.
- Now multiply the current matrix by the shadow matrix. (Check out glMultMatrixf().)
- Declare the diffuse and ambient material properties for the shadow; i.e. black.
- Redraw the cube.
- Pop the current matrix.
Compile and run the code. Problem? Currently the shadow occupies the
same place as the floor so you may not see it.
To check that it is there, comment out the floor-drawing code,
re-compile and run the program. You should see now be able to see the
shadow.
-
Of course we want to have a floor. The problem of drawing two things in the same place is not uncommon and OpenGL
provides a solution, called polygon offset. Read this article about
the command glPolygonOffset(f,u), which
you should call in your init routine. (Check out the documentation to help figure out good values for f and u.)
You also need to enable polygon offset before drawing the shadow (use glEnable(GL_POLYGON_OFFSET_FILL)) and disable it afterwar
(use glDisable(GL_POLYGON_OFFSET_FILL)).
-
Rather than drawing a black shadow, we'd like to blend it with the
floor. To do this you need to
define a blending function, glBlendFunc(sFactor,dFactor), set the alpha
channel of the shadow color, and enable blending, glEnable(GL_BLEND)
. Check online documentation for details on these commands. Be sure to
disable alpha blending when you are done with the shadow.
-
The shadow will not look right because each polygon of the cube is producing its own shadow. The final
shadow is darker in regions where several polygon shadows are drawn. To avoid this you need to use the stencil
buffer. Enable the stencil buffer before the floor is originally drawn. Whenever a pixel is drawn to the
frame buffer, you should write a "3" to the stencil buffer. When drawing the shadow, compare the stencil
buffer to 2. If the stencil value is greater than 2 then draw the shadow pixel and replace the stencil value
by 2. A shadow will never be drawn more than once for any pixel and only on pixels where the floor has
been drawn. Check online documenation for details on on the stencil buffer.
That is it!