Exercise 4: Appearance
This exercise covers OpenGL functionality to control model appearance
including surface properties
such as colour and reflectance, scene illumination and shading.
Copy the exercise programs from /vol/www/ee/Teaching/Courses/CGI/exercise4
1. Colour Tetrahedra
This example demonstrates the use of OpenGL flat and smooth shading models
on
surface colour.
(i) Look at the example color_tetra.c.
Two arrays are used to specify the vertices and their colour for
a tetrahedra.
Compile and run the program.
This shows the wireframe outline of the polygon with each polygon having a single colour.
There are two shading models for OpenGL 'flat' and
'smooth' for flat shading the colour of
each vertex is treated
independently for smooth shading the colour is interpolated.
For a polygon with flat shading the colour for the entire
polgon is taken as the colour of the
first vertex.
Change the shade model specified by glShadeModel()
to smooth shading GL_SMOOTH.
The colours are now interpolated along the tetrahedra edges.
(ii) Now revert to flat shading GL_FLAT and fill in the polygons with
glPolygonMode(GL_FRONT,GL_FILL);
This should give a single colour for each polygon corresponding to the first vertex.
Change the smoothing model to GL_SMOOTH colours
are now interpolated between
vertices so that the polygons are
filled.
(iii) Extend the program to rotate the tetrahedra
and the viewpoint.
2. Teapot
This example demonstrates the use of lighting together with surface
reflectance properties.
Four steps are required for OpenGL to light a scene:
(1) Define normal vectors for each vertex
(2) Setup the lights (location, direction, type)
(3) Select a lighting model
(4) Enable hidden surface removal.
(5) Define material properties for objects
Having done this OpenGL can render the illuminated
scene based on the surface appearance
under the illumination conditions.
(i) Compile and run the program teapot.c
This shows a smooth shaded teapot without any scene
illumination which appears as
a coloured silhouette against the
white background.
(ii) OpenGL lights are specified using glLight*() which specifies the light source type and
corresponding properties such as position, colour direction.
The command is specified as
follows:
glLight*(light,
type, param);
light - is the light number GL_LIGHT0-8
type - is the type of lighting ambient, diffuse, specular, position, spot,
.....
param - set of associated
parameters for a particular type of light
Add a single positional light and enable lighting as follows in the function initgl():
glLightfv(GL_LIGHT0,
GL_POSITION, light0_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
and define the light position as a global static variable:
static GLfloat light0_position[] = {1.0,1.0,1.0,0.0};
Compile and run the program shows the effect of
the illumination on the shaded mat surface
of the teapot model.
However, the model is not shaded directly as the shading does not
take into account the ordering of
surfaces relative to hte viewer. For instance the rim
of the
teapot is incorrectly shaded such
that you see the lid which is hidden from view.
(iii) Hidden surface removal renders the scene such that the surface closest
to the surface which
appears in the image is
the one closest to the viewer ie the visible surface.
In OpenGL this
is achieved using a
'depth buffer', for each rendered pixel the depth buffer stores the distance
to the surface. If a new surface is closer to
the viewer then the value of the pixel is replace otherwise
it is discarded.
To enable depth buffering in OpenGL and GLUT
we must initialise the depth buffer with the
following command in
main():
glutInitDisplayMode(...
| ...| GLUT_DEPTH);
this initialises a depth buffer along with the other buffer ie GLUT_RGB, GLUT_SINGLE/DOUBLE
The use of depth buffering must then be
enabled in OpenGL in initgl() by:
glEnable(GL_DEPTH_TEST);
Finally, when we clear the screen for
each display the depth buffer must also be cleared:
glClear(GL_COLOUR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT);
Implement depth buffering, compile and run the program.
The teapot should now appear correctly shaded with a mat surface finish.
(iv) To change the apperance of the teapot surface
we can adjust the surface properties such
as shininess. Add the
following surface properties and redisplay the teapot.
static GLfloat
mat_specular[] = {1.0,1.0,1.0,1.0};
static GLfloat mat_shininess[] = {50.0};
glMaterialfv(GL_FRONT,
GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT,
GL_SHININESS, mat_shininess);
This should now produce a much more realistic teapot.
Try rotating the teapot about the y-axis.
(v) Change the surface colour to see the combined effect of illumination,
colour and reflectance.
To do this you must not only set the object colour as
before but also enable material colour
In initgl() enable material colour:
glEnable(GL_COLOR_MATERIAL);
Now specify the teapot colour as before using glColor3f()
Using the function glColorMaterial() you can efficiently apply material properties.
To apply colour just to the front facing polygons
illuminated for the ambient reflectance
component
specify:
glColorMaterial(GL_FRONT,
GL_DIFFUSE);
Note: This specifies the mode for applying teh material colour - only one mode can be specified
at one time. Repeated calls are
required to set different colours for front/back faces if
back faces are visible.
(vi) Extend the program to dynamically control the light position, view
direction, and surface
properties using
key-board input. Note transformation of light sources is treated as with other
geometric primitives
using the modelview matrix.
(vii) Experiment with other surface material properties ambient, diffuse. specular, emission....