132001f49Smrg/*
232001f49Smrg * Simple test of multiple textures
332001f49Smrg */
432001f49Smrg
532001f49Smrg
632001f49Smrg#include <stdio.h>
732001f49Smrg#include <stdlib.h>
832001f49Smrg#include <math.h>
932001f49Smrg#include <GL/glew.h>
1032001f49Smrg#include "glut_wrap.h"
1132001f49Smrg#include "readtex.h"
1232001f49Smrg
1332001f49Smrg#define TEST_CLAMP 0
1432001f49Smrg#define TEST_MIPMAPS 0
1532001f49Smrg#define TEST_GEN_COMPRESSED_MIPMAPS 0
1632001f49Smrg
1732001f49Smrg#define MAX_TEXTURES 8
1832001f49Smrg
1932001f49Smrg
2032001f49Smrgstatic int Win;
2132001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
2232001f49Smrgstatic GLboolean Anim = GL_TRUE;
2332001f49Smrgstatic GLboolean Blend = GL_FALSE;
2432001f49Smrgstatic GLuint Filter = 0;
2532001f49Smrgstatic GLboolean Clamp = GL_FALSE;
2632001f49Smrgstatic GLfloat Scale = 1.0;
2732001f49Smrg
2832001f49Smrgstatic GLuint NumTextures;
2932001f49Smrgstatic GLuint Textures[MAX_TEXTURES];
3032001f49Smrgstatic float TexRot[MAX_TEXTURES][3];
3132001f49Smrgstatic float TexPos[MAX_TEXTURES][3];
3232001f49Smrgstatic float TexAspect[MAX_TEXTURES];
3332001f49Smrg
3432001f49Smrgstatic const char *DefaultFiles[] = {
3532001f49Smrg   DEMOS_DATA_DIR "arch.rgb",
3632001f49Smrg   DEMOS_DATA_DIR "reflect.rgb",
3732001f49Smrg   DEMOS_DATA_DIR "tree2.rgba",
3832001f49Smrg   DEMOS_DATA_DIR "tile.rgb"
3932001f49Smrg};
4032001f49Smrg
4132001f49Smrg
4232001f49Smrg#define NUM_FILTERS 6
4332001f49Smrgstatic
4432001f49Smrgstruct filter {
4532001f49Smrg   GLenum min, mag;
4632001f49Smrg   const char *name;
4732001f49Smrg} FilterModes[NUM_FILTERS] = {
4832001f49Smrg   { GL_NEAREST, GL_NEAREST, "Nearest,Nearest" },
4932001f49Smrg   { GL_LINEAR, GL_LINEAR, "Linear,Linear" },
5032001f49Smrg   { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, "NearestMipmapNearest,Nearest" },
5132001f49Smrg   { GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR, "NearestMipmapNearest,Linear" },
5232001f49Smrg   { GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, "LinearMipmapNearest,Linear" },
5332001f49Smrg   { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, "LinearMipmapLinear,Linear" }
5432001f49Smrg};
5532001f49Smrg
5632001f49Smrg
5732001f49Smrg
5832001f49Smrg
5932001f49Smrgstatic void
6032001f49SmrgIdle(void)
6132001f49Smrg{
6232001f49Smrg   Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.02;
6332001f49Smrg   Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.04;
6432001f49Smrg   /* Zrot += 2.0; */
6532001f49Smrg   glutPostRedisplay();
6632001f49Smrg}
6732001f49Smrg
6832001f49Smrg
6932001f49Smrgstatic void
7032001f49SmrgDrawTextures(void)
7132001f49Smrg{
7232001f49Smrg   GLuint i;
7332001f49Smrg
7432001f49Smrg   for (i = 0; i < NumTextures; i++) {
7532001f49Smrg      GLfloat ar = TexAspect[i];
7632001f49Smrg
7732001f49Smrg      glPushMatrix();
7832001f49Smrg      glTranslatef(TexPos[i][0], TexPos[i][1], TexPos[i][2]);
7932001f49Smrg      glRotatef(TexRot[i][0], 1, 0, 0);
8032001f49Smrg      glRotatef(TexRot[i][1], 0, 1, 0);
8132001f49Smrg      glRotatef(TexRot[i][2], 0, 0, 1);
8232001f49Smrg
8332001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[i]);
8432001f49Smrg      glBegin(GL_POLYGON);
8532001f49Smrg#if TEST_CLAMP
8632001f49Smrg      glTexCoord2f( -0.5, -0.5 );   glVertex2f( -ar, -1.0 );
8732001f49Smrg      glTexCoord2f(  1.5, -0.5 );   glVertex2f(  ar, -1.0 );
8832001f49Smrg      glTexCoord2f(  1.5,  1.5 );   glVertex2f(  ar,  1.0 );
8932001f49Smrg      glTexCoord2f( -0.5,  1.5 );   glVertex2f( -ar,  1.0 );
9032001f49Smrg#else
9132001f49Smrg      glTexCoord2f( 0.0, 0.0 );   glVertex2f( -ar, -1.0 );
9232001f49Smrg      glTexCoord2f( 1.0, 0.0 );   glVertex2f(  ar, -1.0 );
9332001f49Smrg      glTexCoord2f( 1.0, 1.0 );   glVertex2f(  ar,  1.0 );
9432001f49Smrg      glTexCoord2f( 0.0, 1.0 );   glVertex2f( -ar,  1.0 );
9532001f49Smrg#endif
9632001f49Smrg      glEnd();
9732001f49Smrg
9832001f49Smrg      glPopMatrix();
9932001f49Smrg   }
10032001f49Smrg}
10132001f49Smrg
10232001f49Smrgstatic void
10332001f49SmrgDraw(void)
10432001f49Smrg{
10532001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10632001f49Smrg
10732001f49Smrg   if (Blend) {
10832001f49Smrg      glEnable(GL_BLEND);
10932001f49Smrg      glDisable(GL_DEPTH_TEST);
11032001f49Smrg   }
11132001f49Smrg   else {
11232001f49Smrg      glDisable(GL_BLEND);
11332001f49Smrg      glEnable(GL_DEPTH_TEST);
11432001f49Smrg   }
11532001f49Smrg
11632001f49Smrg   glPushMatrix();
11732001f49Smrg   glRotatef(Xrot, 1, 0, 0);
11832001f49Smrg   glRotatef(Yrot, 0, 1, 0);
11932001f49Smrg   glRotatef(Zrot, 0, 0, 1);
12032001f49Smrg   glScalef(Scale, Scale, Scale);
12132001f49Smrg
12232001f49Smrg   DrawTextures();
12332001f49Smrg
12432001f49Smrg   glPopMatrix();
12532001f49Smrg
12632001f49Smrg   glutSwapBuffers();
12732001f49Smrg}
12832001f49Smrg
12932001f49Smrg
13032001f49Smrgstatic void
13132001f49SmrgReshape(int width, int height)
13232001f49Smrg{
13332001f49Smrg   glViewport(0, 0, width, height);
13432001f49Smrg   glMatrixMode(GL_PROJECTION);
13532001f49Smrg   glLoadIdentity();
13632001f49Smrg   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 50.0);
13732001f49Smrg   glMatrixMode(GL_MODELVIEW);
13832001f49Smrg   glLoadIdentity();
13932001f49Smrg   glTranslatef(0.0, 0.0, -10.0);
14032001f49Smrg}
14132001f49Smrg
14232001f49Smrg
14332001f49Smrgstatic GLfloat
14432001f49SmrgRandFloat(float min, float max)
14532001f49Smrg{
14632001f49Smrg   float x = (float) (rand() % 1000) * 0.001;
14732001f49Smrg   x = x * (max - min) + min;
14832001f49Smrg   return x;
14932001f49Smrg}
15032001f49Smrg
15132001f49Smrg
15232001f49Smrgstatic void
15332001f49SmrgRandomize(void)
15432001f49Smrg{
15532001f49Smrg   GLfloat k = 1.0;
15632001f49Smrg   GLuint i;
15732001f49Smrg
15832001f49Smrg   srand(glutGet(GLUT_ELAPSED_TIME));
15932001f49Smrg
16032001f49Smrg   for (i = 0; i < NumTextures; i++) {
16132001f49Smrg      TexRot[i][0] = RandFloat(0.0, 360);
16232001f49Smrg      TexRot[i][1] = RandFloat(0.0, 360);
16332001f49Smrg      TexRot[i][2] = RandFloat(0.0, 360);
16432001f49Smrg      TexPos[i][0] = RandFloat(-k, k);
16532001f49Smrg      TexPos[i][1] = RandFloat(-k, k);
16632001f49Smrg      TexPos[i][2] = RandFloat(-k, k);
16732001f49Smrg   }
16832001f49Smrg}
16932001f49Smrg
17032001f49Smrg
17132001f49Smrgstatic void
17232001f49SmrgSetTexParams(void)
17332001f49Smrg{
17432001f49Smrg   GLuint i;
17532001f49Smrg   for (i = 0; i < NumTextures; i++) {
17632001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[i]);
17732001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
17832001f49Smrg                      FilterModes[Filter].min);
17932001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
18032001f49Smrg                      FilterModes[Filter].mag);
18132001f49Smrg
18232001f49Smrg      if (Clamp) {
18332001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
18432001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
18532001f49Smrg      }
18632001f49Smrg      else {
18732001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
18832001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
18932001f49Smrg      }
19032001f49Smrg   }
19132001f49Smrg}
19232001f49Smrg
19332001f49Smrg
19432001f49Smrgstatic void
19532001f49SmrgPrintState(void)
19632001f49Smrg{
19732001f49Smrg   printf("Blend=%s Filter=%s\n",
19832001f49Smrg          Blend ? "Y" : "n",
19932001f49Smrg          FilterModes[Filter].name);
20032001f49Smrg}
20132001f49Smrg
20232001f49Smrg
20332001f49Smrgstatic void
20432001f49SmrgKey(unsigned char key, int x, int y)
20532001f49Smrg{
20632001f49Smrg   const GLfloat step = 3.0;
20732001f49Smrg   (void) x;
20832001f49Smrg   (void) y;
20932001f49Smrg   switch (key) {
21032001f49Smrg   case 'a':
21132001f49Smrg   case ' ':
21232001f49Smrg      Anim = !Anim;
21332001f49Smrg      if (Anim)
21432001f49Smrg         glutIdleFunc(Idle);
21532001f49Smrg      else
21632001f49Smrg         glutIdleFunc(NULL);
21732001f49Smrg      break;
21832001f49Smrg   case 'b':
21932001f49Smrg      Blend = !Blend;
22032001f49Smrg      break;
22132001f49Smrg   case 's':
22232001f49Smrg      Scale /= 1.1;
22332001f49Smrg      break;
22432001f49Smrg   case 'S':
22532001f49Smrg      Scale *= 1.1;
22632001f49Smrg      break;
22732001f49Smrg   case 'f':
22832001f49Smrg      Filter = (Filter + 1) % NUM_FILTERS;
22932001f49Smrg      SetTexParams();
23032001f49Smrg      break;
23132001f49Smrg   case 'r':
23232001f49Smrg      Randomize();
23332001f49Smrg      break;
23432001f49Smrg#if TEST_CLAMP
23532001f49Smrg   case 'c':
23632001f49Smrg      Clamp = !Clamp;
23732001f49Smrg      SetTexParams();
23832001f49Smrg      break;
23932001f49Smrg#endif
24032001f49Smrg   case 'z':
24132001f49Smrg      Zrot -= step;
24232001f49Smrg      break;
24332001f49Smrg   case 'Z':
24432001f49Smrg      Zrot += step;
24532001f49Smrg      break;
24632001f49Smrg   case 27:
24732001f49Smrg      glutDestroyWindow(Win);
24832001f49Smrg      exit(0);
24932001f49Smrg      break;
25032001f49Smrg   }
25132001f49Smrg
25232001f49Smrg   PrintState();
25332001f49Smrg
25432001f49Smrg   glutPostRedisplay();
25532001f49Smrg}
25632001f49Smrg
25732001f49Smrg
25832001f49Smrgstatic void
25932001f49SmrgSpecialKey(int key, int x, int y)
26032001f49Smrg{
26132001f49Smrg   const GLfloat step = 3.0;
26232001f49Smrg   (void) x;
26332001f49Smrg   (void) y;
26432001f49Smrg   switch (key) {
26532001f49Smrg      case GLUT_KEY_UP:
26632001f49Smrg         Xrot -= step;
26732001f49Smrg         break;
26832001f49Smrg      case GLUT_KEY_DOWN:
26932001f49Smrg         Xrot += step;
27032001f49Smrg         break;
27132001f49Smrg      case GLUT_KEY_LEFT:
27232001f49Smrg         Yrot -= step;
27332001f49Smrg         break;
27432001f49Smrg      case GLUT_KEY_RIGHT:
27532001f49Smrg         Yrot += step;
27632001f49Smrg         break;
27732001f49Smrg   }
27832001f49Smrg   glutPostRedisplay();
27932001f49Smrg}
28032001f49Smrg
28132001f49Smrg
28232001f49Smrgstatic void
28332001f49SmrgLoadTextures(GLuint n, const char *files[])
28432001f49Smrg{
28532001f49Smrg   GLuint i;
28632001f49Smrg
28732001f49Smrg   NumTextures = n < MAX_TEXTURES ? n : MAX_TEXTURES;
28832001f49Smrg
28932001f49Smrg   glGenTextures(n, Textures);
29032001f49Smrg
29132001f49Smrg   SetTexParams();
29232001f49Smrg
29332001f49Smrg   for (i = 0; i < n; i++) {
29432001f49Smrg      GLint w, h;
29532001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[i]);
29632001f49Smrg#if TEST_MIPMAPS
29732001f49Smrg      {
29832001f49Smrg         static const GLubyte color[9][4] = {
29932001f49Smrg            {255, 0, 0},
30032001f49Smrg            {0, 255, 0},
30132001f49Smrg            {0, 0, 255},
30232001f49Smrg            {0, 255, 255},
30332001f49Smrg            {255, 0, 255},
30432001f49Smrg            {255, 255, 0},
30532001f49Smrg            {255, 128, 255},
30632001f49Smrg            {128, 128, 128},
30732001f49Smrg            {64, 64, 64}
30832001f49Smrg         };
30932001f49Smrg
31032001f49Smrg         GLubyte image[256*256*4];
31132001f49Smrg         int i, level;
31232001f49Smrg         w = h = 256;
31332001f49Smrg         for (level = 0; level <= 8; level++) {
31432001f49Smrg            for (i = 0; i < w * h; i++) {
31532001f49Smrg               image[i*4+0] = color[level][0];
31632001f49Smrg               image[i*4+1] = color[level][1];
31732001f49Smrg               image[i*4+2] = color[level][2];
31832001f49Smrg               image[i*4+3] = color[level][3];
31932001f49Smrg            }
32032001f49Smrg            printf("Load level %d: %d x %d\n", level, w>>level, h>>level);
32132001f49Smrg            glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w>>level, h>>level, 0,
32232001f49Smrg                         GL_RGBA, GL_UNSIGNED_BYTE, image);
32332001f49Smrg         }
32432001f49Smrg      }
32532001f49Smrg#elif TEST_GEN_COMPRESSED_MIPMAPS
32632001f49Smrg      {
32732001f49Smrg         GLenum intFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
32832001f49Smrg         int f;
32932001f49Smrg         GLenum format;
33032001f49Smrg         GLubyte *img = LoadRGBImage(files[i], &w, &h, &format);
33132001f49Smrg         GLboolean write_compressed = GL_FALSE;
33232001f49Smrg         GLboolean read_compressed = GL_FALSE;
33332001f49Smrg
33432001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
33532001f49Smrg         glTexImage2D(GL_TEXTURE_2D, 0, intFormat, w, h, 0,
33632001f49Smrg                      format, GL_UNSIGNED_BYTE, img);
33732001f49Smrg         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
33832001f49Smrg         free(img);
33932001f49Smrg
34032001f49Smrg         glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
34132001f49Smrg                                  GL_TEXTURE_INTERNAL_FORMAT, &f);
34232001f49Smrg         printf("actual internal format 0x%x\n", f);
34332001f49Smrg
34432001f49Smrg         if (write_compressed) {
34532001f49Smrg            GLint i, sz, w, h;
34632001f49Smrg            int num_levels = 8;
34732001f49Smrg            for (i = 0; i < num_levels; i++) {
34832001f49Smrg               char name[20], *buf;
34932001f49Smrg               FILE *f;
35032001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
35132001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
35232001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
35332001f49Smrg                                        GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sz);
35432001f49Smrg               printf("Writing level %d: %d x %d  bytes: %d\n", i, w, h, sz);
35532001f49Smrg               buf = malloc(sz);
35632001f49Smrg               glGetCompressedTexImageARB(GL_TEXTURE_2D, i, buf);
35732001f49Smrg               sprintf(name, "comp%d", i);
35832001f49Smrg               f = fopen(name, "w");
35932001f49Smrg               fwrite(buf, 1, sz, f);
36032001f49Smrg               fclose(f);
36132001f49Smrg               free(buf);
36232001f49Smrg            }
36332001f49Smrg         }
36432001f49Smrg
36532001f49Smrg         if (read_compressed) {
36632001f49Smrg            GLint i, sz, w, h;
36732001f49Smrg            int num_levels = 8;
36832001f49Smrg            for (i = 01; i < num_levels; i++) {
36932001f49Smrg               char name[20], *buf;
37032001f49Smrg               FILE *f;
37132001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
37232001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
37332001f49Smrg               glGetTexLevelParameteriv(GL_TEXTURE_2D, i,
37432001f49Smrg                                        GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sz);
37532001f49Smrg               buf = malloc(sz);
37632001f49Smrg               sprintf(name, "comp%d", i);
37732001f49Smrg               printf("Reading level %d: %d x %d  bytes: %d from %s\n",
37832001f49Smrg                      i, w, h, sz, name);
37932001f49Smrg               f = fopen(name, "r");
38032001f49Smrg               fread(buf, 1, sz, f);
38132001f49Smrg               fclose(f);
38232001f49Smrg               glCompressedTexImage2DARB(GL_TEXTURE_2D, i, intFormat,
38332001f49Smrg                                         w, h, 0, sz, buf);
38432001f49Smrg               free(buf);
38532001f49Smrg            }
38632001f49Smrg         }
38732001f49Smrg      }
38832001f49Smrg#else
38932001f49Smrg      if (!LoadRGBMipmaps2(files[i], GL_TEXTURE_2D, GL_RGB, &w, &h)) {
39032001f49Smrg         printf("Error: couldn't load %s\n", files[i]);
39132001f49Smrg         exit(1);
39232001f49Smrg      }
39332001f49Smrg#endif
39432001f49Smrg      TexAspect[i] = (float) w / (float) h;
39532001f49Smrg      printf("Loaded %s\n", files[i]);
39632001f49Smrg   }
39732001f49Smrg}
39832001f49Smrg
39932001f49Smrg
40032001f49Smrgstatic void
40132001f49SmrgInit(int argc, const char *argv[])
40232001f49Smrg{
40332001f49Smrg   if (argc == 1)
40432001f49Smrg      LoadTextures(4, DefaultFiles);
40532001f49Smrg   else
40632001f49Smrg      LoadTextures(argc - 1, argv + 1);
40732001f49Smrg
40832001f49Smrg   Randomize();
40932001f49Smrg
41032001f49Smrg   glEnable(GL_TEXTURE_2D);
41132001f49Smrg
41232001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
41332001f49Smrg   glColor4f(1, 1, 1, 0.5);
41432001f49Smrg
41532001f49Smrg#if 0
41632001f49Smrg   /* setup lighting, etc */
41732001f49Smrg   glEnable(GL_LIGHTING);
41832001f49Smrg   glEnable(GL_LIGHT0);
41932001f49Smrg#endif
42032001f49Smrg}
42132001f49Smrg
42232001f49Smrg
42332001f49Smrgstatic void
42432001f49SmrgUsage(void)
42532001f49Smrg{
42632001f49Smrg   printf("Usage:\n");
42732001f49Smrg   printf("  textures [file.rgb] ...\n");
42832001f49Smrg   printf("Keys:\n");
42932001f49Smrg   printf("  a - toggle animation\n");
43032001f49Smrg   printf("  b - toggle blending\n");
43132001f49Smrg   printf("  f - change texture filter mode\n");
43232001f49Smrg   printf("  r - randomize\n");
43332001f49Smrg   printf("  ESC - exit\n");
43432001f49Smrg}
43532001f49Smrg
43632001f49Smrg
43732001f49Smrgint
43832001f49Smrgmain(int argc, char *argv[])
43932001f49Smrg{
44032001f49Smrg   glutInitWindowSize(700, 700);
44132001f49Smrg   glutInit(&argc, argv);
44232001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
44332001f49Smrg   Win = glutCreateWindow(argv[0]);
44432001f49Smrg   glewInit();
44532001f49Smrg   glutReshapeFunc(Reshape);
44632001f49Smrg   glutKeyboardFunc(Key);
44732001f49Smrg   glutSpecialFunc(SpecialKey);
44832001f49Smrg   glutDisplayFunc(Draw);
44932001f49Smrg   if (Anim)
45032001f49Smrg      glutIdleFunc(Idle);
45132001f49Smrg   Init(argc, (const char **) argv);
45232001f49Smrg   Usage();
45332001f49Smrg   PrintState();
45432001f49Smrg   glutMainLoop();
45532001f49Smrg   return 0;
45632001f49Smrg}
457