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).
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.
Follow these steps in the first pass:
Follow these steps in the second pass:
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);
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).
(Some of these requirements are for ease of grading)