/* * Copyright (c) 1996-1999 Silicon Graphics, Inc. All rights reserved. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* 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. * * Key - toggle alpha test on/off * Key - toggle blending on/off * Key - toggle between white and red polygon * Key - cycle through environment modes * Escape Key - exit program */ #include /* includes gl.h, glu.h */ #include #include #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.0f, 1.0f, 1.0f, 1.0f }; static GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f }; static GLfloat water[] = { 0.0f, 0.3f, 0.5f, 1.0f }; 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 = (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_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" " Key - toggle alpha test on/off\n" " Key - toggle blending on/off\n" " Key - toggle polygon color between white/red \n" " 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.1f ); 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.0f, 0.0f, -12.0f ); } 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( "alpha test %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.5f, -1.0f, 0.0f }; static float v1[3] = { 1.5f, -1.0f, 0.0f }; static float v2[3] = { 1.5f, 1.0f, 0.0f }; static float v3[3] = { -1.5f, 1.0f, 0.0f }; static float t0[2] = { 0.0f, 0.0f }; static float t1[2] = { 1.0f, 0.0f }; static float t2[2] = { 1.0f, 1.0f }; static float t3[2] = { 0.0f, 1.0f }; 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(); }