132001f49Smrg/* 232001f49Smrg * Compressed texture demo. Written by Daniel Borca. 332001f49Smrg * This program is in the public domain. 432001f49Smrg */ 532001f49Smrg 632001f49Smrg#include <stdio.h> 732001f49Smrg#include <stdlib.h> 832001f49Smrg#include <math.h> 932001f49Smrg#include <string.h> 1032001f49Smrg#include <GL/glew.h> 1132001f49Smrg#include "glut_wrap.h" 1232001f49Smrg 1332001f49Smrg#include "readtex.c" /* I know, this is a hack. */ 1432001f49Smrg#define TEXTURE_FILE DEMOS_DATA_DIR "tree2.rgba" 1532001f49Smrg 1632001f49Smrg 1732001f49Smrgstatic float Rot = 0.0; 1832001f49Smrgstatic GLboolean Anim = 1; 1932001f49Smrg 2032001f49Smrgtypedef struct { 2132001f49Smrg GLubyte *data; 2232001f49Smrg GLuint size; 2332001f49Smrg GLenum format; 2432001f49Smrg GLuint w, h; 2532001f49Smrg 2632001f49Smrg GLenum TC; 2732001f49Smrg 2832001f49Smrg GLubyte *cData; 2932001f49Smrg GLuint cSize; 3032001f49Smrg GLenum cFormat; 3132001f49Smrg} TEXTURE; 3232001f49Smrg 3332001f49Smrgstatic TEXTURE *Tx, t1, t2, t3; 3432001f49Smrgstatic GLboolean fxt1, dxtc, s3tc; 3532001f49Smrg 3632001f49Smrg 3732001f49Smrgstatic const char *TextureName (GLenum TC) 3832001f49Smrg{ 3932001f49Smrg switch (TC) { 4032001f49Smrg case GL_RGB: 4132001f49Smrg return "RGB"; 4232001f49Smrg case GL_RGBA: 4332001f49Smrg return "RGBA"; 4432001f49Smrg case GL_COMPRESSED_RGB: 4532001f49Smrg return "COMPRESSED_RGB"; 4632001f49Smrg case GL_COMPRESSED_RGBA: 4732001f49Smrg return "COMPRESSED_RGBA"; 4832001f49Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 4932001f49Smrg return "GL_COMPRESSED_RGB_FXT1_3DFX"; 5032001f49Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 5132001f49Smrg return "GL_COMPRESSED_RGBA_FXT1_3DFX"; 5232001f49Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 5332001f49Smrg return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; 5432001f49Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 5532001f49Smrg return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; 5632001f49Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 5732001f49Smrg return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; 5832001f49Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 5932001f49Smrg return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; 6032001f49Smrg case GL_RGB_S3TC: 6132001f49Smrg return "GL_RGB_S3TC"; 6232001f49Smrg case GL_RGB4_S3TC: 6332001f49Smrg return "GL_RGB4_S3TC"; 6432001f49Smrg case GL_RGBA_S3TC: 6532001f49Smrg return "GL_RGBA_S3TC"; 6632001f49Smrg case GL_RGBA4_S3TC: 6732001f49Smrg return "GL_RGBA4_S3TC"; 6832001f49Smrg case 0: 6932001f49Smrg return "Invalid format"; 7032001f49Smrg default: 7132001f49Smrg return "Unknown format"; 7232001f49Smrg } 7332001f49Smrg} 7432001f49Smrg 7532001f49Smrg 7632001f49Smrgstatic void 7732001f49SmrgPrintString(const char *s) 7832001f49Smrg{ 7932001f49Smrg while (*s) { 8032001f49Smrg glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 8132001f49Smrg s++; 8232001f49Smrg } 8332001f49Smrg} 8432001f49Smrg 8532001f49Smrg 8632001f49Smrgstatic void Idle( void ) 8732001f49Smrg{ 8832001f49Smrg float t = glutGet(GLUT_ELAPSED_TIME) * 0.001; /* in seconds */ 8932001f49Smrg Rot = t * 360 / 4; /* 1 rotation per 4 seconds */ 9032001f49Smrg glutPostRedisplay(); 9132001f49Smrg} 9232001f49Smrg 9332001f49Smrg 9432001f49Smrgstatic void Display( void ) 9532001f49Smrg{ 9632001f49Smrg /* draw background gradient */ 9732001f49Smrg glDisable(GL_TEXTURE_2D); 9832001f49Smrg glBegin(GL_POLYGON); 9932001f49Smrg glColor3f(1.0, 0.0, 0.2); glVertex2f(-1.5, -1.0); 10032001f49Smrg glColor3f(1.0, 0.0, 0.2); glVertex2f( 1.5, -1.0); 10132001f49Smrg glColor3f(0.0, 0.0, 1.0); glVertex2f( 1.5, 1.0); 10232001f49Smrg glColor3f(0.0, 0.0, 1.0); glVertex2f(-1.5, 1.0); 10332001f49Smrg glEnd(); 10432001f49Smrg 10532001f49Smrg glPushMatrix(); 10632001f49Smrg glRotatef(Rot, 0, 0, 1); 10732001f49Smrg 10832001f49Smrg glEnable(GL_TEXTURE_2D); 10932001f49Smrg glEnable(GL_BLEND); 11032001f49Smrg 11132001f49Smrg glBegin(GL_POLYGON); 11232001f49Smrg glTexCoord2f(0, 1); glVertex2f(-1, -0.5); 11332001f49Smrg glTexCoord2f(1, 1); glVertex2f( 1, -0.5); 11432001f49Smrg glTexCoord2f(1, 0); glVertex2f( 1, 0.5); 11532001f49Smrg glTexCoord2f(0, 0); glVertex2f(-1, 0.5); 11632001f49Smrg glEnd(); 11732001f49Smrg 11832001f49Smrg glPopMatrix(); 11932001f49Smrg 12032001f49Smrg glDisable(GL_TEXTURE_2D); 12132001f49Smrg 12232001f49Smrg /* info */ 12332001f49Smrg glDisable(GL_BLEND); 12432001f49Smrg glColor4f(1, 1, 1, 1); 12532001f49Smrg 12632001f49Smrg glRasterPos3f(-1.2, -0.7, 0); 12732001f49Smrg PrintString("Selected: "); 12832001f49Smrg PrintString(TextureName(Tx->TC)); 12932001f49Smrg if (Tx->cData) { 13032001f49Smrg char tmp[64]; 13132001f49Smrg glRasterPos3f(-1.2, -0.8, 0); 13232001f49Smrg PrintString("Internal: "); 13332001f49Smrg PrintString(TextureName(Tx->cFormat)); 13432001f49Smrg glRasterPos3f(-1.2, -0.9, 0); 13532001f49Smrg PrintString("Size : "); 13632001f49Smrg sprintf(tmp, "%d (%d%% of %d)", Tx->cSize, Tx->cSize * 100 / Tx->size, Tx->size); 13732001f49Smrg PrintString(tmp); 13832001f49Smrg } 13932001f49Smrg 14032001f49Smrg glutSwapBuffers(); 14132001f49Smrg} 14232001f49Smrg 14332001f49Smrg 14432001f49Smrgstatic void Reshape( int width, int height ) 14532001f49Smrg{ 14632001f49Smrg glViewport( 0, 0, width, height ); 14732001f49Smrg glMatrixMode( GL_PROJECTION ); 14832001f49Smrg glLoadIdentity(); 14932001f49Smrg glOrtho( -1.5, 1.5, -1.0, 1.0, -1.0, 1.0 ); 15032001f49Smrg glMatrixMode( GL_MODELVIEW ); 15132001f49Smrg glLoadIdentity(); 15232001f49Smrg} 15332001f49Smrg 15432001f49Smrg 15532001f49Smrgstatic void ReInit( GLenum TC, TEXTURE *Tx ) 15632001f49Smrg{ 15732001f49Smrg GLint rv, v; 15832001f49Smrg 15932001f49Smrg if ((Tx->TC == TC) && (Tx->cData != NULL)) { 16032001f49Smrg glCompressedTexImage2DARB(GL_TEXTURE_2D, /* target */ 16132001f49Smrg 0, /* level */ 16232001f49Smrg Tx->cFormat, /* real format */ 16332001f49Smrg Tx->w, /* original width */ 16432001f49Smrg Tx->h, /* original height */ 16532001f49Smrg 0, /* border */ 16632001f49Smrg Tx->cSize, /* compressed size*/ 16732001f49Smrg Tx->cData); /* compressed data*/ 16832001f49Smrg } else { 16932001f49Smrg glTexImage2D(GL_TEXTURE_2D, /* target */ 17032001f49Smrg 0, /* level */ 17132001f49Smrg TC, /* internal format */ 17232001f49Smrg Tx->w, Tx->h, /* width, height */ 17332001f49Smrg 0, /* border */ 17432001f49Smrg Tx->format, /* texture format */ 17532001f49Smrg GL_UNSIGNED_BYTE, /* texture type */ 17632001f49Smrg Tx->data); /* the texture */ 17732001f49Smrg 17832001f49Smrg 17932001f49Smrg v = 0; 18032001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, 18132001f49Smrg GL_TEXTURE_INTERNAL_FORMAT, &v); 18232001f49Smrg printf("Requested internal format = 0x%x, actual = 0x%x\n", TC, v); 18332001f49Smrg 18432001f49Smrg if (0) { 18532001f49Smrg GLint r, g, b, a, l, i; 18632001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r); 18732001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g); 18832001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b); 18932001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a); 19032001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_LUMINANCE_SIZE, &l); 19132001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTENSITY_SIZE, &i); 19232001f49Smrg printf("Compressed Bits per R: %d G: %d B: %d A: %d L: %d I: %d\n", 19332001f49Smrg r, g, b, a, l, i); 19432001f49Smrg } 19532001f49Smrg 19632001f49Smrg /* okay, now cache the compressed texture */ 19732001f49Smrg Tx->TC = TC; 19832001f49Smrg if (Tx->cData != NULL) { 19932001f49Smrg free(Tx->cData); 20032001f49Smrg Tx->cData = NULL; 20132001f49Smrg } 20232001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &rv); 20332001f49Smrg if (rv) { 20432001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&Tx->cFormat); 20532001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&Tx->cSize); 20632001f49Smrg if ((Tx->cData = malloc(Tx->cSize)) != NULL) { 20732001f49Smrg glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, Tx->cData); 20832001f49Smrg } 20932001f49Smrg } 21032001f49Smrg } 21132001f49Smrg} 21232001f49Smrg 21332001f49Smrg 21432001f49Smrgstatic void Init( void ) 21532001f49Smrg{ 21632001f49Smrg /* HEIGHT * WIDTH + 1 (for trailing '\0') */ 21732001f49Smrg static char pattern[8 * 32 + 1] = {"\ 21832001f49Smrg \ 21932001f49Smrg MMM EEEE SSS AAA \ 22032001f49Smrg M M M E S S A A \ 22132001f49Smrg M M M EEEE SS A A \ 22232001f49Smrg M M M E SS AAAAA \ 22332001f49Smrg M M E S S A A \ 22432001f49Smrg M M EEEE SSS A A \ 22532001f49Smrg " 22632001f49Smrg }; 22732001f49Smrg 22832001f49Smrg GLuint i, j; 22932001f49Smrg 23032001f49Smrg GLubyte (*texture1)[8 * 32][4]; 23132001f49Smrg GLubyte (*texture2)[256][256][4]; 23232001f49Smrg 23332001f49Smrg t1.w = 32; 23432001f49Smrg t1.h = 8; 23532001f49Smrg t1.size = t1.w * t1.h * 4; 23632001f49Smrg t1.data = malloc(t1.size); 23732001f49Smrg t1.format = GL_RGBA; 23832001f49Smrg t1.TC = GL_RGBA; 23932001f49Smrg 24032001f49Smrg texture1 = (GLubyte (*)[8 * 32][4])t1.data; 24132001f49Smrg for (i = 0; i < sizeof(pattern) - 1; i++) { 24232001f49Smrg switch (pattern[i]) { 24332001f49Smrg default: 24432001f49Smrg case ' ': 24532001f49Smrg (*texture1)[i][0] = 255; 24632001f49Smrg (*texture1)[i][1] = 255; 24732001f49Smrg (*texture1)[i][2] = 255; 24832001f49Smrg (*texture1)[i][3] = 64; 24932001f49Smrg break; 25032001f49Smrg case 'M': 25132001f49Smrg (*texture1)[i][0] = 255; 25232001f49Smrg (*texture1)[i][1] = 0; 25332001f49Smrg (*texture1)[i][2] = 0; 25432001f49Smrg (*texture1)[i][3] = 255; 25532001f49Smrg break; 25632001f49Smrg case 'E': 25732001f49Smrg (*texture1)[i][0] = 0; 25832001f49Smrg (*texture1)[i][1] = 255; 25932001f49Smrg (*texture1)[i][2] = 0; 26032001f49Smrg (*texture1)[i][3] = 255; 26132001f49Smrg break; 26232001f49Smrg case 'S': 26332001f49Smrg (*texture1)[i][0] = 0; 26432001f49Smrg (*texture1)[i][1] = 0; 26532001f49Smrg (*texture1)[i][2] = 255; 26632001f49Smrg (*texture1)[i][3] = 255; 26732001f49Smrg break; 26832001f49Smrg case 'A': 26932001f49Smrg (*texture1)[i][0] = 255; 27032001f49Smrg (*texture1)[i][1] = 255; 27132001f49Smrg (*texture1)[i][2] = 0; 27232001f49Smrg (*texture1)[i][3] = 255; 27332001f49Smrg break; 27432001f49Smrg } 27532001f49Smrg } 27632001f49Smrg 27732001f49Smrg t2.w = 256; 27832001f49Smrg t2.h = 256; 27932001f49Smrg t2.size = t2.w * t2.h * 4; 28032001f49Smrg t2.data = malloc(t2.size); 28132001f49Smrg t2.format = GL_RGBA; 28232001f49Smrg t2.TC = GL_RGBA; 28332001f49Smrg 28432001f49Smrg texture2 = (GLubyte (*)[256][256][4])t2.data; 28532001f49Smrg for (j = 0; j < t2.h; j++) { 28632001f49Smrg for (i = 0; i < t2.w; i++) { 28732001f49Smrg (*texture2)[j][i][0] = sqrt(i * j * 255 * 255 / (t2.w * t2.h)); 28832001f49Smrg (*texture2)[j][i][1] = 0; 28932001f49Smrg (*texture2)[j][i][2] = 0; 29032001f49Smrg (*texture2)[j][i][3] = 255; 29132001f49Smrg } 29232001f49Smrg } 29332001f49Smrg 29432001f49Smrg t3.data = LoadRGBImage(TEXTURE_FILE, (GLint *)&t3.w, (GLint *)&t3.h, &t3.format); 29532001f49Smrg t3.size = t3.w * t3.h * ((t3.format == GL_RGB) ? 3 : 4); 29632001f49Smrg t3.TC = GL_RGBA; 29732001f49Smrg 29832001f49Smrg ReInit(GL_RGBA, Tx = &t1); 29932001f49Smrg 30032001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 30132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 30232001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 30332001f49Smrg glEnable(GL_TEXTURE_2D); 30432001f49Smrg 30532001f49Smrg glEnable(GL_BLEND); 30632001f49Smrg glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 30732001f49Smrg} 30832001f49Smrg 30932001f49Smrg 31032001f49Smrgstatic void Key( unsigned char key, int x, int y ) 31132001f49Smrg{ 31232001f49Smrg (void) x; 31332001f49Smrg (void) y; 31432001f49Smrg switch (key) { 31532001f49Smrg case 27: 31632001f49Smrg exit(0); 31732001f49Smrg break; 31832001f49Smrg case ' ': 31932001f49Smrg Anim = !Anim; 32032001f49Smrg if (Anim) 32132001f49Smrg glutIdleFunc( Idle ); 32232001f49Smrg else 32332001f49Smrg glutIdleFunc( NULL ); 32432001f49Smrg break; 32532001f49Smrg case 't': 32632001f49Smrg if (Tx == &t1) { 32732001f49Smrg Tx = &t2; 32832001f49Smrg } else if (Tx == &t2) { 32932001f49Smrg Tx = &t3; 33032001f49Smrg } else { 33132001f49Smrg Tx = &t1; 33232001f49Smrg } 33332001f49Smrg ReInit(Tx->TC, Tx); 33432001f49Smrg break; 33532001f49Smrg case '9': 33632001f49Smrg ReInit(GL_RGB, Tx); 33732001f49Smrg break; 33832001f49Smrg case '0': 33932001f49Smrg ReInit(GL_RGBA, Tx); 34032001f49Smrg break; 34132001f49Smrg case '1': 34232001f49Smrg ReInit(GL_COMPRESSED_RGB, Tx); 34332001f49Smrg break; 34432001f49Smrg case '2': 34532001f49Smrg ReInit(GL_COMPRESSED_RGBA, Tx); 34632001f49Smrg break; 34732001f49Smrg case '3': 34832001f49Smrg if (fxt1) ReInit(GL_COMPRESSED_RGB_FXT1_3DFX, Tx); 34932001f49Smrg break; 35032001f49Smrg case '4': 35132001f49Smrg if (fxt1) ReInit(GL_COMPRESSED_RGBA_FXT1_3DFX, Tx); 35232001f49Smrg break; 35332001f49Smrg case '5': 35432001f49Smrg if (dxtc) ReInit(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, Tx); 35532001f49Smrg break; 35632001f49Smrg case '6': 35732001f49Smrg if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, Tx); 35832001f49Smrg break; 35932001f49Smrg case '7': 36032001f49Smrg if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, Tx); 36132001f49Smrg break; 36232001f49Smrg case '8': 36332001f49Smrg if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, Tx); 36432001f49Smrg break; 36532001f49Smrg case 'a': 36632001f49Smrg if (s3tc) ReInit(GL_RGB_S3TC, Tx); 36732001f49Smrg break; 36832001f49Smrg case 's': 36932001f49Smrg if (s3tc) ReInit(GL_RGB4_S3TC, Tx); 37032001f49Smrg break; 37132001f49Smrg case 'd': 37232001f49Smrg if (s3tc) ReInit(GL_RGBA_S3TC, Tx); 37332001f49Smrg break; 37432001f49Smrg case 'f': 37532001f49Smrg if (s3tc) ReInit(GL_RGBA4_S3TC, Tx); 37632001f49Smrg break; 37732001f49Smrg } 37832001f49Smrg glutPostRedisplay(); 37932001f49Smrg} 38032001f49Smrg 38132001f49Smrg 38232001f49Smrgint main( int argc, char *argv[] ) 38332001f49Smrg{ 38432001f49Smrg float gl_version; 38532001f49Smrg GLint num_formats; 38632001f49Smrg GLint i; 38732001f49Smrg GLint formats[64]; 38832001f49Smrg 38932001f49Smrg 39032001f49Smrg glutInit( &argc, argv ); 39132001f49Smrg glutInitWindowPosition( 0, 0 ); 39232001f49Smrg glutInitWindowSize( 400, 300 ); 39332001f49Smrg 39432001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 39532001f49Smrg 39632001f49Smrg if (glutCreateWindow(argv[0]) <= 0) { 39732001f49Smrg printf("Couldn't create window\n"); 39832001f49Smrg exit(0); 39932001f49Smrg } 40032001f49Smrg 40132001f49Smrg glewInit(); 40232001f49Smrg gl_version = atof( (const char *) glGetString( GL_VERSION ) ); 40332001f49Smrg if ( (gl_version < 1.3) 40432001f49Smrg && !glutExtensionSupported("GL_ARB_texture_compression") ) { 40532001f49Smrg printf("Sorry, GL_ARB_texture_compression not supported\n"); 40632001f49Smrg exit(0); 40732001f49Smrg } 40832001f49Smrg if (glutExtensionSupported("GL_3DFX_texture_compression_FXT1")) { 40932001f49Smrg fxt1 = GL_TRUE; 41032001f49Smrg } 41132001f49Smrg if (glutExtensionSupported("GL_EXT_texture_compression_s3tc")) { 41232001f49Smrg dxtc = GL_TRUE; 41332001f49Smrg } 41432001f49Smrg if (glutExtensionSupported("GL_S3_s3tc")) { 41532001f49Smrg s3tc = GL_TRUE; 41632001f49Smrg } 41732001f49Smrg 41832001f49Smrg glGetIntegerv( GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, & num_formats ); 41932001f49Smrg 42032001f49Smrg (void) memset( formats, 0, sizeof( formats ) ); 42132001f49Smrg glGetIntegerv( GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats ); 42232001f49Smrg 42332001f49Smrg printf( "The following texture formats are supported:\n" ); 42432001f49Smrg for ( i = 0 ; i < num_formats ; i++ ) { 42532001f49Smrg printf( "\t%s\n", TextureName( formats[i] ) ); 42632001f49Smrg } 42732001f49Smrg 42832001f49Smrg Init(); 42932001f49Smrg 43032001f49Smrg glutReshapeFunc( Reshape ); 43132001f49Smrg glutKeyboardFunc( Key ); 43232001f49Smrg glutDisplayFunc( Display ); 43332001f49Smrg if (Anim) 43432001f49Smrg glutIdleFunc( Idle ); 43532001f49Smrg 43632001f49Smrg glutMainLoop(); 43732001f49Smrg return 0; 43832001f49Smrg} 439