In this project, you will implement an interactive system for shading of a 3D object.
1 Assign normal vectors
In OpenGL, you need to specify a normal vector to each vertex of a face (polygon). For example, the following statements indicate that the vertex (1,1,1) is assigned with a normal vector (1,0,0).
glNormal3f(1, 0, 0);
glVertex3f(1, 1, 1);
If a face consists of 4 vertices, then there are 4 pairs of glNormal3f() and glVertex3f().
Strictly speaking, a normal vector of a vertex (that is a point) is not well-defined. In other words, we
may have different ways to assign a normal vector to a vertex v. A simple way is to assign the normal
vector of the face that v belongs to as v’s normal vector. Note that the normal vector of the face is
uniquely determined by any three vertices as long as these vertices are not in the same line. Therefore,
the same vertex can be assigned by different normal vectors because it may belong to multiple faces.
The above simple way can be used to assign normal vectors in flat shading. But for Gouraud shading,
you will need to average multiple normal vectors “inherited” from intersecting polygons to compute the
final normal vector of a vertex.
2 Create light sources
In OpenGL, you can create a light source with a specific property, such as position, color and direction
by a function called glLightfv() or glLightf(), as follows:
void glLightfv(GLenum light, GLenum pname, const TYPE *param);
void glLightf(GLenum light, GLenum pname, TYPE param);
glLightfv() has three function parameters. The first one indicates the identity of a light source, which
can be one of the values from GL LIGHT0 to GL LIGHT7. The second one indicates the name of a
property, which can be one of the following values
GL POSITION
GL AMBIENT, GL DIFFUSE, GL SPECULAR
GL SPOT DIRECTION
1
There are some other properties, such as GL SPOT EXPONENT, GL CONSTANT ATTENUATION,
etc. But we will only consider the properties of position, color and direction, in this project. The
third parameter indicates the values of a specific property of the light source. Note that the values of a
property of position, color or direction are usually reprsented as a vector, and thus we use the function
glLightfv(). For example, the following statement specifies the position of LIGHT0 to be (1.0, 1.0, 1.0,
1.0) (homogenous form).
GLfloat light_position = {1.0, 1.0, 1.0, 1.0};
void glLightfv(GL_LIGHT0, GL_POSITION, light_position);
In this project, you will create 2 light sources. One is initially located in (1.0, 0.0, 0.0, 1.0) and the
other is initially located in (-1.0, 0.0, 0.0, 1.0).
After a light source is created, you will need to enable the light source by glEnable(), such as the
following:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
3 Shading
In the class, we have learned three shading models: flat, Gouraud, and phong. With the flat model, the
colors of points in the same face are identical. So, it is common that the flat model is not good at retaining
3D strucutre of an object. With the Gouraud model, the colors of points in a face are interpolated by the
colors of the vertex of the face. Recall that the colors of different vertices of a face are usually different
even if they are assigned with the same normal vector. Therefore, the colors of points in a face are
different.
OpenGL provides implementation of the flat and Gouraud shading. In OpenGL, you can specify a
shading model by the following function:
void glShadeModel(GLenum mode);
where mode can be GL FLAT or GL SMOOTH. GL SMOOTH implies the Gouraud shading model.