CS 450/550 -- Fall Quarter 2022

Project #4

100 Points

Due: October 31


This page was last updated: September 13, 2022


The goal of this project is to create a 3D animated scene that demonstrates dynamic OpenGL lighting.


  1. Create a 3D scene consisting of at least 3 objects and at least 3 light sources:
    Category Minimum number Minimum number
    Light motion 2 stationary 1 moving
    Light types 1 point 1 spotlight
    Light colors 1 white 1 colored
    Object material 1 shiny 1 dull
    Object glShadeModel 1 GL_FLAT 1 GL_SMOOTH
    Object motion 1 stationary 1 moving
    Object texture 1 lighted and textured 1 lighted, not textured

  2. Notice that there really only needs to be 3 light sources total. Clearly you can be double-dipping with the motion, types, and colors.

  3. Be sure to spread things out enough that we can see the effect of the 3 lights.

  4. Use RGB color for each object's GL_FRONT.
    Use a shade of gray for each object's GL_BACK.

  5. Put small spheres at the light source locations so that you and I can see where they are. Make each sphere the same color as the light source it is representing. Don't use lighting on the light-source spheres. Just make them glColor3f blobs with lighting disabled.

  6. Feel free to use the OsuSphere, the GLUT solids, or OBJ files for your objects.

  7. However, I recommend you use all OsuSphere objects at first, get the lighting working, then experiment with other objects.

  8. If you use OBJ files, they will need to have per-vertex surface normal vectors. Edit the .obj file and look for lines that begin with the letters vn to see if it does.

  9. If you use OBJ files for the textured object, that file will need to have per-vertex texture coordinates to see if it does. Edit the .obj file and look for lines that begin with the letters vt.

  10. For the textured and lighted object, remember to use a texture environment of GL_MODULATE.

  11. Warning: among the GLUT solids, only the sphere and teapot have texture coordinates built into them.

  12. Remember that light positions automatically get transformed by the GL_MODELVIEW transformation as it exists at the moment you specify the light position. You can't prevent this from happening. You can only control the GL_MODELVIEW matrix to be what you need it to be at the time and control where in your code you specify the light source positions.

  13. Enable the following keys:
    '0'Toggle light #0 off/on
    '1'Toggle light #1 off/on
    '2'Toggle light #2 off/on
    'f'Freeze/un-freeze the animation
    Even if you weren't required to turn lights off and on, you would want to do it anyway as part of a lit-scene debug process. This really helps debug lighting programs.

  14. You can do anything with the attenuation that you'd like.

  15. Feel free to use the "Shortcut" functions from the Lighting notes.

  16. Help us get the grading right! Even though you have lots of flexibility about how to create the scene, you must make it obvious to us that it is handling the lighting correctly! Narrating the video will help a lot.

Implementing the Keyboard Keys

The 'f' key is implemented by turning the Idle Function on and off, like in Project #3:

	bool Frozen;		// declare this as a global

	Frozen = false;		// set this in Reset( )

	// in Keyboard( ):
	case 'f':
	case 'F':
		Frozen = ! Frozen;
		if( Frozen )
			glutIdleFunc( NULL );
			glutIdleFunc( Animate );

The number keys are implemented something like this:

	bool Light0On, Light1On, Light2On;		// declare these as globals

	Light0On = Light1On = Light2On = false;		// set these in Reset( )

	// in Keyboard( ):
	case '0':
		Light0On = ! Light0On;

	case '1':
		Light1On = ! Light1On;

	case '2':
		Light2On = ! Light2On;

	// in Display( ):

	if( Light0On )
		glEnable( GL_LIGHT0 );
		glDisable( GL_LIGHT0 );

	if( Light1On )
		glEnable( GL_LIGHT1 );
		glDisable( GL_LIGHT1 );

	if( Light2On )
		glEnable( GL_LIGHT2 );
		glDisable( GL_LIGHT2 );

Timing Your Scene Animation

Deliberately time the animation like we've seen before. Here is a good way to do that. Set a constant called something like MS_PER_CYCLE that specifies the number of milliseconds per animation cycle. Then, in your Idle Function, query the number of milliseconds since your program started and turn that into a floating point number between 0. and 1. that indicates how far through the animation cycle you are. So, in Animate, you might say:

int ms = glutGet( GLUT_ELAPSED_TIME );
Time = (float)ms / (float)MS_PER_CYCLE;		// [0.,1.)
and then in Display, you might use that 0.-1. number something like this:
 glRotatef( 360.*Time, 0., 1., 0. );

Using Objects You Get From Elsewhere

If you want to bring in another 3D object to work with (and there are a lot of them on the web), look for something in a .obj format.

If you want to load a .obj file as part of one of your projects, incorporate the file loadobjfile.cpp into your own code. Use this by placing the .obj object into a display list:

int DinoDL;				// declare as a global

// in InitLists( ):
DinoDL = glGenLists( 1 );
glNewList( DinoDL, GL_COMPILE );
LoadObjFile( "dino.obj" );
glEndList( );

// in Display( ):
glCallList( DinoDL );

Warning! Not all obj files have normals and textures. Take a look at the lines in the obj file (it is ascii-editable).
If you see lines of text beginning with vn, it has normals.
If you see lines of text beginning with vt, it has texture coordinates.

Good Lighting is Hard!

One of the things that you are supposed to learn from this project is that lighting is difficult, especially good lighting. (Unfortunately, even bad lighting is hard...) Next time you see a CG-animated movie, look to see how many people in the credits have the word "Lighting" somewhere in their title. There's a reason the list is so long. Look to see how the lighting is used, how it becomes part of telling a story. Some CG movies can end up being lit with hundreds or thousands of light sources (e.g., Coco).


Use the Teach system to turn in your:

  1. .cpp file
  2. A one-page PDF with a title, your name, your email address, a nice screen shot from your program, and the link to the Kaltura video demonstrating that your project does what the requirements ask for. Narrate your video so that you can tell us what it is doing.
  3. In your video, start with all light sources off. Just show the scene with ambient lighting. Then turn one light on, showing the effect of it alone. Then turn it off and turn another light on, showing just the effect of it. And so on.


Don't spin a smooth-shaded lighted sphere about an axis through its center! You can't tell that it is spinning. Same goes for any other 360-degree smooth objects like torii and cones.


Note: you don't get credit for these things by just having done them. You get credit by convincing us that your program's lighting behavior is correct. That is, code that looks correct will only get credit if you have made a scene that demonstrates the correct visual lighting behavior.

Item Points
Lights: 2 stationary, 1 moving 15
Lights: 1 point, 1 spotlight 15
Lights: 1 white, 1 colored 15
Objects: 1 stationary, 1 moving 15
Objects: 1 shiny, 1 dull 15
Objects: 1 GL_FLAT, 1 GL_SMOOTH 10
Objects: 1 textured+lighted 10
Small unlit spheres to show the where the light sources are 5
Potential Total 100