/*
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
**
** http://oss.sgi.com/projects/FreeB
**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
**
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
**
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
** Window System(R) (Version 1.3), released October 19, 1998. This software
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
** published by SGI, but has not been independently verified as being
** compliant with the OpenGL(R) version 1.2.1 Specification.
**
** $Date$ $Revision$
*/
/*
** cc -o texenv texenv.c -lglut -lGLU -lGL -lXext -lX11
**
** Demonstrates texture environment modes and internal image formats.
**
** Requires the GL_EXT_texture extension.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#if defined(GL_EXT_texture)
#define max(a,b) ((a) >= (b) ? (a) : (b))
#define min(a,b) ((a) <= (b) ? (a) : (b))
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 };
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" },
{ GL_LUMINANCE, GL_LUMINANCE4_EXT, "LUMINANCE4" },
{ GL_LUMINANCE, GL_LUMINANCE8_EXT, "LUMINANCE8" },
{ GL_LUMINANCE, GL_LUMINANCE12_EXT, "LUMINANCE12" },
{ GL_LUMINANCE, GL_LUMINANCE16_EXT, "LUMINANCE16" },
};
#define NUM_ALPHA_FORMATS \
(sizeof(alphaFormats) / sizeof(alphaFormats[0]))
struct formatInfo alphaFormats[] = {
{ GL_ALPHA, GL_ALPHA, "ALPHA" },
{ GL_ALPHA, GL_ALPHA4_EXT, "ALPHA4" },
{ GL_ALPHA, GL_ALPHA8_EXT, "ALPHA8" },
{ GL_ALPHA, GL_ALPHA12_EXT, "ALPHA12" },
{ GL_ALPHA, GL_ALPHA16_EXT, "ALPHA16" },
};
#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" },
};
#define NUM_LUMINANCE_ALPHA_FORMATS \
(sizeof(luminanceAlphaFormats) / sizeof(luminanceAlphaFormats[0]))
struct formatInfo luminanceAlphaFormats[] = {
{ GL_LUMINANCE_ALPHA, 2, "LUMINANCE_ALPHA" },
{ 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" },
};
#define NUM_RGB_FORMATS \
(sizeof(rgbFormats) / sizeof(rgbFormats[0]))
struct formatInfo rgbFormats[] = {
{ GL_RGB, 3, "RGB" },
{ 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" },
};
#define NUM_RGBA_FORMATS \
(sizeof(rgbaFormats) / sizeof(rgbaFormats[0]))
struct formatInfo rgbaFormats[] = {
{ GL_RGBA, 4, "RGBA" },
{ 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" },
};
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 },
{ intensityFormats, 0, NUM_INTENSITY_FORMATS },
{ 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[] = {
{ GL_REPLACE_EXT, "REPLACE" },
{ 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);
}
void
keyboard(unsigned char c, int x, int y)
{
switch (c) {
case 'c':
envColor = ++envColor % 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;
default:
break;
}
glutPostRedisplay();
}
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;
glutPostRedisplay();
}
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:
case GL_INTENSITY_EXT:
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;
GLint redSize, greenSize, blueSize, alphaSize;
GLint luminanceSize, intensitySize;
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);
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);
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);
sprintf(buf, " %d/%d/%d/%d/%d/%d",
redSize, greenSize, blueSize, alphaSize,
luminanceSize, intensitySize);
drawStringOutline(buf, 15, h/2-20, labelLevelColor0, labelLevelColor1);
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;
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(int argc, char *argv[])
{
fprintf(stderr, "\n");
fprintf(stderr, "usage: %s [ options ]\n", argv[0]);
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[])
{
char *name = "Texture Environment Test";
int i;
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(argc, argv);
exit(EXIT_FAILURE);
}
}
if (doubleBuffered) {
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
} else {
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
}
glutInitWindowSize(winWidth, winHeight);
glutCreateWindow(name);
if (!glutExtensionSupported("GL_EXT_texture")) {
fprintf(stderr, "missing extension: GL_EXT_texture\n");
exit(EXIT_FAILURE);
}
initialize();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutMainLoop();
}
#else
int main(int argc, char **argv)
{
printf("Couldn't find GL_EXT_texture extension.\n");
}
#endif