Merge branch '7.8'
[mesa.git] / progs / demos / textures.c
1 /*
2 * Simple test of multiple textures
3 */
4
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <GL/glew.h>
10 #include <GL/glut.h>
11 #include "readtex.h"
12
13 #define TEST_CLAMP 0
14 #define TEST_MIPMAPS 0
15 #define TEST_GEN_COMPRESSED_MIPMAPS 0
16
17 #define MAX_TEXTURES 8
18
19
20 static int Win;
21 static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
22 static GLboolean Anim = GL_TRUE;
23 static GLboolean Blend = GL_FALSE;
24 static GLuint Filter = 0;
25 static GLboolean Clamp = GL_FALSE;
26
27 static GLuint NumTextures;
28 static GLuint Textures[MAX_TEXTURES];
29 static float TexRot[MAX_TEXTURES][3];
30 static float TexPos[MAX_TEXTURES][3];
31 static float TexAspect[MAX_TEXTURES];
32
33 static const char *DefaultFiles[] = {
34 "../images/arch.rgb",
35 "../images/reflect.rgb",
36 "../images/tree2.rgba",
37 "../images/tile.rgb"
38 };
39
40
41 #define NUM_FILTERS 5
42 static
43 struct filter {
44 GLenum min, mag;
45 const char *name;
46 } FilterModes[NUM_FILTERS] = {
47 { GL_NEAREST, GL_NEAREST, "Nearest,Nearest" },
48 { GL_LINEAR, GL_LINEAR, "Linear,Linear" },
49 { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, "NearestMipmapNearest,Nearest" },
50 { GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, "LinearMipmapNearest,Linear" },
51 { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, "LinearMipmapLinear,Linear" }
52 };
53
54
55
56
57 static void
58 Idle(void)
59 {
60 Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.02;
61 Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.04;
62 /* Zrot += 2.0; */
63 glutPostRedisplay();
64 }
65
66
67 static void
68 DrawTextures(void)
69 {
70 GLuint i;
71
72 for (i = 0; i < NumTextures; i++) {
73 GLfloat ar = TexAspect[i];
74
75 glPushMatrix();
76 glTranslatef(TexPos[i][0], TexPos[i][1], TexPos[i][2]);
77 glRotatef(TexRot[i][0], 1, 0, 0);
78 glRotatef(TexRot[i][1], 0, 1, 0);
79 glRotatef(TexRot[i][2], 0, 0, 1);
80
81 glBindTexture(GL_TEXTURE_2D, Textures[i]);
82 glBegin(GL_POLYGON);
83 #if TEST_CLAMP
84 glTexCoord2f( -0.5, -0.5 ); glVertex2f( -ar, -1.0 );
85 glTexCoord2f( 1.5, -0.5 ); glVertex2f( ar, -1.0 );
86 glTexCoord2f( 1.5, 1.5 ); glVertex2f( ar, 1.0 );
87 glTexCoord2f( -0.5, 1.5 ); glVertex2f( -ar, 1.0 );
88 #else
89 glTexCoord2f( 0.0, 0.0 ); glVertex2f( -ar, -1.0 );
90 glTexCoord2f( 1.0, 0.0 ); glVertex2f( ar, -1.0 );
91 glTexCoord2f( 1.0, 1.0 ); glVertex2f( ar, 1.0 );
92 glTexCoord2f( 0.0, 1.0 ); glVertex2f( -ar, 1.0 );
93 #endif
94 glEnd();
95
96 glPopMatrix();
97 }
98 }
99
100 static void
101 Draw(void)
102 {
103 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
104
105 if (Blend) {
106 glEnable(GL_BLEND);
107 glDisable(GL_DEPTH_TEST);
108 }
109 else {
110 glDisable(GL_BLEND);
111 glEnable(GL_DEPTH_TEST);
112 }
113
114 glPushMatrix();
115 glRotatef(Xrot, 1, 0, 0);
116 glRotatef(Yrot, 0, 1, 0);
117 glRotatef(Zrot, 0, 0, 1);
118
119 DrawTextures();
120
121 glPopMatrix();
122
123 glutSwapBuffers();
124 }
125
126
127 static void
128 Reshape(int width, int height)
129 {
130 glViewport(0, 0, width, height);
131 glMatrixMode(GL_PROJECTION);
132 glLoadIdentity();
133 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 50.0);
134 glMatrixMode(GL_MODELVIEW);
135 glLoadIdentity();
136 glTranslatef(0.0, 0.0, -10.0);
137 }
138
139
140 static GLfloat
141 RandFloat(float min, float max)
142 {
143 float x = (float) (rand() % 1000) * 0.001;
144 x = x * (max - min) + min;
145 return x;
146 }
147
148
149 static void
150 Randomize(void)
151 {
152 GLfloat k = 1.0;
153 GLuint i;
154
155 srand(glutGet(GLUT_ELAPSED_TIME));
156
157 for (i = 0; i < NumTextures; i++) {
158 TexRot[i][0] = RandFloat(0.0, 360);
159 TexRot[i][1] = RandFloat(0.0, 360);
160 TexRot[i][2] = RandFloat(0.0, 360);
161 TexPos[i][0] = RandFloat(-k, k);
162 TexPos[i][1] = RandFloat(-k, k);
163 TexPos[i][2] = RandFloat(-k, k);
164 }
165 }
166
167
168 static void
169 SetTexParams(void)
170 {
171 GLuint i;
172 for (i = 0; i < NumTextures; i++) {
173 glBindTexture(GL_TEXTURE_2D, Textures[i]);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
175 FilterModes[Filter].min);
176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
177 FilterModes[Filter].mag);
178
179 if (Clamp) {
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
182 }
183 else {
184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
186 }
187 }
188 }
189
190
191 static void
192 Key(unsigned char key, int x, int y)
193 {
194 const GLfloat step = 3.0;
195 (void) x;
196 (void) y;
197 switch (key) {
198 case 'a':
199 case ' ':
200 Anim = !Anim;
201 if (Anim)
202 glutIdleFunc(Idle);
203 else
204 glutIdleFunc(NULL);
205 break;
206 case 'b':
207 Blend = !Blend;
208 break;
209 case 'f':
210 Filter = (Filter + 1) % NUM_FILTERS;
211 SetTexParams();
212 break;
213 case 'r':
214 Randomize();
215 break;
216 #if TEST_CLAMP
217 case 'c':
218 Clamp = !Clamp;
219 SetTexParams();
220 break;
221 #endif
222 case 'z':
223 Zrot -= step;
224 break;
225 case 'Z':
226 Zrot += step;
227 break;
228 case 27:
229 glutDestroyWindow(Win);
230 exit(0);
231 break;
232 }
233
234 printf("Blend=%s Filter=%s\n",
235 Blend ? "Y" : "n",
236 FilterModes[Filter].name);
237
238 glutPostRedisplay();
239 }
240
241
242 static void
243 SpecialKey(int key, int x, int y)
244 {
245 const GLfloat step = 3.0;
246 (void) x;
247 (void) y;
248 switch (key) {
249 case GLUT_KEY_UP:
250 Xrot -= step;
251 break;
252 case GLUT_KEY_DOWN:
253 Xrot += step;
254 break;
255 case GLUT_KEY_LEFT:
256 Yrot -= step;
257 break;
258 case GLUT_KEY_RIGHT:
259 Yrot += step;
260 break;
261 }
262 glutPostRedisplay();
263 }
264
265
266 static void
267 LoadTextures(GLuint n, const char *files[])
268 {
269 GLuint i;
270
271 NumTextures = n < MAX_TEXTURES ? n : MAX_TEXTURES;
272
273 glGenTextures(n, Textures);
274
275 SetTexParams();
276
277 for (i = 0; i < n; i++) {
278 GLint w, h;
279 glBindTexture(GL_TEXTURE_2D, Textures[i]);
280 #if TEST_MIPMAPS
281 {
282 static const GLubyte color[9][4] = {
283 {255, 0, 0},
284 {0, 255, 0},
285 {0, 0, 255},
286 {0, 255, 255},
287 {255, 0, 255},
288 {255, 255, 0},
289 {255, 128, 255},
290 {128, 128, 128},
291 {64, 64, 64}
292 };
293
294 GLubyte image[256*256*4];
295 int i, level;
296 w = h = 256;
297 for (level = 0; level <= 8; level++) {
298 for (i = 0; i < w * h; i++) {
299 image[i*4+0] = color[level][0];
300 image[i*4+1] = color[level][1];
301 image[i*4+2] = color[level][2];
302 image[i*4+3] = color[level][3];
303 }
304 printf("Load level %d: %d x %d\n", level, w>>level, h>>level);
305 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w>>level, h>>level, 0,
306 GL_RGBA, GL_UNSIGNED_BYTE, image);
307 }
308 }
309 #elif TEST_GEN_COMPRESSED_MIPMAPS
310 {
311 GLenum intFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
312 int f;
313 GLenum format;
314 GLubyte *img = LoadRGBImage(files[i], &w, &h, &format);
315 GLboolean write_compressed = GL_FALSE;
316 GLboolean read_compressed = GL_FALSE;
317
318 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
319 glTexImage2D(GL_TEXTURE_2D, 0, intFormat, w, h, 0,
320 format, GL_UNSIGNED_BYTE, img);
321 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
322 free(img);
323
324 glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
325 GL_TEXTURE_INTERNAL_FORMAT, &f);
326 printf("actual internal format 0x%x\n", f);
327
328 if (write_compressed) {
329 GLint i, sz, w, h;
330 int num_levels = 8;
331 for (i = 0; i < num_levels; i++) {
332 char name[20], *buf;
333 FILE *f;
334 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
335 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
336 glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
337 GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sz);
338 printf("Writing level %d: %d x %d bytes: %d\n", i, w, h, sz);
339 buf = malloc(sz);
340 glGetCompressedTexImageARB(GL_TEXTURE_2D, i, buf);
341 sprintf(name, "comp%d", i);
342 f = fopen(name, "w");
343 fwrite(buf, 1, sz, f);
344 fclose(f);
345 free(buf);
346 }
347 }
348
349 if (read_compressed) {
350 GLint i, sz, w, h;
351 int num_levels = 8;
352 for (i = 01; i < num_levels; i++) {
353 char name[20], *buf;
354 FILE *f;
355 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
356 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
357 glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
358 GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sz);
359 buf = malloc(sz);
360 sprintf(name, "comp%d", i);
361 printf("Reading level %d: %d x %d bytes: %d from %s\n",
362 i, w, h, sz, name);
363 f = fopen(name, "r");
364 fread(buf, 1, sz, f);
365 fclose(f);
366 glCompressedTexImage2DARB(GL_TEXTURE_2D, i, intFormat,
367 w, h, 0, sz, buf);
368 free(buf);
369 }
370 }
371 }
372 #else
373 if (!LoadRGBMipmaps2(files[i], GL_TEXTURE_2D, GL_RGB, &w, &h)) {
374 printf("Error: couldn't load %s\n", files[i]);
375 exit(1);
376 }
377 #endif
378 TexAspect[i] = (float) w / (float) h;
379 printf("Loaded %s\n", files[i]);
380 }
381 }
382
383
384 static void
385 Init(int argc, const char *argv[])
386 {
387 if (argc == 1)
388 LoadTextures(4, DefaultFiles);
389 else
390 LoadTextures(argc - 1, argv + 1);
391
392 Randomize();
393
394 glEnable(GL_TEXTURE_2D);
395
396 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
397 glColor4f(1, 1, 1, 0.5);
398
399 #if 0
400 /* setup lighting, etc */
401 glEnable(GL_LIGHTING);
402 glEnable(GL_LIGHT0);
403 #endif
404 }
405
406
407 static void
408 Usage(void)
409 {
410 printf("Usage:\n");
411 printf(" textures [file.rgb] ...\n");
412 printf("Keys:\n");
413 printf(" a - toggle animation\n");
414 printf(" b - toggle blending\n");
415 printf(" f - change texture filter mode\n");
416 printf(" r - randomize\n");
417 printf(" ESC - exit\n");
418 }
419
420
421 int
422 main(int argc, char *argv[])
423 {
424 glutInitWindowSize(700, 700);
425 glutInit(&argc, argv);
426 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
427 Win = glutCreateWindow(argv[0]);
428 glewInit();
429 glutReshapeFunc(Reshape);
430 glutKeyboardFunc(Key);
431 glutSpecialFunc(SpecialKey);
432 glutDisplayFunc(Draw);
433 if (Anim)
434 glutIdleFunc(Idle);
435 Init(argc, (const char **) argv);
436 Usage();
437 glutMainLoop();
438 return 0;
439 }