/* Copyright (c) Mark J. Kilgard, 1994. */ /** * (c) Copyright 1993, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "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, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* Demonstrates texture environment modes and internal image formats. Requires the GL_EXT_texture extension. */ #include #include #include #include #undef max #undef min #define max(a,b) ((a) >= (b) ? (a) : (b)) #define min(a,b) ((a) <= (b) ? (a) : (b)) /* *INDENT-OFF* */ GLfloat lightCheck[4] = {0.7, 0.7, 0.7, 1.0}; GLfloat darkCheck[4] = {0.3, 0.3, 0.3, 1.0}; GLfloat labelColor0[4] = {1.0, 1.0, 1.0, 1.0}; GLfloat labelColor1[4] = {1.0, 1.0, 0.4, 1.0}; GLfloat *labelInfoColor = labelColor0; GLfloat labelLevelColor0[4] = {0.8, 0.8, 0.1, 1.0}; GLfloat labelLevelColor1[4] = {0.0, 0.0, 0.0, 1.0}; /* *INDENT-ON* */ GLboolean doubleBuffered = GL_FALSE; GLboolean drawBackground = GL_FALSE; GLboolean drawBlended = GL_TRUE; GLboolean drawSmooth = GL_FALSE; GLboolean drawTextured = GL_TRUE; GLboolean displayLevelInfo = GL_FALSE; int textureWidth = 64; int textureHeight = 64; int winWidth = 580, winHeight = 720; struct formatInfo { GLenum baseFormat; GLenum internalFormat; char *name; }; #define NUM_LUMINANCE_FORMATS \ (sizeof(luminanceFormats) / sizeof(luminanceFormats[0])) struct formatInfo luminanceFormats[] = { {GL_LUMINANCE, 1, "LUMINANCE"}, #if GL_EXT_texture {GL_LUMINANCE, GL_LUMINANCE4_EXT, "LUMINANCE4"}, {GL_LUMINANCE, GL_LUMINANCE8_EXT, "LUMINANCE8"}, {GL_LUMINANCE, GL_LUMINANCE12_EXT, "LUMINANCE12"}, {GL_LUMINANCE, GL_LUMINANCE16_EXT, "LUMINANCE16"}, #endif }; #define NUM_ALPHA_FORMATS \ (sizeof(alphaFormats) / sizeof(alphaFormats[0])) struct formatInfo alphaFormats[] = { {GL_ALPHA, GL_ALPHA, "ALPHA"}, #if GL_EXT_texture {GL_ALPHA, GL_ALPHA4_EXT, "ALPHA4"}, {GL_ALPHA, GL_ALPHA8_EXT, "ALPHA8"}, {GL_ALPHA, GL_ALPHA12_EXT, "ALPHA12"}, {GL_ALPHA, GL_ALPHA16_EXT, "ALPHA16"}, #endif }; #if GL_EXT_texture #define NUM_INTENSITY_FORMATS \ (sizeof(intensityFormats) / sizeof(intensityFormats[0])) struct formatInfo intensityFormats[] = { {GL_INTENSITY_EXT, GL_INTENSITY_EXT, "INTENSITY"}, {GL_INTENSITY_EXT, GL_INTENSITY4_EXT, "INTENSITY4"}, {GL_INTENSITY_EXT, GL_INTENSITY8_EXT, "INTENSITY8"}, {GL_INTENSITY_EXT, GL_INTENSITY12_EXT, "INTENSITY12"}, {GL_INTENSITY_EXT, GL_INTENSITY16_EXT, "INTENSITY16"}, }; #endif #define NUM_LUMINANCE_ALPHA_FORMATS \ (sizeof(luminanceAlphaFormats) / sizeof(luminanceAlphaFormats[0])) struct formatInfo luminanceAlphaFormats[] = { {GL_LUMINANCE_ALPHA, 2, "LUMINANCE_ALPHA"}, #if GL_EXT_texture {GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4_EXT, "LUMINANCE4_ALPHA4"}, {GL_LUMINANCE_ALPHA, GL_LUMINANCE6_ALPHA2_EXT, "LUMINANCE6_ALPHA2"}, {GL_LUMINANCE_ALPHA, GL_LUMINANCE8_ALPHA8_EXT, "LUMINANCE8_ALPHA8"}, {GL_LUMINANCE_ALPHA, GL_LUMINANCE12_ALPHA4_EXT, "LUMINANCE12_ALPHA4"}, {GL_LUMINANCE_ALPHA, GL_LUMINANCE12_ALPHA12_EXT, "LUMINANCE12_ALPHA12"}, {GL_LUMINANCE_ALPHA, GL_LUMINANCE16_ALPHA16_EXT, "LUMINANCE16_ALPHA16"}, #endif }; #define NUM_RGB_FORMATS \ (sizeof(rgbFormats) / sizeof(rgbFormats[0])) struct formatInfo rgbFormats[] = { {GL_RGB, 3, "RGB"}, #if GL_EXT_texture {GL_RGB, GL_RGB2_EXT, "RGB2"}, {GL_RGB, GL_RGB4_EXT, "RGB4"}, {GL_RGB, GL_RGB5_EXT, "RGB5"}, {GL_RGB, GL_RGB8_EXT, "RGB8"}, {GL_RGB, GL_RGB10_EXT, "RGB10"}, {GL_RGB, GL_RGB12_EXT, "RGB12"}, {GL_RGB, GL_RGB16_EXT, "RGB16"}, #endif }; #define NUM_RGBA_FORMATS \ (sizeof(rgbaFormats) / sizeof(rgbaFormats[0])) struct formatInfo rgbaFormats[] = { {GL_RGBA, 4, "RGBA"}, #if GL_EXT_texture {GL_RGBA, GL_RGBA2_EXT, "RGBA2"}, {GL_RGBA, GL_RGBA4_EXT, "RGBA4"}, {GL_RGBA, GL_RGBA8_EXT, "RGBA8"}, {GL_RGBA, GL_RGBA12_EXT, "RGBA12"}, {GL_RGBA, GL_RGBA16_EXT, "RGBA16"}, {GL_RGBA, GL_RGB5_A1_EXT, "RGB5_A1"}, {GL_RGBA, GL_RGB10_A2_EXT, "RGB10_A2"}, #endif }; struct baseFormatInfo { struct formatInfo *format; int current, number; }; #define NUM_BASE_FORMATS \ (sizeof(baseFormats) / sizeof(baseFormats[0])) int baseFormat; struct baseFormatInfo baseFormats[] = { {luminanceFormats, 0, NUM_LUMINANCE_FORMATS}, {alphaFormats, 0, NUM_ALPHA_FORMATS}, #if GL_EXT_texture {intensityFormats, 0, NUM_INTENSITY_FORMATS}, #endif {luminanceAlphaFormats, 0, NUM_LUMINANCE_ALPHA_FORMATS}, {rgbFormats, 0, NUM_RGB_FORMATS}, {rgbaFormats, 0, NUM_RGBA_FORMATS}, }; #define NUM_ENV_COLORS \ (sizeof(envColors) / sizeof(envColors[0])) int envColor; GLfloat envColors[][4] = { {0.0, 0.0, 0.0, 1.0}, {1.0, 0.0, 0.0, 1.0}, {0.0, 1.0, 0.0, 1.0}, {0.0, 0.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}, }; struct envModeInfo { GLenum mode; char *name; }; #define NUM_ENV_MODES \ (sizeof(envModes) / sizeof(envModes[0])) struct envModeInfo envModes[] = { #if GL_EXT_texture {GL_REPLACE_EXT, "REPLACE"}, #endif {GL_MODULATE, "MODULATE"}, {GL_BLEND, "BLEND"}, {GL_DECAL, "DECAL"}, }; void checkErrors(void) { GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error)); } } static void drawString(char *string, GLfloat x, GLfloat y, GLfloat color[4]) { glColor4fv(color); glRasterPos2f(x, y); while (*string) { glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, *string); string++; } } static void drawStringOutline(char *string, GLfloat x, GLfloat y, GLfloat color[4], GLfloat outline[4]) { drawString(string, x - 1, y, outline); drawString(string, x + 1, y, outline); drawString(string, x, y - 1, outline); drawString(string, x, y + 1, outline); drawString(string, x, y, color); } static void begin2D(int width, int height) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } static void end2D(void) { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } static void initialize(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.5, 1.5, -1.5, 1.5, -1.5, 1.5); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glShadeModel(GL_FLAT); } /* ARGSUSED1 */ void keyboard(unsigned char c, int x, int y) { switch (c) { case 'c': envColor = ++envColor % (int) NUM_ENV_COLORS; break; case 'g': drawBackground = !drawBackground; break; case 'b': drawBlended = !drawBlended; break; case 's': drawSmooth = !drawSmooth; break; case 't': drawTextured = !drawTextured; break; case 'i': displayLevelInfo = !displayLevelInfo; break; case 27: /* Escape key should force exit. */ exit(0); break; default: break; } glutPostRedisplay(); } /* ARGSUSED1 */ void special(int key, int x, int y) { switch (key) { case GLUT_KEY_DOWN: if (++baseFormat > NUM_BASE_FORMATS - 1) baseFormat = 0; break; case GLUT_KEY_UP: if (--baseFormat < 0) baseFormat = NUM_BASE_FORMATS - 1; break; case GLUT_KEY_LEFT: --baseFormats[baseFormat].current; if (baseFormats[baseFormat].current < 0) baseFormats[baseFormat].current = baseFormats[baseFormat].number - 1; break; case GLUT_KEY_RIGHT: ++baseFormats[baseFormat].current; if (baseFormats[baseFormat].current > baseFormats[baseFormat].number - 1) baseFormats[baseFormat].current = 0; break; default: break; } glutPostRedisplay(); } void reshape(int w, int h) { winWidth = w; winHeight = h; /* No need to call glViewPort here since "draw" calls it! */ } static void loadTexture(int width, int height, struct formatInfo *format) { int luminanceSize = 0; int alphaSize = 0; int rgbSize = 0; GLenum textureFormat; GLubyte *texImage, *p; int elementsPerGroup, elementSize, groupSize, rowSize; int i, j; switch (format->baseFormat) { case GL_LUMINANCE: #if GL_EXT_texture case GL_INTENSITY_EXT: #endif luminanceSize = 1; textureFormat = GL_LUMINANCE; break; case GL_ALPHA: alphaSize = 1; textureFormat = GL_ALPHA; break; case GL_LUMINANCE_ALPHA: luminanceSize = 1; alphaSize = 1; textureFormat = GL_LUMINANCE_ALPHA; break; case GL_RGB: rgbSize = 3; textureFormat = GL_RGB; break; case GL_RGBA: rgbSize = 3; alphaSize = 1; textureFormat = GL_RGBA; break; default: fprintf(stderr, "bad internal format info\n"); return; } elementsPerGroup = luminanceSize + alphaSize + rgbSize; elementSize = sizeof(GLubyte); groupSize = elementsPerGroup * elementSize; rowSize = width * groupSize; if ((texImage = (GLubyte *) malloc(height * rowSize)) == NULL) { fprintf(stderr, "texture malloc failed\n"); return; } for (i = 0; i < height; ++i) { p = texImage + i * rowSize; for (j = 0; j < width; ++j) { if (luminanceSize > 0) { /** ** +-----+-----+ ** | | | ** | W | LG | ** | | | ** +-----+-----+ ** | | | ** | DG | B | ** | | | ** +-----+-----+ **/ if (i > height / 2) { if (j < width / 2) { p[0] = 0xff; } else { p[0] = 0xaa; } } else { if (j < width / 2) { p[0] = 0x55; } else { p[0] = 0x00; } } p += elementSize; } if (rgbSize > 0) { /** ** +-----+-----+ ** | | | ** | R | G | ** | | | ** +-----+-----+ ** | | | ** | Y | B | ** | | | ** +-----+-----+ **/ if (i > height / 2) { if (j < width / 2) { p[0] = 0xff; p[1] = 0x00; p[2] = 0x00; } else { p[0] = 0x00; p[1] = 0xff; p[2] = 0x00; } } else { if (j < width / 2) { p[0] = 0xff; p[1] = 0xff; p[2] = 0x00; } else { p[0] = 0x00; p[1] = 0x00; p[2] = 0xff; } } p += 3 * elementSize; } if (alphaSize > 0) { /** ** +-----------+ ** | W | ** | +-----+ | ** | | | | ** | | B | | ** | | | | ** | +-----+ | ** | | ** +-----------+ **/ int i2 = i - height / 2; int j2 = j - width / 2; int h8 = height / 8; int w8 = width / 8; if (-h8 <= i2 && i2 <= h8 && -w8 <= j2 && j2 <= w8) { p[0] = 0x00; } else if (-2 * h8 <= i2 && i2 <= 2 * h8 && -2 * w8 <= j2 && j2 <= 2 * w8) { p[0] = 0x55; } else if (-3 * h8 <= i2 && i2 <= 3 * h8 && -3 * w8 <= j2 && j2 <= 3 * w8) { p[0] = 0xaa; } else { p[0] = 0xff; } p += elementSize; } } } glTexImage2D(GL_TEXTURE_2D, 0, format->internalFormat, width, height, 0, textureFormat, GL_UNSIGNED_BYTE, texImage); free(texImage); } static void drawCheck(int w, int h, GLfloat lightCheck[4], GLfloat darkCheck[4]) { float dw = 2.0 / w; float dh = 2.0 / h; int i, j; for (i = 0; i < w; ++i) { GLfloat x0 = -1.0 + i * dw; GLfloat x1 = x0 + dw; glBegin(GL_QUAD_STRIP); for (j = 0; j <= h; ++j) { GLfloat y = -1.0 + j * dh; if ((i ^ j) & 1) { glColor4fv(lightCheck); } else { glColor4fv(darkCheck); } glVertex2f(x0, y); glVertex2f(x1, y); } glEnd(); } } static void drawSample(int x, int y, int w, int h, struct formatInfo *format, struct envModeInfo *envMode) { glViewport(x, y, w, h); glScissor(x, y, w, h); glClearColor(0.1, 0.1, 0.1, 1.0); glClear(GL_COLOR_BUFFER_BIT); begin2D(w, h); drawString(format->name, 10, h - 15, labelInfoColor); drawString(envMode->name, 10, 5, labelInfoColor); end2D(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, envMode->mode); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColors[envColor]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); loadTexture(textureWidth, textureHeight, format); if (drawBackground) { drawCheck(15, 15, lightCheck, darkCheck); } if (drawBlended) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } if (drawSmooth) { glShadeModel(GL_SMOOTH); } if (drawTextured) { glEnable(GL_TEXTURE_2D); } glBegin(GL_QUADS); glColor4f(1.0, 0.0, 0.0, 1.0); glTexCoord2f(0.0, 0.0); glVertex2f(-0.8, -0.8); glColor4f(0.0, 1.0, 0.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex2f(0.8, -0.8); glColor4f(0.0, 0.0, 1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex2f(0.8, 0.8); glColor4f(1.0, 1.0, 1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex2f(-0.8, 0.8); glEnd(); glDisable(GL_BLEND); glShadeModel(GL_FLAT); glDisable(GL_TEXTURE_2D); if (displayLevelInfo) { GLint width, height, border, components; #if GL_EXT_texture GLint redSize, greenSize, blueSize, alphaSize; GLint luminanceSize, intensitySize; #endif char buf[255]; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &components); #if GL_EXT_texture glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE_EXT, &redSize); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE_EXT, &greenSize); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE_EXT, &blueSize); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE_EXT, &alphaSize); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_LUMINANCE_SIZE_EXT, &luminanceSize); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTENSITY_SIZE_EXT, &intensitySize); #endif begin2D(w, h); sprintf(buf, "dimensions: %d x %d", width, height); drawStringOutline(buf, 15, h / 2 + 20, labelLevelColor0, labelLevelColor1); sprintf(buf, "border: %d", border); drawStringOutline(buf, 15, h / 2 + 10, labelLevelColor0, labelLevelColor1); sprintf(buf, "components: 0x%04X", components); drawStringOutline(buf, 15, h / 2, labelLevelColor0, labelLevelColor1); sprintf(buf, "sizes:"); drawStringOutline(buf, 15, h / 2 - 10, labelLevelColor0, labelLevelColor1); #if GL_EXT_texture sprintf(buf, " %d/%d/%d/%d/%d/%d", redSize, greenSize, blueSize, alphaSize, luminanceSize, intensitySize); drawStringOutline(buf, 15, h / 2 - 20, labelLevelColor0, labelLevelColor1); #endif end2D(); } } static void display(void) { int numX = NUM_ENV_MODES, numY = NUM_BASE_FORMATS; float xBase = (float) winWidth * 0.01; float xOffset = (winWidth - xBase) / numX; float xSize = max(xOffset - xBase, 1); float yBase = (float) winHeight * 0.01; float yOffset = (winHeight - yBase) / numY; float ySize = max(yOffset - yBase, 1); float x, y; int i, j; glViewport(0, 0, winWidth, winHeight); glDisable(GL_SCISSOR_TEST); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); x = xBase; y = (winHeight - 1) - yOffset; for (i = 0; i < NUM_BASE_FORMATS; ++i) { struct formatInfo *format; if (i == baseFormat) { labelInfoColor = labelColor1; } else { labelInfoColor = labelColor0; } format = &baseFormats[i].format[baseFormats[i].current]; for (j = 0; j < NUM_ENV_MODES; ++j) { struct envModeInfo *envMode; envMode = &envModes[j]; drawSample(x, y, xSize, ySize, format, envMode); x += xOffset; } x = xBase; y -= yOffset; } if (doubleBuffered) { glutSwapBuffers(); } else { glFlush(); } checkErrors(); } static void usage(char *name) { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [ options ]\n", name); fprintf(stderr, "\n"); fprintf(stderr, " Tests texture environments and internal formats\n"); fprintf(stderr, "\n"); fprintf(stderr, " Options:\n"); fprintf(stderr, " -sb single buffered\n"); fprintf(stderr, " -db double buffered\n"); fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { int i; glutInit(&argc, argv); for (i = 1; i < argc; ++i) { if (!strcmp("-sb", argv[i])) { doubleBuffered = GL_FALSE; } else if (!strcmp("-db", argv[i])) { doubleBuffered = GL_TRUE; } else { usage(argv[0]); exit(1); } } #if !GL_EXT_texture printf("WARNING: client-side OpenGL implementation lacks\n"); printf(" the GL_EXT_texture extension!\n"); printf(" Skipping GL_EXT_texture functionality...\n"); #endif if (doubleBuffered) { glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); } else { glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); } glutInitWindowSize(winWidth, winHeight); glutCreateWindow("Texture Environment Test"); if (!glutExtensionSupported("GL_EXT_texture")) { fprintf(stderr, "missing extension: GL_EXT_texture\n"); exit(1); } initialize(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }