blob: fe3f58cf347dc441509cef74ee7c6d8c9005a9f6 [file] [log] [blame]
Daniel Borca08e6fb32003-11-20 17:07:31 +00001/*
2 * Compressed texture demo. Written by Daniel Borca.
3 * This program is in the public domain.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <math.h>
9#include <string.h>
10#define GL_GLEXT_PROTOTYPES 1
11#include <GL/glut.h>
12
13#include "readtex.c" /* I know, this is a hack. */
14#define TEXTURE_FILE "../images/tree2.rgba"
15
16
17static float Rot = 0.0;
18static GLboolean Anim = 1;
19
20typedef struct {
21 GLubyte *data;
22 GLuint size;
23 GLenum format;
24 GLuint w, h;
25
26 GLenum TC;
27
28 GLubyte *cData;
29 GLuint cSize;
30 GLenum cFormat;
31} TEXTURE;
32
33static TEXTURE *Tx, t1, t2, t3;
34static GLboolean fxt1, dxtc, s3tc;
35
36
37static const char *TextureName (GLenum TC)
38{
39 switch (TC) {
Daniel Borca33ffbd12004-05-04 06:27:06 +000040 case GL_RGB:
41 return "RGB";
Daniel Borca08e6fb32003-11-20 17:07:31 +000042 case GL_RGBA:
43 return "RGBA";
44 case GL_COMPRESSED_RGB:
45 return "COMPRESSED_RGB";
46 case GL_COMPRESSED_RGBA:
47 return "COMPRESSED_RGBA";
48 case GL_COMPRESSED_RGB_FXT1_3DFX:
49 return "GL_COMPRESSED_RGB_FXT1_3DFX";
50 case GL_COMPRESSED_RGBA_FXT1_3DFX:
51 return "GL_COMPRESSED_RGBA_FXT1_3DFX";
52 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
53 return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT";
54 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
55 return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT";
56 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
57 return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT";
58 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
59 return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT";
60 case GL_RGB_S3TC:
61 return "GL_RGB_S3TC";
62 case GL_RGB4_S3TC:
63 return "GL_RGB4_S3TC";
64 case GL_RGBA_S3TC:
65 return "GL_RGBA_S3TC";
66 case GL_RGBA4_S3TC:
67 return "GL_RGBA4_S3TC";
68 default:
69 return "?";
70 }
71}
72
73
74static void
75PrintString(const char *s)
76{
77 while (*s) {
78 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
79 s++;
80 }
81}
82
83
84static void Idle( void )
85{
86 float t = glutGet(GLUT_ELAPSED_TIME) * 0.001; /* in seconds */
87 Rot = t * 360 / 4; /* 1 rotation per 4 seconds */
88 glutPostRedisplay();
89}
90
91
92static void Display( void )
93{
94 /* draw background gradient */
95 glDisable(GL_TEXTURE_2D);
96 glBegin(GL_POLYGON);
97 glColor3f(1.0, 0.0, 0.2); glVertex2f(-1.5, -1.0);
98 glColor3f(1.0, 0.0, 0.2); glVertex2f( 1.5, -1.0);
99 glColor3f(0.0, 0.0, 1.0); glVertex2f( 1.5, 1.0);
100 glColor3f(0.0, 0.0, 1.0); glVertex2f(-1.5, 1.0);
101 glEnd();
102
103 glPushMatrix();
104 glRotatef(Rot, 0, 0, 1);
105
106 glEnable(GL_TEXTURE_2D);
107 glBegin(GL_POLYGON);
108 glTexCoord2f(0, 1); glVertex2f(-1, -0.5);
109 glTexCoord2f(1, 1); glVertex2f( 1, -0.5);
110 glTexCoord2f(1, 0); glVertex2f( 1, 0.5);
111 glTexCoord2f(0, 0); glVertex2f(-1, 0.5);
112 glEnd();
113
114 glPopMatrix();
115
116 /* info */
117 glColor4f(1, 1, 1, 1);
118
119 glRasterPos3f(-1.2, -0.7, 0);
120 PrintString("Selected: ");
121 PrintString(TextureName(Tx->TC));
122 if (Tx->cData) {
123 char tmp[64];
124 glRasterPos3f(-1.2, -0.8, 0);
125 PrintString("Internal: ");
126 PrintString(TextureName(Tx->cFormat));
127 glRasterPos3f(-1.2, -0.9, 0);
128 PrintString("Size : ");
129 sprintf(tmp, "%d (%d%% of %d)", Tx->cSize, Tx->cSize * 100 / Tx->size, Tx->size);
130 PrintString(tmp);
131 }
132
133 glutSwapBuffers();
134}
135
136
137static void Reshape( int width, int height )
138{
139 glViewport( 0, 0, width, height );
140 glMatrixMode( GL_PROJECTION );
141 glLoadIdentity();
142 glOrtho( -1.5, 1.5, -1.0, 1.0, -1.0, 1.0 );
143 glMatrixMode( GL_MODELVIEW );
144 glLoadIdentity();
145}
146
147
148static void ReInit( GLenum TC, TEXTURE *Tx )
149{
150 GLint rv;
151
152 if ((Tx->TC == TC) && (Tx->cData != NULL)) {
153 glCompressedTexImage2DARB(GL_TEXTURE_2D, /* target */
154 0, /* level */
155 Tx->cFormat, /* real format */
156 Tx->w, /* original width */
157 Tx->h, /* original height */
158 0, /* border */
159 Tx->cSize, /* compressed size*/
160 Tx->cData); /* compressed data*/
161 } else {
162 glTexImage2D(GL_TEXTURE_2D, /* target */
163 0, /* level */
164 TC, /* internal format */
165 Tx->w, Tx->h, /* width, height */
166 0, /* border */
167 Tx->format, /* texture format */
168 GL_UNSIGNED_BYTE, /* texture type */
169 Tx->data); /* the texture */
170
171 /* okay, now cache the compressed texture */
172 Tx->TC = TC;
173 if (Tx->cData != NULL) {
174 free(Tx->cData);
175 Tx->cData = NULL;
176 }
177 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &rv);
178 if (rv) {
179 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&Tx->cFormat);
180 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&Tx->cSize);
181 if ((Tx->cData = malloc(Tx->cSize)) != NULL) {
182 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, Tx->cData);
183 }
184 }
185 }
186}
187
188
189static void Init( void )
190{
191 /* HEIGHT * WIDTH + 1 (for trailing '\0') */
192 static char pattern[8 * 32 + 1] = {"\
193 \
194 MMM EEEE SSS AAA \
195 M M M E S S A A \
196 M M M EEEE SS A A \
197 M M M E SS AAAAA \
198 M M E S S A A \
199 M M EEEE SSS A A \
200 "
201 };
202
203 GLuint i, j;
204
205 GLubyte (*texture1)[8 * 32][4];
206 GLubyte (*texture2)[256][256][4];
207
208 t1.w = 32;
209 t1.h = 8;
210 t1.size = t1.w * t1.h * 4;
211 t1.data = malloc(t1.size);
212 t1.format = GL_RGBA;
213 t1.TC = GL_RGBA;
214
215 texture1 = (GLubyte (*)[8 * 32][4])t1.data;
216 for (i = 0; i < sizeof(pattern) - 1; i++) {
217 switch (pattern[i]) {
218 default:
219 case ' ':
220 (*texture1)[i][0] = 255;
221 (*texture1)[i][1] = 255;
222 (*texture1)[i][2] = 255;
223 (*texture1)[i][3] = 64;
224 break;
225 case 'M':
226 (*texture1)[i][0] = 255;
227 (*texture1)[i][1] = 0;
228 (*texture1)[i][2] = 0;
229 (*texture1)[i][3] = 255;
230 break;
231 case 'E':
232 (*texture1)[i][0] = 0;
233 (*texture1)[i][1] = 255;
234 (*texture1)[i][2] = 0;
235 (*texture1)[i][3] = 255;
236 break;
237 case 'S':
238 (*texture1)[i][0] = 0;
239 (*texture1)[i][1] = 0;
240 (*texture1)[i][2] = 255;
241 (*texture1)[i][3] = 255;
242 break;
243 case 'A':
244 (*texture1)[i][0] = 255;
245 (*texture1)[i][1] = 255;
246 (*texture1)[i][2] = 0;
247 (*texture1)[i][3] = 255;
248 break;
249 }
250 }
251
252 t2.w = 256;
253 t2.h = 256;
254 t2.size = t2.w * t2.h * 4;
255 t2.data = malloc(t2.size);
256 t2.format = GL_RGBA;
257 t2.TC = GL_RGBA;
258
259 texture2 = (GLubyte (*)[256][256][4])t2.data;
260 for (j = 0; j < t2.h; j++) {
261 for (i = 0; i < t2.w; i++) {
262 (*texture2)[j][i][0] = sqrt(i * j * 255 * 255 / (t2.w * t2.h));
263 (*texture2)[j][i][1] = 0;
264 (*texture2)[j][i][2] = 0;
265 (*texture2)[j][i][3] = 255;
266 }
267 }
268
269 t3.data = LoadRGBImage(TEXTURE_FILE, (GLint *)&t3.w, (GLint *)&t3.h, &t3.format);
270 t3.size = t3.w * t3.h * ((t3.format == GL_RGB) ? 3 : 4);
271 t3.TC = GL_RGBA;
272
273 ReInit(GL_RGBA, Tx = &t1);
274
275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
277 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
278 glEnable(GL_TEXTURE_2D);
279
280 glEnable(GL_BLEND);
281 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
282}
283
284
285static void Key( unsigned char key, int x, int y )
286{
287 (void) x;
288 (void) y;
289 switch (key) {
290 case 27:
291 exit(0);
292 break;
293 case ' ':
294 Anim = !Anim;
295 if (Anim)
296 glutIdleFunc( Idle );
297 else
298 glutIdleFunc( NULL );
299 break;
300 case 't':
301 if (Tx == &t1) {
302 Tx = &t2;
303 } else if (Tx == &t2) {
304 Tx = &t3;
305 } else {
306 Tx = &t1;
307 }
308 ReInit(Tx->TC, Tx);
309 break;
Daniel Borcac35dcfc2004-04-29 09:01:41 +0000310 case '9':
311 ReInit(GL_RGB, Tx);
312 break;
Daniel Borca08e6fb32003-11-20 17:07:31 +0000313 case '0':
314 ReInit(GL_RGBA, Tx);
315 break;
316 case '1':
317 ReInit(GL_COMPRESSED_RGB, Tx);
318 break;
319 case '2':
320 ReInit(GL_COMPRESSED_RGBA, Tx);
321 break;
322 case '3':
323 if (fxt1) ReInit(GL_COMPRESSED_RGB_FXT1_3DFX, Tx);
324 break;
325 case '4':
326 if (fxt1) ReInit(GL_COMPRESSED_RGBA_FXT1_3DFX, Tx);
327 break;
328 case '5':
329 if (dxtc) ReInit(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, Tx);
330 break;
331 case '6':
332 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, Tx);
333 break;
334 case '7':
335 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, Tx);
336 break;
337 case '8':
338 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, Tx);
339 break;
340 case 'a':
341 if (s3tc) ReInit(GL_RGB_S3TC, Tx);
342 break;
343 case 's':
344 if (s3tc) ReInit(GL_RGB4_S3TC, Tx);
345 break;
346 case 'd':
347 if (s3tc) ReInit(GL_RGBA_S3TC, Tx);
348 break;
349 case 'f':
350 if (s3tc) ReInit(GL_RGBA4_S3TC, Tx);
351 break;
352 }
353 glutPostRedisplay();
354}
355
356
357int main( int argc, char *argv[] )
358{
359 glutInit( &argc, argv );
360 glutInitWindowPosition( 0, 0 );
361 glutInitWindowSize( 400, 300 );
362
363 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
364
365 if (glutCreateWindow(argv[0]) <= 0) {
366 printf("Couldn't create window\n");
367 exit(0);
368 }
369
370 if (!glutExtensionSupported("GL_ARB_texture_compression")) {
371 printf("Sorry, GL_ARB_texture_compression not supported\n");
372 exit(0);
373 }
374 if (glutExtensionSupported("GL_3DFX_texture_compression_FXT1")) {
375 fxt1 = GL_TRUE;
376 }
377 if (glutExtensionSupported("GL_EXT_texture_compression_s3tc")) {
378 dxtc = GL_TRUE;
379 }
380 if (glutExtensionSupported("GL_S3_s3tc")) {
381 s3tc = GL_TRUE;
382 }
383
384 Init();
385
386 glutReshapeFunc( Reshape );
387 glutKeyboardFunc( Key );
388 glutDisplayFunc( Display );
389 if (Anim)
390 glutIdleFunc( Idle );
391
392 glutMainLoop();
393 return 0;
394}