Programming Assignment 4

Due: Tuesday, April 22, 2008 at 11:59pm. This project is worth 15% of your grade.

The goal of this assignment is to render a simple virtual scene with shadowing using the 2-pass shadow algorithm. You will use GLUT to render basic shapes in the scene that will cast shadows on one another. You will also light the the models using OpenGL's lighting and materials functions. Your program should allow the user to move the viewpoint and light around the scene.

In the 2-pass shadow algorithm, the scene is first rendered from the point-of-view of the light source. In the second pass, the scene is rendered from the eye point. Each pixel rendered from the eyepoint is then checked against the z-buffer of light source to determine if it is in shadow. If the pixel is in shadow, it's color intensity is reduced by an appropriate amount (try 30 out of 255) for each color component. For example, if the pixel color is (200,100,75), the shadowed pixel color should be (170,70,45). See the figure below for a pictorial of the 2-pass shadow algorithm. The following sections describe each pass in more detail.

Extra Credit (20 points): Implement shadowing based on two light sources. For each light source, if a pixel is not visible from the light source, its color is attenuated (the intensity is reduced). The result is that points that are in shadow with respect to both light sources are darker than those that are in shadow with respect to only one light source. Allow the user to move both light sources by specifying another set of keys for moving the second light source (for example, use the s/d/e/x keys).


Virtual Scene

Constrain your virtual scene to be within a 6x6x3 box centered at (0,1.5,0) so that it is sitting on a ground plane at y=0. Your light position and eye point should move on a hemisphere of radius 5 over the box along the A and B directions, looking at the origin (0,0,0). Draw a white ground plane at y=0.

Include at least 5 models from the GLUT library of models in your scene. The following GLUT commands render solid models: glutSolidCube, glutSolidCone, glutSolidTorus, glutSolidDodecahedron, glutSolidOctahedron, glutSolidTetrahedron, glutSolidIcosahedron, glutSolidTeapot.


First Pass

Follow these steps in the first pass:

  1. Render scene from the point of view of the light source (using the light position as the eyepoint)
  2. Obtain and store the modelview matrix, projection matrix and viewport for the light source using glGet -- glGetDoublev for modelview and projection matrices; glGetIntegerv for the viewport.
  3. Use glReadPixels with GL_DEPTH_COMPONENT for the format parameter to obtain the contents of the z-buffer. Note that memory must be allocated for pixels before calling glReadPixels.


Second Pass

Follow these steps in the second pass:

  1. Render scene from the eye point.
  2. Obtain and store the modelview matrix, projection matrix and viewport for the eyepoint using glGet -- glGetDoublev for modelview and projection matrices;
  3. Use glReadPixels with GL_RGB for the format parameter to obtain the contents of the framebuffer and store in an image (matrix of size equal to the framebuffer storing R,G,B values for each pixel).
  4. Use glReadPixels with GL_DEPTH_COMPONENT for the format parameter to obtain the contents of the z-buffer for the eye point. You will need the depth (z) value to unproject.
  5. For each pixel in the image, find out whether it is visible from the point of view of the light by doing the following:
  6. Display the new image containing shadowing using the glDrawPixels function.


Using OpenGL Lighting and Materials

The color of the model surface is determined by the reflective properties of the material (ka,kd, and ks for each color channel). In your ray-casting project, you calculated the diffuse illumination of each polygon as an intensity value and applied it to the polygon's color. In this part of the project, you will instead define light sources and material properties in OpenGL. OpenGL then performs the illumination calculation. Surfaces are smoothly shaded by calling the function glShadeModel(GL_SMOOTH) as done in glInit in the sample code.

To define a light source in OpenGL, you will need to call the following functions to define the ambient, diffuse, and specular components of your light as well as the position of your light. Lights are specified in OpenGL using GL_LIGHTn, where n is the light number. For one light source, use GL_LIGHT1 as below:

      glLightfv (GL_LIGHT1, GL_AMBIENT, ambient_light);
      glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse_light);
      glLightfv (GL_LIGHT1, GL_SPECULAR, specular_light);
      glLightfv (GL_LIGHT1, GL_POSITION, light_position);
      glEnable (GL_LIGHT1);
      glEnable (GL_LIGHTING);

ambient_light, diffuse_light, and specular_light are arrays of 4 floating point values for red, green, blue, and alpha. light_position is an array of 4 floating point values for x,y,z,w. To move your light source, you will need to modify the values in the light_position array. This sample code shows how this is done. You can use a regular positional light source or a spotlight. To specify a spotlight, set the GL_SPOT_DIRECTION, GL_SPOT_EXPONENT, and GL_SPOT_CUTOFF parameters using the glLightfv function. You may hardcode the values for these parameters. Allow the user to toggle between using OpenGL lighting and no lighting by pressing the L key. To enable and disable lighting, use the OpenGL command glEnable and glEnable with the parameter GL_LIGHTING.

For ambient, diffuse, and specular illumination of surfaces, you will need to specify the ambient, diffuse, and specular coefficents (red, green, blue, and alpha) of materials applied to your models. The coefficents determine how the surface reflects red, green, and blue color channels, giving the surface its color. For specular surfaces, you will also need to specify the glossiness by setting the GL_SHININESS parameter of the material. To specify the coefficients in OpenGL, use the glMaterialfv command as you would the glColor3f command (right before specifying vertex coordinates). For example, a red surface may be specified as follows:

      GLfloat red_amb_mat[] = {0.2f, 0.0f, 0.0f, 1.0f};
      GLfloat red_diff_mat[] = {0.5f, 0.0f, 0.0f, 1.0f};
      GLfloat red_spec_mat[] = {0.5f, 0.0f, 0.0f, 1.0f};
      GLfloat red_glossy = 0.2;
      glMaterialfv (GL_FRONT, GL_AMBIENT, red_amb_mat);
      glMaterialfv (GL_FRONT, GL_DIFFUSE, red_diff_mat);
      glMaterialfv (GL_FRONT, GL_SPECULAR, red_spec_mat);
      glMaterialfv (GL_FRONT, GL_SHININESS, red_glossy);


Rotating Eye and Light Positions

Your program must allow the user to move both the eye point and light positions on a hemisphere over the box, looking at the origin (0,0,0). The eye point should move when the user presses the up/down/left/right arrow keys. Up/down moves the eye point along the longitudinal direction (A direction in figure above), and left/right moves the eye point laterally (B direction). The light source should move when the user presses the home/end/page-up/page-down keys. Home/end moves the light source along the longitudinal (A) direction, and page-up/page-down moves the light source laterally (B direction). Use the OpenGL function gluLookAt to change the viewpoint when rendering from the point of view of the light source or eye point.

For the extra credit, allow the user to move both light sources by specifying another set of keys for moving the second light source (for example, use the s/d/e/x keys).


User Interface


Implementation Requirements

(Some of these requirements are for ease of grading)

Submission


Grading

The grade breakdown is as follows:



Back to Class Page