
Roberto Toldo,
<nome.cognome@univr.it >
Hit the space bar for next slide
Because the world is not made up of wireframe and flat-shaded models, the OpenGL interface provides a lighting model that allows objects to be more realistically rendered. When lighting is active, models appear to be lit by one or more light sources that can be any color and be positioned anywhere in the scene. Models can also have a variety of material properties ranging from dull to shiny and even luminescent. Different material properties can give the appearance of, for example, plastics or specific metals.
The OpenGL lighting model is just that--a model. It would be impossible to completely represent the interaction of photons of light with atoms that comprise object materials. Instead, the OpenGL lighting model allows you to specify parameters that approximate the way light behaves in the real world. The result, although not physically accurate, gives reasonable results while maintaining interactive performance.
Using OpenGL lighting is a matter of defining properties that specify how a polygon should be colored. When not using lighting, you explicitly specify a color or colors. When flat shading a polygon, you assign one color for all vertices of the polygon. Smooth shading involves assigning a different color to each vertex. The system then smoothly interpolates those colors across the polygon.
Two other polygon shading methods do not involve specifying a color at all. Instead, the system computes the color for you based on lighting. First, in flat-shaded lighting you specify one surface normal for the entire polygon. Based on this surface normal and other parameters that you define, the system computes a color and uses that color to fill the polygon.
Finally, complex lighting, which is the usual way to use lighting, involves specifying a surface normal for each vertex. The system computes the color at each vertex and smooth shades as before.
In order to use lighting, models must be tessellated. That is, the theoretical surface must be approximated by many polygons. The more polygons the surface is broken into, the better the resultant image, and of course, the slower the system.
The polygons that make up the model must include surface normals. A surface normal is a unit-length direction vector that is perpendicular to the theoretical surface. For lit, flat-shaded polygons, one normal per polygon must be specified. For lit, smooth-shaded polygons, one normal per vertex must be specified. Normals are specified using the glNormal3*() calls.
Besides tessellating the models and specifying surface normals for the polygons or vertices, several other parameters must be set. These parameters are known as lighting resources. Lighting resources fall into three categories: lighting models, light sources, and materials.
The lighting model describes how the overall scene behaves: overall scene illumination, how the eye position should be modeled, etc. The light sources are individual sources of light. For each light source, properties such as its position, color and intensity can be defined. Materials are used to describe the objects in the scene. A material has properties such as base color, shininess, and so on.
Once the resources have been specified, they must be enabled to become active. Only one lighting model and one material may be active at any given time. Multiple light sources can be enabled within the lighting model.
Two types of light sources may be defined: local and infinite. A local light source has the w component of its position specified as 1.0. The x, y, and z of the position are then the actual position of the light source and subject to transformation by the ModelView matrix at the time it is bound (more on moving lights in a moment). Typically, using a local light source gives more accurate results but incurs a non-negligible performance penalty.
An infinite light source has 0.0 as its w component. In this case, the light source is treated as being infinitely far away, with its x, y, and z position specifying the direction of its rays (from x,y,z to the origin). Again, this direction is transformed by the ModelView matrix at the time of binding.
Because the light source position is transformed by the current ModelView matrix, the place at which glLight*() is called can have a significant effect on the behavior of the light. Specifying the light position before the viewing transformation causes the position of the light to be relative to the eye position. Specifying the light position after the viewing transformation, but before any modeling transformations, causes the light position to be relative to "world" coordinates. Finally, the light may be made to move by specifying the light position after modeling transformations such as rotate and translate. In general, think of the light position as you would think of any other object you might draw. Its position is dependent on the state of the current transformations.
The coloring of any point, line, or polygon may be determined using the OpenGL lighting model. The process for lighting points and lines is identical to the process of lighting polygons: at least one light model, light source, and material must be specified. Each point should have a vertex normal assigned to it. Flat-shaded lines are generated by assigning one vertex normal to each line. Smooth-shaded lines have one normal for each vertex.
Once a material is specified it is often desirable to make modifications quickly to that material. This is useful for applications in which an object's material is being edited or where you wish to assign a slightly different material to each vertex of a polygon.
To modify a material quickly, use glColorMaterial(). This allows normal color commands, such as glColor3f(), to modify specific properties of the current material. First, call glEnable(GL_COLOR_MATERIAL). Then call glColorMaterial() to specify which material property will be the target of the fast material changes. For example, calling glColorMaterial(GL_DIFFUSE, mat_diffuse) would cause subsequent calls to glColor3f to modify the diffuse component of the current material. Other material components can be modified using glColorMaterial(). Remember to return to the default mode by calling glDisable(GL_COLOR_MATERIAL) when you are finished modifying the material so that later color commands do not cause unexpected results.
The color at each vertex is calculated using the following equation:


ME - material's emission property
SA - scene ambient term, from light model definition
MA - material ambient reflection property
The scene ambient term (SA ) is effectively scaled by the material ambient reflection (MA).

LA - light source ambient property
MA - material ambient property

LD - light diffuse property
MD - material diffuse property
N - vertex normal vector
L - vector between vertex and light
Represents the direction of the light for infinite light sources (faster)
Computed at each vertex for local light sources


Specular reflection depends on viewpoint
LS - light specular property
MS - material specular property
N - vertex normal vector
H - vector halfway between light and view vectors
s - shininess; s = 0 disables specular (faster)


How the light falls off with distance
k0 - constant attenuation property (from light source definition)
k1 - first order (linear) attenuation property (from light source definition)
k2 - second order attenuation property (from light source definition)
d - distance from light source to vertex
At the completion of this lecture, you will be able to
Notes:
Raster (framebuffer) images can be used as textures.
In OpenGL 1.0-1.1, three-dimensional textures are available if the EXT_texture3D extension is supported. Starting with OpenGL 1.2, 3D textures are a core feature.
A one component texture contains Luminance, Intensity, or Alpha data. Examples: Wood, grass, sand ![]() |
A two component texture contains Luminance and Alpha (transparency) data. Examples: Trees, clouds
|
A three component texture contains Red, Green, and Blue values. Examples: Fabrics, bricks ![]() |
A four component texture contains Red, Green, Blue, and Alpha values. Examples: Objects ![]() |
Notes:
Fewer components may lead to faster performance, however, word aligned data may be faster in some cases.
Library tutorial/lib/liboglprog.a provides a routine that loads an SGI format .rgb(a) image file for use as a texture:
unsigned * read_texture(char *name, int *width, int *height,
int *components)
Example:
char *imageFileName = "fish.rgba"; GLubyte *image; int imageWidth, imageHeight, components; image = (GLubyte *) read_texture(imageFileName, &imageWidth, &imageHeight, &components);
Notes:
read_texture() is used in this course so that the texture example programs, demos, and sample answers compile and run under both IRIX and Windows NT.
To load .bmp files under Windows, you can use auxDIBImageLoad("filename.bmp"). This routine is in glaux.lib, which must be added to the list of Project Settings Link Object/library modules:
#include <GL/glaux.h>
AUX_RGBImageRec* texture;
texture = auxDIBImageLoad("filename.bmp");
// ... later, to create texture
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
texture->sizeX, texture->sizeY,
GL_RGB, GL_UNSIGNED_BYTE,
texture->data);
The diagram illustrates the alignment of texture data for 1, 2, 3, and 4 component textures, respectively:

