# Lab(4) - Graphics

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(left) = - i + 0 j + 0 k
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 rotatingoverhead.  */#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 functionGLfloat 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.

Post-lab
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.