Lab 5: OpenGL Lighting

CSC385 - Computer Graphics

Goal: Learn about lighting by modifying our OpenGL program.

Action:

  1. Modify your project as follows:
    Recompile and run your program. You should see the the purple (somewhat clunky) sphere. It looks more like a circle than a sphere because there is no lighting in the scene to provide visual cues as to the 3D shape. We'll add that next.

  2. Lighting: Specify light
    The first step is to specify the light. Add the following code to the init() function.
    	
    	GLfloat white[] = {1,1,1,1};				// light color
    	GLfloat lightPosition[]={-1,1,1,1};			// light position
    	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);	// setlight position
    	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);		// set diffuse light color
    	glLightfv(GL_LIGHT0, GL_SPECULAR, white);		// set specular light color
    	glEnable(GL_LIGHT0);
    
    The glLightfv() command takes three arguments. The first is the light number, which should be one of the OpenGL constants GL_LIGHTi. The number of lights depends on the implementation, but at least 8 lights are supported. The second is the lighting parameter to be set, also one of the OpenGL constants. The final argument is the value the parameter should be set to. In this case, the value is a vector of floats, as specified by the fv (f for float and v for vector) in the command glLightfv(). (See Woo for a full description of argument specifications.) Note that OpenGL lighting is more flexible than the model we used for raytracing in that a light can provide different colors for diffuse and specular. (For more details on the possible parameters see Woo chapter 5.)

    You might be asking yourself how this specifies a point vs. a directional light. The answer is in lightPosition, which is {-1,1,1,1}. The last term, 1, specifies that the light is a point light. If this were a 0, it would specify a directinal light. The first three terms define the position or direction of the light. For example, setting the light position to {-1,1,1,1} defines a point light situated at the point (-1,1,1) whereas setting the light position to {-1,1,1,0} defines a directional light with direction <-1,1,1>. (I know... I'm just the messenger!)

  3. Lighting: Specify material properties
    The next step is to specify the material properties of the sphere. Replace the glColor3f()command in display() with the following code:
    	GLfloat white[] = {1,1,1,1};			// white
    	GLfloat purple[] = {1,0,1,1};			// purple
    	
    	glMaterialfv(GL_FRONT, GL_DIFFUSE, purple);
    	glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
    	glMateriali(GL_FRONT,GL_SHININESS,50);	
    
    
    Just as with colors, the most recently defined properties apply to an object when it is drawn. (Why? think state machine...)

  4. Lighting: Enable
    The final step is to enable lighting. Add the following code to init().
    	
    	glEnable(GL_LIGHTING);
    

    Recompile your code and run it. You should now see the effects of lighting.


  5. Lighting: Attenuation
    Next lets add some attenuation for our light. Add the following to your init function:
    	
    	float const=1.0;								// constant attenuation
    	float linear=1.0;								// linear attenuation
    	float quadratic=0.5;							// quadratic attenuation
    	glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, const);		// set diffuse light color
    	glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, const);		// set diffuse light color
    	glLightf(GL_LIGHT0, GL_QUQADRATIC_ATTENUATION, const);	// set diffuse light color
    
    Note that we are using glLightf, where the f signifies a float argument.
    Recompile and see what happens. Adjust the attenuation parameter to get some nice fall off on the sphere.


  6. Lighting triangles strips:
    Next create a "ground" for your scene; i.e. a flat surface the sphere will sit on. To do this, we will use a new primitive call a GL_TRIANGLE_STRIP. Add the following after your sphere:
    	
    	glBegin(GL_TRIANGLE_STRIP);
    		glVertexf(-20.0,-5.0,-40.0);
    		glVertexf(-20.0,-5.0,0.0);
    		glVertexf(20.0,-5.0,-40.0);
    		glVertexf(20.0,-5.0,0.0);
    	glEnd();
    
    Recompile and run your program.



  7. There are several issues with the current code that need to be fixed. First, you need to set the material properties for the floor. Use similar code as for the sphere but make the floor a different color. Next, OpenGL needs surface normals in order to compute the lighting (just as you did in the ray tracer). You can define a normal by glNormalf(vx,vy,vz). OpenGL keeps track of the the most recently defined normal, let's call it currNormal. When you create a vertex by a call like glVertexf(-10,-5,10), OpenGL assumes the normal at that point on the surface is currNormal. Since the normal to our floor is <0,1,0> it suffices to call glNormalf(0,1,0) immediately before the call to glBegin(GL_TRIANGLE,STRIP). Make these changes and recompile your program.

     

  8. Lighting Refinements
    You probably won't see much fall off in lighting across the ground. The reason for this is that OpenGL computes surface color at the vertices and then interpolates at interior points. In order to see localized lighting effects you need vertices in regions of lighting change. Modify your ground to comprise several several triangle strips, each with many smaller triangles. Recompile and run your program.

Deliverables: Email a your OpenGL.cpp to me and hand in a hard-copy in class next Tuesday. If you haven't handed in a file for Lab 4, you can hand in one file for both.