Notes:
The source for read_texture() is in the utility library file "tutorial/lib/texture.c".
Applying textures (images) to polygons.
![]() |
The basic texture mapping steps are:
|
Notes:
Texture mapping is a technique that applies an image onto an object's surface as if the image were a decal or cellophane shrink-wrap. The image is created in texture space, with an (s, t, r) coordinate system. A texture is a one-, two-, or three-dimensional image and a set of parameters that determine how samples are derived from the image.
OpenGL defines defaults for all of the texture parameters in step 2. In many cases, you can rely on these defaults.
Later you will see how to let OpenGL provide texture coordinates for you.
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Notes:
See the man page for the full list of values available for the arguments target, internalformat, format, and type.

Notes:
gluScaleImage() uses linear interpolation and box filtering to scale an image to the requested size.
When shrinking an image, gluScaleImage() uses a box filter to sample the source image and create pixels for the destination image.
When magnifying an image, the pixels from the source image are linearly interpolated to create the destination image.
GLint gluScaleImage( GLenum format, GLsizei widthin, GLsizei heightin, GLenum typein, const void *datain, GLsizei widthout, GLsizei heightout, GLenum typeout, void *dataout )
Notes:
format can be one of: GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, or GL_LUMINANCE_ALPHA.
typein and typeout can be one of: GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, or GL_FLOAT.
The storage pointed to by dataout must be allocated by the user.
widthout and heightout must be powers of two (plus border).
Texture coordinates are part of the data that is associated with each vertex.
![]() |
A 2D texture is treated as a 1x1 square whose texture coordinates go from 0.0 to 1.0 in each dimension.
Texture coordinates are assigned to each vertex of a polygon.
Texture coordinates are interpolated as a polygon is filled.
|
void glTexCoord2fv( const GLfloat *v )

Notes:
Example:
glBegin( GL_QUADS );
glTexCoord2fv( t0 ); glVertex3fv( v0 );
glTexCoord2fv( t1 ); glVertex3fv( v1 );
glTexCoord2fv( t2 ); glVertex3fv( v2 );
glTexCoord2fv( t3 ); glVertex3fv( v3 );
glEnd();
There are many variations of glTexCoord for specifying texture coordinates in one, two, three, or four dimensions. glTexCoord1 sets the current texture coordinates to (s, 0, 0,1); a call to glTexCoord2 sets them to (s, t, 0, 1). Similarly, glTexCoord3 specifies the texture coordinates as (s, t, r, 1), and glTexCoord4 defines all four components explicitly as (s, t, r, q).
Texture coordinates can be specified in scalar or vector form as short, int, float, or double.
One texel rarely corresponds to one pixel on the final screen image.
Magnification Filter |
Minification Filter |
Texture information must be magnified ![]() |
Texture information must be minified ![]() |
Notes:
OpenGL provides several filters to magnify or minify the texture. This allows you to make a trade-off between speed and image quality.
As the pictures show, each texel may not be minified or magnified by the same amount. In the magnification case above, the right edge requires more magnification than the left.
void glTexParameterf( GLenum target, GLenum
pname, const GLfloat param )
Notes:
GL_NEAREST is generally faster than GL_LINEAR interpolation.
There are additional magnification and minification filters used only for mipmaps. These are discussed with mipmaps later in this module. For now, be aware that when you are not using mipmaps, you must specify a minification filter.
Magnification |
Minification |
Pixels map to less than one texel.
If GL_NEAREST is specified, then texel 10 is applied to the pixel. If GL_LINEAR is specified, the weighted average of texels 9, 10, 13 and 14 is applied to the pixel. |
Pixels map to more than one texel.
If GL_NEAREST is specified, then texel 17 is applied to the pixel. If GL_LINEAR is specified, the weighted average of texels 12, 13, 17 and 18 is applied to the pixel. |
Notes:
For 1D textures, linear filtering accesses the two nearest texture elements. For 3D textures, linear filtering accesses the eight nearest texture elements.
In the magnification example above,
If GL_NEAREST is specified, the resulting image will be "blocky."
If GL_LINEAR is specified, the result is a smoother looking image.

