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