**Objectives:**

To Learn about lighting and material properties

We talked about various ways of calculating vertex normals (which are required
for the smooth shading used by OpenGL). We could take the cross product of
two vectors in the plane of a polygon and use this for the normal at all
the vertices of the polygon. However, if we're using a fixed light direction
this will give exactly the same lighting at each interior point. We could
instead come up with different normals at all the vertices. The way to estimate
these is to average the normals of all polygons (usually triangles) which
meet at a given vertex.

Let's look at an example that we had in class. We used a tetrahedron with
vertices at (0,0,0), (1,0,0), (0,1,0), and (0,0,1). What would the normal
be at the origin? One way to compute the normal is to find two vectors and
compute their cross products, right?

So, for the three faces that meet (left, right, and bottom) the normals
are vectors:

n(right) = 0 i + 0 j - k

n(bottom) = 0 i - j + 0 k

<-1,0,0>, <0,-1,0> and <0,0,-1>, so the
normal would be in the direction <-1,-1,-1>. (We'd divide the three
components by sqrt(3) if we want the normal 'normalized'). Try finding the
normals at the other three vertices. Then try lighting the tetrahedron using
the four normals you've estimated. The result should be a rounded tetrahedron,
much less stark than that obtained with uniform lighting on each face. There
are other ways to get surface normals. In the case of a mathematically defined
surface, such as a sphere, we can calculate the precise normal at each point.
In third semester calculus you learn about finding the "gradient vector"
to get the normal this way. If we have a surface z = f(x,y), then differentiating
the function with respect to x gets the tangent slope in the x direction,
and differentiating with respect to y gets the tangent slope in the y direction.
The cross product of the two resulting tangent vectors obtains the normal
vector. We won't get into this, but I hope you're motivated to pursue more
mathematics if you're interested in graphics.

There are a few predefined shapes -- spheres, cylinders, toruses -- available in OpenGL. Here's a program which rotates a light in a circle a fixed height above a torus:

/* A shiny torus illuminated by a light source rotating

overhead. */

#include <math.h>

#include <GL/glut.h>

double t = 0;

const double PI2= 2*3.14159265; // 2 PI

// This is global so that it can be changed in the idle function

GLfloat light_position[] = { 2.0, 4.0, 0};

void display()

{

int i;

glClearColor(1,1,1,0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(0,2,4,0,0,0,0,1,0);

glRotatef(90,1,0,0); // flip the torus on its side

// Torus inner radius .5, outer radius 1

// 20 latitudes and 20 longitudes, sort of

glutSolidTorus(.5,1,20,20);

glFlush();

glutSwapBuffers();

}

void myinit()

{

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat mat_shininess[] = { 50.0 };

GLfloat mat_amb_diff[] = { 0.1, 0.5, 0.8, 1.0 };

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,

mat_amb_diff);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glEnable(GL_DEPTH_TEST); /* enable z buffer */

glMatrixMode(GL_PROJECTION);

// gluPerspective is an alternative to glFrustum in which

// the 'lens' is specified by angle and aspect ratio rather

// than frustum coordinates

// The near and far planes have the same meaning as before.

gluPerspective( /* field of view in degree */ 40.0,

/* aspect ratio */ 1.0,

/* Z near */ 1.0, /* Z far */ 10);

glMatrixMode(GL_MODELVIEW);

}

void idle(){

light_position[0]=2*cos(t);

light_position[2]=2*sin(t);

t+=.1;

if(t>PI2)t-=PI2;

glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glutPostRedisplay();

}

int main(int argc,char** argv)

{

glutInit(&argc,argv);

glutInitWindowSize(800,600);

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);

glutInitWindowPosition(100,100);

glutCreateWindow("Cubes");

glutDisplayFunc(display);

glutIdleFunc(idle);

myinit();

glutMainLoop();

return 0;

}

Here's a typical snapshot:

Our specular light is all white -- if we change it to red, then our blue-green
torus will reflect very little of it. The animation in the idle call back
changes the position of the light. In OpenGL, you can define several light
sources -- up to 8. The shininess of the material is 50 -- this translate
roughly to the exponent of the cosine of the angle between the viewer and
the ray reflected from the light source. If we reduce this number, the surfaces
appears softer, more like plastic than metal.

**Lab Activity (1)**

Try the above code with __four__ different value sets for values in the
following line:

GLfloat light_position[] = { 2.0, 4.0, 0};

1) Light at the center (0, 0, 0),

2) Keep only the x component and set the rest to 0,

3) Keep only the y component and set the rest to 0, and

4) Keep only the z component and set the rest to 0.

Based on your observations you have made by running the above 4 cases, can you make a conclusion on the effect of light

source position and the appearance of the object.

**Lab Activity (2)**

Modify the code such that the above torus appears in red. A quick way to
do this is to make a change in the:

GLfloat mat_amb_diff[] = { 0.1, 0.5, 0.8, 1.0 };

If you have done it a different way, let me know.

**Lab Activity (3)**

You should try fiddling with the parameters in this program to get a feel
for what they do. Here is what you will create next. To create this shape,
you will add a new torus that is smaller than the one above and will rotate
it 90 degree. You need to play with the dimension a bit.

**Lab Activity (4)
** Here is what you create next. To create this one, you
will use two different material for the two toruses that you had created
in the previous section.

Try to create the top view and the side view of the above object. Keep all three options in the program such that by setting a flag value, one can get one of the views. Submit an electronic copy of the program with all options in it. Leave a comment at the location of the flag that changes the views, so I can test your program. You may use different functions for each views, as you wish. Submit a hard copy of the program and snap shots of the three views.