void glEnable( GLenum mode )
Notes:
If both GL_TEXTURE_1D and GL_TEXTURE_2D are enabled, two-dimensional texturing will be performed.
/* texture.c
* This program reads in a single image from a .rgb file, uses the
* utility routine gluScaleImage() to scale the image, if
* necessary, sets up the minification and magnification filter,
* and then uses glTexImage2D() to load the image into texture
* memory. It then applies the texture to a rectangular polygon
* using explicit texture coordinates.
*
* <a> key - toggle animation on/off
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <math.h>
#include <stdio.h>
#include "texture.h" /* should be in ../../include */
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid animate( GLvoid );
GLvoid visibility( GLint );
GLvoid drawScene( GLvoid );
GLvoid reshape( GLsizei, GLsizei );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid initTexture( GLubyte *, GLsizei, GLsizei );
static GLuint nearestPower( GLuint );
void printHelp( char *progname );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
/* Global Variables */
static GLfloat swim = 1.0;
static GLboolean animateFlag = GL_TRUE;
void
main( int argc, char *argv[] )
{
char *imageFileName = "fish.rgba";
GLubyte *image;
GLsizei width, height;
GLsizei imageWidth, imageHeight, components;
glutInit( &argc, argv );
if (argc < 2) {
fprintf (stderr, "usage: %s [imageFileName]\n", argv[0] );
} else
imageFileName = argv[1];
fprintf(stdout, "using image %s\n\n", imageFileName );
image = read_texture(imageFileName, &imageWidth,
&imageHeight, &components);
/* create a window that is 1/4 the size of the screen */
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 4, height / 4 );
glutInitWindowSize( (width / 2) - 4, height / 2 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( argv[0] );
initTexture( image, imageWidth, imageHeight );
initgfx();
glutKeyboardFunc( keyboard );
glutIdleFunc( animate );
glutVisibilityFunc( visibility );
glutReshapeFunc( reshape );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glutMainLoop();
}
GLvoid
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrates basic texture mapping\n"
"<a> key - toggle animation on/off\n"
"Escape key - exit the program\n\n",
progname );
}
GLvoid
initgfx( void )
{
glClearColor( 0.0, 0.0, 0.0, 1.0 );
}
/* Compute the nearest power of 2 number that is
* less than or equal to the value passed in.
*/
static GLuint
nearestPower( GLuint value )
{
int i = 1;
if (value == 0) return -1; /* Error! */
for (;;) {
if (value == 1) return i;
else if (value == 3) return i*4;
value >>= 1; i *= 2;
}
}
GLvoid
initTexture( GLubyte *image,
GLsizei imageWidth, GLsizei imageHeight )
{
GLsizei sWidth, sHeight;
GLubyte *sImage;
/* Find the largest power of two dimensions that are
* less than or equal to the size of the image
*/
sWidth = nearestPower( imageWidth );
sHeight = nearestPower( imageHeight );
printf( "input image size: %dx%d\n", imageWidth, imageHeight );
printf( "scaled image size: %dx%d\n", sWidth, sHeight );
/* scale texture image to 2^m by 2^n if necessary */
if ( sWidth == imageWidth && sHeight == imageHeight ) {
sImage = (GLubyte *) image;
} else {
sImage = (GLubyte *)malloc( sHeight*sWidth*4*sizeof( GLubyte ) );
gluScaleImage( GL_RGBA, imageWidth, imageHeight,
GL_UNSIGNED_BYTE, image,
sWidth, sHeight, GL_UNSIGNED_BYTE, sImage );
}
/* Setting the minification and magnification filters
* to nearest instead of linear, may run faster on some
* platforms, with possibly lower quality
*/
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
/* Set the minification filter to something other than
* the default (GL_NEAREST_MIPMAP_LINEAR)
*/
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* load texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sWidth, sHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, sImage);
/* enable 2D texture mapping */
glEnable( GL_TEXTURE_2D );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case 'a': /* toggle animation */
animateFlag = !animateFlag;
if (animateFlag)
glutIdleFunc( animate );
else
glutIdleFunc( NULL );
break;
case KEY_ESC: /* Exit whenever the Escape key is pressed */
exit(0);
}
}
GLvoid
animate( GLvoid )
{
swim = fmod( swim + 0.1, 35.0 );
/* Tell GLUT to redraw the scene */
glutPostRedisplay();
}
GLvoid
visibility( int state )
{
if (state == GLUT_VISIBLE && animateFlag) {
glutIdleFunc( animate );
} else {
glutIdleFunc( NULL );
}
}
GLvoid
reshape( GLsizei width, GLsizei height )
{
GLdouble aspect;
glViewport( 0, 0, width, height );
aspect = (GLdouble) width / (GLdouble) height;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0, aspect, 1.0, 50.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -12.0 );
}
GLvoid
drawScene(void)
{
static float v0[3] = { -1.5, -1.0, 0.0 };
static float v1[3] = { 1.5, -1.0, 0.0 };
static float v2[3] = { 1.5, 1.0, 0.0 };
static float v3[3] = { -1.5, 1.0, 0.0 };
static float t0[2] = { 0.0, 0.0 };
static float t1[2] = { 1.0, 0.0 };
static float t2[2] = { 1.0, 1.0 };
static float t3[2] = { 0.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glPushMatrix();
glTranslatef( -6.0 + swim, 0.2*sin(swim * 3.0), -swim );
glBegin( GL_QUADS );
glTexCoord2fv( t0 ); glVertex3fv( v0 );
glTexCoord2fv( t1 ); glVertex3fv( v1 );
glTexCoord2fv( t2 ); glVertex3fv( v2 );
glTexCoord2fv( t3 ); glVertex3fv( v3 );
glEnd();
glPopMatrix();
glutSwapBuffers();
}
Notes:
This program reads in a single image from a .rgb file, and uses it as a texture. It applies the image to a polygon using explicit texture coordinates. The polygon is then made to "swim" across the window.
The name of the file containing the image can be specified on the command line. If no file is specified, the program attempts to open the file fish.rgba in the current directory.
After reading in the image, the program initializes the texture parameters and loads the texture in initTexture(). Before loading the texture, initTexture() determines whether the image is a power of two in each dimension. If not, it uses the utility routine gluScaleImage() to scale the image. Next it sets both the minification and magnification filter to perform nearest neighbor interpolation. Lastly, it calls glTexImage2D() to load the image into texture memory, and enables 2D texturing.
It then applies the texture to a rectangular polygon using explicit texture coordinates.
The function drawScene() simply uses glTexCoord2fv(), to explicitly assign the texture coordinates to the polygon.
Notes:
* Indicates an optional laboratory exercise.
A set of textures and their related state can be treated as a single object.
So, if you are using more than one texture, always set up the textures as texture objects!
Notes:
Texture objects can be edited--that is, image data can be changed using OpenGL's subtexture capability.
Some systems can keep multiple textures in dedicated texture memory. Texture objects provide some control over residency using priorities (implementation specific).
void glGenTextures(GLsize n, GLuint *texnames)
void glBindTexture(GLenum target, GLuint texname)
void glPrioritizeTextures(GLsize n, const GLuint *texnames,
const GLclampf *priorities)
void glDeleteTextures ( sizei n, uint *textures )
Notes:
In OpenGL 1.0, texture objects are supported by the EXT_texture_object extension (see man glBindTextureEXT). If texture objects are not supported in your runtime environment, display lists (although not as efficient) can be used to increase texture performance.
static GLuint texnames[2];
/* generate unused texture names */
glGenTextures(2, texnames);
/* bind, then define, each texture */
glBindTexture(GL_TEXTURE_2D, texnames[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA,
GL_UNSIGNED_BYTE, redtex);
glBindTexture(GL_TEXTURE_2D, texnames[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greentex);
...
/* in drawScene(), bind the texture you want before drawing each object */
glBindTexture(GL_TEXTURE_2D, texnames[1]);
drawTexturesPolygon(); /* uses greentex */
glBindTexture(GL_TEXTURE_2D, texnames[0]);
drawTexturesPolygon(); /* uses redtex */
Notes:
The first call to glBindTexture() for a given name creates the object. Subsequent calls to glBindTexture() for a given name binds the current texture to that object.
When you create a texture object, its images and parameters are the same as the initial settings of the default texture (texture 0). You set the parameters and the image of a texture object using glTexParameter*() and glTexImage*() . You can edit the texture object in the same way.
Notice that the code must set the minification filter for each of the bound textures. If the minification was not set for either of the texture objects, then the default minification filter would be used for that object.
On IRIX systems, a simple demonstration program can be found in
/usr/share/src/OpenGL/teach/texture/texobj.c

Notes:
As the viewpoint changes, the texture must increase or decrease in size with the size of the object. For example, in texture.c, as the image moves farther away, another sized texture might be more appropriate, rather than trying to filter a large texture down.
If only one resolution of the image is specified, OpenGL has to filter the texture up or down to the appropriate size. A mipmap is an ordered set of pixel arrays representing the same image at progressively lower resolutions.
Using mipmaps allows you to reduce the amount of details on smaller sized objects. (Detail that you probably would not be able to distinguish anyway.)
You want to design the mipmaps in such a way that the transition from one to the next is smooth, so that you do not get shimmering and flashing effects.
You can use the OpenGL Utility routine gluBuild2DMipmaps() to build and load mipmaps automatically.
GLint gluBuild2DMipmaps( GLenum target, GLint
internalformat, GLsizei width, GLint height, GLenum
format, GLenum type, void *data )
Notes:
If you use gluBuild2DMipmaps() to automatically load mipmaps, then for a 2m by 2n texture, m+1 or n+1 (whichever is larger) mipmaps are created and loaded. If necessary, OpenGL will scale the original image to be 2m by 2n.
target must be GL_TEXTURE_2D for OpenGL release 1.0. internalformat must be 1, 2, 3, 4, or one of the specified symbolic constants. In this class, you should always specify GL_RGBA since read_texture() returns 4 components (RGBA). See the man page for the full list of values available for the arguments target, components, format, and type.
To load mipmaps manually:
OpenGL does not care how you compute each level, so different sized mipmaps can be unrelated.
void glTexParameterf( target, GL_TEXTURE_MIN_FILTER, param )
These minification filters use the closest mipmap:
These minification filters use the two closest mipmaps:
/* mipmap.c
* This program reads in a texture from a .rgb file, uses the utility
* routine gluBulid2dMipmaps() to scale and load mipmaps for a single
* texture image, then applies the texture to a rectangular polygon
* using explicit texture coordinates. If no file is given, the
* program creates its own solid color mipmaps. The user can
* switch between the various minification and magnification filters.
*
* <a> key - pause/restart movement
* <m> key - cycle minification filter
* <M> key - cycle Magnification filter
* <R> key - reset image to starting position
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <math.h>
#include <stdio.h>
#include "texture.h" /* should be in ../../include directory */
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid animate( GLvoid );
GLvoid visibility( GLint );
GLvoid drawScene( GLvoid );
GLvoid reshape( GLsizei, GLsizei );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid initTexture( GLubyte *, GLsizei, GLsizei );
GLvoid cycleMinFilter( GLvoid );
GLvoid cycleMagFilter( GLvoid );
GLvoid toggleMoving( GLvoid );
GLvoid resetSwim( GLvoid );
void printFilters( GLvoid );
void printHelp( char *progname );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
#define MAXDIM 128 /* Maximum texture size */
/* Global Variables */
static GLboolean moving = GL_TRUE;
static GLfloat swim = 1.0;
typedef struct {
GLint type;
char *name;
} FilterInfo;
static FilterInfo filters[6] = {
{ GL_NEAREST, "GL_NEAREST" },
{ GL_LINEAR, "GL_LINEAR" },
{ GL_NEAREST_MIPMAP_NEAREST, "GL_NEAREST_MIPMAP_NEAREST" },
{ GL_LINEAR_MIPMAP_NEAREST, "GL_LINEAR_MIPMAP_NEAREST" },
{ GL_NEAREST_MIPMAP_LINEAR, "GL_NEAREST_MIPMAP_LINEAR" },
{ GL_LINEAR_MIPMAP_LINEAR, "GL_LINEAR_MIPMAP_LINEAR" }
};
static int curMagFilter = 0;
static int curMinFilter = 0;
void
main( int argc, char *argv[] )
{
char *imageFileName;
GLubyte *image;
GLsizei width, height;
GLsizei imageWidth = 0, imageHeight = 0, components;
glutInit( &argc, argv );
if (argc > 2) {
fprintf (stderr, "usage: %s [filename]\n", argv[0]);
exit(-1);
} else if (argc == 2) {
imageFileName = argv[1];
fprintf(stdout, "using image %s\n", imageFileName );
image = read_texture(imageFileName, &imageWidth,
&imageHeight, &components);
}
/* create a window that is 1/4 the size of the screen */
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 4, height / 4 );
glutInitWindowSize( (width / 2) - 4, height / 2 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( argv[0] );
initTexture( image, imageWidth, imageHeight );
initgfx();
glutKeyboardFunc( keyboard );
glutIdleFunc( animate );
glutVisibilityFunc( visibility );
glutReshapeFunc( reshape );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glutMainLoop();
}
GLvoid
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrates texture map filtering \n"
"<a> key - pause/restart movement\n"
"<m> key - cycle minification filter\n"
"<M> key - cycle Magnification filter\n"
"<R> key - reset image to starting position\n"
"Escape key - exit the program\n\n",
progname );
}
GLvoid
initgfx( void )
{
glClearColor( 0.0, 0.0, 0.0, 1.0 );
}
GLvoid
initTexture( GLubyte *image, GLsizei imageWidth, GLsizei imageHeight )
{
GLint r, g, b;
int i, dim;
GLint level;
GLubyte *mipmap;
if (imageWidth != 0 && imageHeight != 0 ) {
/* scale texture image, make mipmaps and load texture
* gluBuild2DMipmaps( target, internalformat, width, height,
* format, type, imageArray )
*/
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
imageWidth, imageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, image);
} else {
/* build artificial colored mipmaps to show the changes */
fprintf (stdout, "creating artificial mipmaps\n");
dim = MAXDIM;
for (level = 0; dim >= 1; level++, dim >>= 1 ) {
mipmap = (GLubyte *) malloc(dim*dim*4*sizeof(GLubyte));
b = level & 0x1;
g = (level>>1) & 0x1;
r = (level>>2) & 0x1;
r=!r; g=!g; b=!b;
for ( i = 0; i < dim * dim * 4; ) {
mipmap[i++] = r * 0xff;
mipmap[i++] = g * 0xff;
mipmap[i++] = b * 0xff;
mipmap[i++] = 0;
}
printf("mipmap %d size is %3d X %3d, "
"color is (%d, %d, %d, %d)\n",
level, dim, dim, r, g, b, 0);
/* use the image as a texture */
glTexImage2D(GL_TEXTURE_2D, level, 4, dim, dim,
0, GL_RGBA, GL_UNSIGNED_BYTE, mipmap);
}
}
glEnable(GL_TEXTURE_2D);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filters[curMinFilter].type );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
filters[curMagFilter].type );
printFilters();
}
GLvoid
cycleMinFilter( GLvoid )
{
curMinFilter = (curMinFilter +1) % 6;
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filters[curMinFilter].type );
printFilters();
}
GLvoid
cycleMagFilter( GLvoid )
{
curMagFilter = (curMagFilter +1) % 2;
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
filters[curMagFilter].type );
printFilters();
}
GLvoid
printFilters( GLvoid )
{
printf("mag filter: %10s, min filter: %26s\n",
filters[curMagFilter].name, filters[curMinFilter].name);
}
GLvoid
resetSwim ( GLvoid )
{
swim = 1.0;
}
GLvoid
toggleMoving ( GLvoid )
{
moving = ! moving;
printf ("%s\n", moving?"...MOVING":"PAUSED...");
if (moving) {
glutIdleFunc( animate );
} else {
glutIdleFunc( NULL );
}
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case 'a': /* toggle animation */
toggleMoving();
break;
case 'm': /* cycle minification filter */
cycleMinFilter();
break;
case 'M': /* cycle Magnification filter */
cycleMagFilter();
break;
case 'R': /* reset image to starting position */
resetSwim();
break;
case KEY_ESC: /* Exit when the Escape key is pressed */
exit(0);
}
glutPostRedisplay();
}
GLvoid
reshape( GLsizei width, GLsizei height )
{
GLfloat aspect;
glViewport( 0, 0, width, height );
aspect = (GLfloat) (width) / height;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 30.0, aspect, 1.0, 1500.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -3.0 );
}
GLvoid
animate( GLvoid )
{
swim = fmod( swim + 0.1, 35.0 );
/* Tell GLUT to redraw the scene */
glutPostRedisplay();
}
GLvoid
visibility( int state )
{
if (state == GLUT_VISIBLE && moving) {
glutIdleFunc( animate );
} else {
glutIdleFunc( NULL );
}
}
GLvoid
drawScene( GLvoid )
{
static float v0[3] = { -1.5, -1.0, 0.0 };
static float v1[3] = { 1.5, -1.0, 0.0 };
static float v2[3] = { 1.5, 1.0, 0.0 };
static float v3[3] = { -1.5, 1.0, 0.0 };
static float t0[2] = { 0.0, 0.0 };
static float t1[2] = { 1.0, 0.0 };
static float t2[2] = { 1.0, 1.0 };
static float t3[2] = { 0.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glPushMatrix();
glTranslatef( -3+swim, 0.2*sin(swim * 3.0), -swim*5.0 );
glRotatef( 45.0, 0.0, 1.0, 0.0 );
glBegin( GL_QUADS );
glTexCoord2fv( t0 ); glVertex3fv( v0 );
glTexCoord2fv( t1 ); glVertex3fv( v1 );
glTexCoord2fv( t2 ); glVertex3fv( v2 );
glTexCoord2fv( t3 ); glVertex3fv( v3 );
glEnd();
glPopMatrix();
glutSwapBuffers();
}
Notes:
This program creates multiple levels of detail for a texture. It applies them to a polygon that is rotated about the Y axis so that one edge is farther away than the other. It then slowly swims the polygon across the window, moving farther away from the viewpoint as the polygon moves to the right. As the polygon moves farther away from the viewpoint, different resolutions of the texture are used.
If no image file is specified, a series of artificial textures are created, one for each mipmap level. Each mipmap texture is a different color. This makes it easy to see when OpenGL is transitioning from one mipmap to the next.
If an image is specified, program calls gluBuild2DMipmaps() to create and load multiple resolutions of the image into texture memory. gluBuild2DMipmaps() takes care of scaling the image, if necessary. gluBuild2DMipmaps() also calls glTexImage2D() to load each level of the image into texture memory.
The program starts out with the minification and magnification filters set to GL_NEAREST. Pressing the <m> cycles through all of the minification filters. Pressing the <M> cycles through all of the magnification filters.
void glTexEnvf( GLenum target, GLenum pname, const
GLfloat param )
Specifies how the texture colors interact with the original polygon colors.
Notes:
A texture function acts on the fragment to be textured using the texture image value that applies to the fragment (determined by glTexParameter) and produces an RGBA color for that fragment.
The GL_DECAL texture environment mode is only defined for textures with 3 or 4 components.
The replace texture environment mode is specified in OpenGL 1.0 as GL_REPLACE_EXT, and is only available if the GL_EXT_texture extension is supported. GL_REPLACE_EXT is not available on RealityEngine, RealityEngine2, or VTX systems.

Notes:
For a 4-component texture, the texture environment functions affect the color and alpha value in the following way:
For a 3-component texture (not pitcured), the texture environment functions affect the color in the following way:
For a 3-component texture, the alpha value of the fragment is unchanged. Therefore, Decal and Replace look the same for 3-component textures.
/* texenv.c
* This program reads in a texture from a .rgb file,
* and maps it onto a polygon using explicit coordinates.
*
* Decal mode uses only the texture color, not the original polygon
* color. If there are alpha values in the texture, the alpha
* determines the percentage of texture blended with the polygon
* color. Decal may be faster than the default modulate mode.
*
* Modulate mode modulates the color of the polygon by the color
* of the texture. A white polygon should be used to get the
* full texture color. If the fragment has alpha, it is modulated by
* the texture alpha.
*
* Blend mode uses the texture color (or luminance, since it is
* primarily used for 1 or 2-component images) as though it were an
* alpha value. It uses the texture color to blend the fragment color
* with a constant blending color. If the fragment has alpha, it is
* modulated by the texture alpha.
*
* Replace mode replaces the fragment's color and alpha values
* with the corresponding texture values.
*
* The texture environment mode and the polygon color can be
* changed interactively.
*
* <a> Key - toggle alpha test on/off
* <b> Key - toggle blending on/off
* <c> Key - toggle between white and red polygon
* <e> Key - cycle through environment modes
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <math.h>
#include <stdio.h>
#include "texture.h" /* should be in ../../include */
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid drawScene( GLvoid );
GLvoid reshape( GLsizei, GLsizei );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid initTexture( GLubyte *, GLsizei, GLsizei );
void resetView( GLvoid );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
/* Global Variables */
static GLuint envmode = 0;
static GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat water[] = { 0.0, 0.3, 0.5, 1.0 };
static GLboolean useWhite = GL_FALSE;
static GLboolean alphatest = GL_FALSE;
static GLboolean blending = GL_FALSE;
typedef struct {
GLint type;
char *name;
} EnvModeInfo;
static EnvModeInfo modes[4] = {
{ GL_DECAL, "GL_DECAL" },
{ GL_MODULATE, "GL_MODULATE" },
{ GL_BLEND, "GL_BLEND" },
#ifdef GL_REPLACE
{ GL_REPLACE, "GL_REPLACE" },
#else
{ GL_REPLACE_EXT, "GL_REPLACE_EXT" },
#endif
};
void
main ( int argc, char *argv[])
{
char *imageFileName = "fish.rgba";
GLubyte *image;
GLsizei width, height;
GLsizei imageWidth, imageHeight, components;
glutInit( &argc, argv );
if (argc < 2) {
fprintf (stderr, "usage: %s [imageFileName]\n", argv[0] );
} else
imageFileName = argv[1];
fprintf(stdout, "using image %s\n\n", imageFileName );
image = read_texture(imageFileName, &imageWidth,
&imageHeight, &components);
/* create a window that is 1/4 the size of the screen */
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 4, height / 4 );
glutInitWindowSize( (width / 2) - 4, height / 2 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( argv[0] );
initTexture( image, imageWidth, imageHeight );
initgfx();
glutKeyboardFunc( keyboard );
glutReshapeFunc( reshape );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrates texture environment modes\n\n"
"<a> Key - toggle alpha test on/off\n"
"<b> Key - toggle blending on/off\n"
"<c> Key - toggle polygon color between white/red \n"
"<e> Key - cycle through texture environment modes\n"
"Escape Key - exit the program\n\n",
progname);
printf("\nTexture Environment Mode is %s\n", modes[envmode].name);
}
GLvoid
initgfx()
{
glClearColor( water[0], water[1], water[2], water[3] );
/* Don't draw nearly transparent pixels */
glAlphaFunc( GL_GREATER, 0.1 );
if (alphatest)
glEnable( GL_ALPHA_TEST );
/* Set up blending so that the rectangle around the
* fish will be transparent with smooth edges
*/
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
if (blending)
glEnable( GL_BLEND );
}
GLvoid
initTexture( GLubyte *image,
GLsizei imageWidth, GLsizei imageHeight )
{
/* use gluBuild2DMipmaps to create and load mipmaps (it will
* also scale he original image to be a power of two, if
* necessary)
*
* gluBuild2DMipmaps( target, internalformat, width, height,
* format, type, imageArray )
*/
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, imageWidth, imageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, image );
/* Setting the magnification filter to nearest instead of linear
* may run faster on some platforms, with possibly lower quality
*/
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
/* Set the texture environment mode */
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, modes[envmode].type);
/* Used when tex env mode is GL_BLEND */
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, water );
/* enable 2D texture mapping */
glEnable( GL_TEXTURE_2D );
}
GLvoid
reshape( GLsizei width, GLsizei height )
{
GLdouble aspect;
glViewport( 0, 0, width, height );
aspect = (GLdouble) width / (GLdouble) height;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0, aspect, 1.0, 50.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -12.0 );
}
GLvoid
cycleTexEnvMode( GLvoid )
{
envmode = (envmode + 1) % 4;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, modes[envmode].type);
printf("Texture Environment Mode is %s\n", modes[envmode].name );
}
GLvoid
toggleAlphaTest( GLvoid )
{
alphatest = !alphatest;
if (alphatest)
glEnable( GL_ALPHA_TEST );
else
glDisable( GL_ALPHA_TEST );
printf( "alphatest %s\n", (alphatest? "enabled":"disabled"));
}
GLvoid
toggleBlending( GLvoid )
{
blending = !blending;
if (blending)
glEnable( GL_BLEND );
else
glDisable( GL_BLEND );
printf( "blending %s\n", (blending? "enabled":"disabled"));
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case 'a': /* toggle alpha test */
toggleAlphaTest();
glutPostRedisplay();
break;
case 'b': /* toggle blending */
toggleBlending();
glutPostRedisplay();
break;
case 'c': /* toggle polygon color */
useWhite = !useWhite;
glutPostRedisplay();
break;
case 'e': /* cycle through texture environment modes */
cycleTexEnvMode();
glutPostRedisplay();
break;
case KEY_ESC: /* Exit whenever the Escape key is pressed */
exit(0);
}
}
GLvoid
drawScene(void)
{
static float v0[3] = { -1.5, -1.0, 0.0 };
static float v1[3] = { 1.5, -1.0, 0.0 };
static float v2[3] = { 1.5, 1.0, 0.0 };
static float v3[3] = { -1.5, 1.0, 0.0 };
static float t0[2] = { 0.0, 0.0 };
static float t1[2] = { 1.0, 0.0 };
static float t2[2] = { 1.0, 1.0 };
static float t3[2] = { 0.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT );
if (useWhite) {
glColor4fv( white );
} else {
/* Make the polygon RED so that we can see what happens
* in modulate and blend mode; usually, you would make
* the polygon white.
*/
glColor4fv( red );
}
glPushMatrix ();
glBegin( GL_QUADS );
glTexCoord2fv( t0 ); glVertex3fv( v0 );
glTexCoord2fv( t1 ); glVertex3fv( v1 );
glTexCoord2fv( t2 ); glVertex3fv( v2 );
glTexCoord2fv( t3 ); glVertex3fv( v3 );
glEnd();
glPopMatrix ();
glutSwapBuffers();
}
Notes:
This program reads in an image from an RGB file, and applies it as a texture to a rectangular polygon using explicit texture coordinates. Pressing the <e> cycles through the texture environment modes. Pressing the <c> toggles between a white polygon and a red polygon. The program starts out in decal mode.
The program also sets up an alpha test such that fragments with alpha values less than or equal to 0.1 are discarded. The blend function ensures that the edges will be blended smoothly. Alpha blending can be enabled so that the polygon is transparent wherever the alpha value ends up being 0 after texture mapping. Press the <a> key to toggle alpha testing on and off. Press the <b> key to toggle blending on and off.
Enabling blending ensures that the edges around the object blend smoothly with the background color.
The default texture (fish.rgba) is a rectangle containing a picture of a fish. Where the fish is drawn, the alpha value is 1.0. In the black background, the alpha value is 0.0.
Decal mode uses the alpha value of the texture to blend the color of the texture with that of the polygon. The alpha value of the polygon is unchanged. Wherever the texture alpha value is 0.0, the full color of the polygon shows through. Everywhere else, the texture alpha values are 1.0, so the image of the fish is "pasted" onto the polygon.
Modulate mode modulates the polygon color by the color of the texture, so the fish looks red when the polygon is red. Wherever the texture alpha values are 0.0, the polygon color becomes transparent. The alpha value of the polygon is modulated by the alpha value of the texture. If the resulting value is very small, the alpha test discards the fragment, creating a transparent effect.
Modulate mode is only interesting if the texture has alpha values. Otherwise, the program simply modulates the texture color with the polygon color; there is no transparency effect because the alpha value of the polygon is 1.0.
Blend mode blends the polygon color with a constant blend color using the texture value as a blend factor. In this program the color is blended with a constant color. The blend color is set in initTexture() to a bluish color. This mode is more useful with single component textures that contain only alpha, luminance or intensity values.
Replace mode replaces the polygon alpha and color values with those from the texture. In replace mode, the fragment alpha value is replaced by the texture alpha value. So, wherever the texture has an alpha value of 0.0, the fragment is discarded by the alpha test.
Glu provides a function to automatically generate texture coordinates for quadrics
Notes:
A quadric surface is one that can be calculated using a quadratic equation. GLU provides the quadric object as a utility to model and render cylinders, spheres, and disks.
void gluQuadricTexture( GLUquadric* quad, GLboolean texture )
Example:
GLUquadricObj *quadObj;
quadObj = gluNewQuadric();
gluQuadricDrawStyle( quadObj, GLU_FILL );
gluQuadricTexture( quadObj, GL_TRUE );
/* ... in the draw routine */
gluSphere( quadObj, 0.75, 32, 32 );
Notes:
For more on GLUquadric utility functions, see the man gluNewQuadric.
/* texgen2.c
* This program reads in a texture from a .rgb file, sets up the
* texture and the texture environment, then applies the texture
* to a polygon using GLU quadric texture coordinate generation.
*
* <a> key - toggle animation on/off
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <math.h>
#include <stdio.h>
#include "texture.h" /* should be in ../../include */
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid animate( GLvoid );
GLvoid visibility( GLint );
GLvoid drawScene( GLvoid );
GLvoid reshape( GLsizei, GLsizei );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid initialize( int, char ** );
GLvoid initTexture( GLubyte *, GLsizei, GLsizei );
GLvoid printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
/* Global Variables */
static GLfloat spin = 0.05;
static GLUquadricObj *quadObj;
static GLboolean animateFlag = GL_TRUE;
void
main ( int argc, char *argv[])
{
char *imageFileName = "bricks.rgb";
GLubyte *image;
GLsizei width, height;
GLsizei imageWidth, imageHeight, components;
glutInit( &argc, argv );
if (argc < 2) {
fprintf (stderr, "usage: %s [imageFileName]\n", argv[0] );
} else
imageFileName = argv[1];
fprintf( stdout, "using image %s\n", imageFileName );
image = (GLubyte *) read_texture(imageFileName, &imageWidth,
&imageHeight, &components);
/* create a window that is 1/4 the size of the screen */
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 4, height / 4 );
glutInitWindowSize( (width / 2) - 4, height / 2 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutCreateWindow( argv[0] );
initTexture( image, imageWidth, imageHeight );
initgfx();
glutKeyboardFunc( keyboard );
glutIdleFunc( animate );
glutVisibilityFunc( visibility );
glutReshapeFunc( reshape );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glutMainLoop();
}
GLvoid
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrates automatic texture coordinate "
"generation\n"
"<a> key - toggle animation on/off\n"
"Escape key - exit the program\n\n",
progname );
}
GLvoid initgfx( GLvoid )
{
glEnable( GL_DEPTH_TEST );
glClearColor( 0, 0, 0, 1 );
/* set up quadric object and turn on FILL draw style for it */
quadObj = gluNewQuadric ();
gluQuadricDrawStyle( quadObj, GLU_FILL );
/* turn on texture coordinate generator for the quadric */
gluQuadricTexture( quadObj, GL_TRUE );
}
GLvoid initTexture( GLubyte *image,
GLsizei imageWidth, GLsizei imageHeight )
{
/* scale texture image, make mipmaps and load texture
* gluBuild2DMipmaps( target, internalformat, width, height,
* format, type, imageArray )
*/
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, imageWidth, imageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, image );
glEnable( GL_TEXTURE_2D );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case 'a': /* toggle animation */
animateFlag = !animateFlag;
if (animateFlag)
glutIdleFunc( animate );
else
glutIdleFunc( NULL );
break;
case KEY_ESC: /* Exit when the Escape key is pressed */
exit(0);
}
}
GLvoid
animate( GLvoid )
{
spin = fmod( spin + 5.0, 360.0 );
/* Tell GLUT to redraw the scene */
glutPostRedisplay();
}
GLvoid
visibility( int state )
{
if (state == GLUT_VISIBLE) {
glutIdleFunc( animate );
} else {
glutIdleFunc( NULL );
}
}
GLvoid
reshape( GLsizei width, GLsizei height )
{
GLdouble aspect;
glViewport( 0, 0, width, height );
aspect = (GLdouble) width / (GLdouble) height;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0, aspect, 3.0, 15.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -6.0 );
}
GLvoid
drawScene(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glPushMatrix();
glRotatef( spin, 0.0, 0.0, 1.0 );
glRotatef( spin, 0.0, 1.0, 0.0 );
gluSphere( quadObj, 0.75, 32, 32 );
glPopMatrix();
glutSwapBuffers();
}
Notes:
This program demonstrates GLU quadric texture coordinate generation.
Notice that the texture is wrapped more smoothly around the sphere than with OpenGL automatic texture coordinate generation.
Notes:
* Indicates an optional laboratory exercise.
Texture mapping is used to add realism and detail to objects. For example, you can put a marble texture on a table, wrap a label around a can, or cover the ground with a grass texture (which saves you the trouble of modeling each blade of grass). You can think of the texture you will use as a piece of elastic wrapping paper. You can stretch or shrink this "paper" to cover the objects in your scene.
There are four basic steps to using texture mapping in OpenGL. The first step is to set the texture parameters using glTexParameter*(). This function allows you to define how the image will be filtered when it is enlarged or shrunk, whether the texture clamps to the border, or repeats when it wraps.
The second step involves loading the texture into texture memory. Encode the texture you want to use in a square pixel array (the same array you would use for raster images). The texture size must be a power of 2 in each dimension. If it is not, use gluScaleImage() to scale the texture before passing it to glTexImage2D() to load the texture.
The third step is to enable texturing using glEnable() with GL_TEXTURE_1D if your texture contains one-dimensional data or GLTEXTURE_2D if your texture contains two-dimensional data.
Finally, you need to apply the texture to an object by explicitly assigning texture coordinates to vertices. Your texture is a square. All textures are given texture coordinates which go from 0.0 to 1.0 in each dimension (s and t, where s represents the horizontal direction and t represents the vertical direction). Texture coordinates are assigned to polygon vertices with the glTexCoord*() command. You will need to figure out the coordinates of the point on the texture that should map to a vertex and use them in the glTexCoord*() command.
For example, suppose you wanted to wrap a label around a cylinder modeled by six vertical panels. After you have loaded the label into the texture memory and set up the texture environment, you draw the cylinder. Each panel uses 1/6 of the texture. The first panel goes from 0.0 to 1.0 in t, and 0.0 to 0.166 in s, the second also goes from 0.0 to 1.0 in t, but from 0.166 to 0.333 in s, and so on.

The following table shows how the RGBA color is produced for each of the texture functions that can be chosen. C is a triple of color values (RGB) and A is the associated alpha value. RGBA values extracted from a texture image are in the range [0,1]. The subscript f refers to the incoming fragment, the subscript t to the texture image, the subscript c to the texture environment color, and subscript v indicates a value produced by the texture function.
| Number of Components | MODULATE | DECAL | BLEND | REPLACE |
|---|---|---|---|---|
| LUMINANCE (1) |
Cv = Cf * Lt Av = Af |
undefined | Cv = Cf * (1-Lt) + Cc * Lt Av = Af |
Cv = Lt Av = Af |
| ALPHA (1) |
Cv = Cf Av = Af * At |
undefined | Cv = Cf Av = Af * At |
Cv = Cf Av = At |
| INTENSITY (1) |
Cv = Cf * It Av = Af |
undefined | Cv = Cf * (1-It) + Cc * It Av = Af |
Cv = It Av = Af |
| LUMINANCE & ALPHA (2) |
Cv = Cf * Lt Av = Af * At |
undefined | Cv = Cf * (1-Lt) + Cc * Lt Av = Af * At |
Cv = Lt Av =At |
| RGB (3) |
Cv = Cf * Ct Av = Af |
Cv = Ct Av = Af |
Cv = Cf * (1-Ct ) + Cc * Ct Av = Af |
Cv = Ct Av = Af |
| RGBA (4) |
Cv = Cf * Ct Av = Af * At |
Cv = Cf * (1-At ) + Ct * At Av = Af |
Cv = Cf * (1-Ct ) + Cc * Ct Av = Af * At |
Cv = Ct |
glEnable(GL_TEXTURE_1D);
If enabled, one-dimensional texturing is performed (unless
two-dimensional texturing is also enabled).
glEnable(GL_TEXTURE_2D);
If enabled, two-dimensional texturing is performed.
glEnable (GL_TEXTURE_GEN_S);
glDisable (GL_TEXTURE_GEN_S);
Enable/disable automatic computation of the s texture
coordinate by the texture generation function defined with glTexGen*().
glEnable (GL_TEXTURE_GEN_T);
glDisable (GL_TEXTURE_GEN_T);
Enable/disable automatic computation of the t texture
coordinate by the texture generation function defined with glTexGen*().
glEnable(GL_TEXTURE_3D_EXT);
If enabled, three-dimensional texturing is performed (if the
EXT_texture3D extension is supported).
void glBindTextureEXT (GLenum target, GLuint texname)
Bind a named texture (texture object) to a texturing target.
void glDeleteTextures ( sizei n, uint *textures )
Delete named texture objects.
void glGenTexturesEXT (GLsize n, GLuint *texnames)
Generate texture object names.
void glPrioritizeTexturesEXT (GLsize n, const GLuint *texnames, const GLclampf *priorities)
Set texture object residence priority.
void glTexCoord2fv( const GLfloat *v )
Set the current texture coordinates to the homogeneous coordinates (s,
t, r, q) pointed to by v.
void glTexEnvf(GLenum target, GLenum pname, GLfloat param) void glTexEnvi(GLenum target, GLenum pname, GLint param) void glTexEnvfv(GLenum target, GLenum pname, GLfloat *params) void glTexEnviv(GLenum target, GLenum pname, GLint *params)
Set any of a number of texture environment parameters. See man
glTexEnv(3G) for the full list of symbolic constants that can be
used for the target and pname arguments.
void glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
void glTexGeni (GLenum coord, GLenum pname, GLint param)
Control the generation of texture coordinates.
void glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Specify a one-dimensional texture image.
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Specify a two-dimensional texture image.
void glTexImage3DEXT(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Specify a three-dimensional texture image. Three-dimensional textures
are available only if the EXT_texture3D extension is supported.
void glTexParameterf(GLenum target, GLenum pname, GLfloat param) void glTexParameteri(GLenum target, GLenum pname, GLint param) void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params) void glTexParameteriv(GLenum target, GLenum pname, GLint *params)
Set any of a number of texture parameters. See man glTexParameter(3G) for the full list of symbolic constants that can be used for the target and pname arguments.
Download sgi.h
and sgi.c. In this files some utilities
for handling textures are implemented.
Our new version of mElite uses texture mapping. New features to add (emphasised in the
the proposed solution code with the word "NEW" in the comments) are: