132001f49Smrg/*
232001f49Smrg * GL_ARB_multitexture demo
332001f49Smrg *
432001f49Smrg * Command line options:
532001f49Smrg *    -info      print GL implementation information
632001f49Smrg *
732001f49Smrg *
832001f49Smrg * Brian Paul  November 1998  This program is in the public domain.
932001f49Smrg * Modified on 12 Feb 2002 for > 2 texture units.
1032001f49Smrg */
1132001f49Smrg
1232001f49Smrg
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <stdio.h>
1532001f49Smrg#include <stdlib.h>
1632001f49Smrg#include <string.h>
1732001f49Smrg#include <GL/glew.h>
1832001f49Smrg#include "glut_wrap.h"
1932001f49Smrg
2032001f49Smrg#include "readtex.h"
2132001f49Smrg
2232001f49Smrg#define TEXTURE_1_FILE DEMOS_DATA_DIR "girl.rgb"
2332001f49Smrg#define TEXTURE_2_FILE DEMOS_DATA_DIR "reflect.rgb"
2432001f49Smrg
2532001f49Smrg#define TEX0 1
2632001f49Smrg#define TEX7 8
2732001f49Smrg#define ANIMATE 10
2832001f49Smrg#define QUIT 100
2932001f49Smrg
3032001f49Smrgstatic GLint T0 = 0;
3132001f49Smrgstatic GLint Frames = 0;
3232001f49Smrgstatic GLboolean Animate = GL_TRUE;
3332001f49Smrgstatic GLint NumUnits = 1;
3432001f49Smrgstatic GLboolean TexEnabled[8];
3532001f49Smrg
3632001f49Smrgstatic GLfloat Drift = 0.0;
3732001f49Smrgstatic GLfloat Xrot = 20.0, Yrot = 30.0, Zrot = 0.0;
3832001f49Smrg
3932001f49Smrg
4032001f49Smrgstatic void Idle( void )
4132001f49Smrg{
4232001f49Smrg   if (Animate) {
4332001f49Smrg      GLint i;
4432001f49Smrg
4532001f49Smrg      Drift = glutGet(GLUT_ELAPSED_TIME) * 0.001;
4632001f49Smrg
4732001f49Smrg      for (i = 0; i < NumUnits; i++) {
4832001f49Smrg         glActiveTextureARB(GL_TEXTURE0_ARB + i);
4932001f49Smrg         glMatrixMode(GL_TEXTURE);
5032001f49Smrg         glLoadIdentity();
5132001f49Smrg         if (i == 0) {
5232001f49Smrg            glTranslatef(Drift, 0.0, 0.0);
5332001f49Smrg            glScalef(2, 2, 1);
5432001f49Smrg         }
5532001f49Smrg         else if (i == 1) {
5632001f49Smrg            glTranslatef(0.0, Drift, 0.0);
5732001f49Smrg         }
5832001f49Smrg         else {
5932001f49Smrg            float tx = 0.5, ty = 0.5;
6032001f49Smrg            glTranslatef(tx, ty, 0.0);
6132001f49Smrg            glRotatef(180.0 * Drift, 0, 0, 1);
6232001f49Smrg            glScalef(1.0/i, 1.0/i, 1.0/i);
6332001f49Smrg            glTranslatef(-tx, -ty + i * 0.1, 0.0);
6432001f49Smrg         }
6532001f49Smrg      }
6632001f49Smrg      glMatrixMode(GL_MODELVIEW);
6732001f49Smrg
6832001f49Smrg      glutPostRedisplay();
6932001f49Smrg   }
7032001f49Smrg}
7132001f49Smrg
7232001f49Smrg
7332001f49Smrgstatic void DrawObject(void)
7432001f49Smrg{
7532001f49Smrg   static const GLfloat tex_coords[] = {  0.0,  0.0,  1.0,  1.0,  0.0 };
7632001f49Smrg   static const GLfloat vtx_coords[] = { -1.0, -1.0,  1.0,  1.0, -1.0 };
7732001f49Smrg   GLint i, j;
7832001f49Smrg
7932001f49Smrg   if (!TexEnabled[0] && !TexEnabled[1])
8032001f49Smrg      glColor3f(0.1, 0.1, 0.1);  /* add onto this */
8132001f49Smrg   else
8232001f49Smrg      glColor3f(1, 1, 1);  /* modulate this */
8332001f49Smrg
8432001f49Smrg   glBegin(GL_QUADS);
8532001f49Smrg   for (j = 0; j < 4; j++ ) {
8632001f49Smrg      for (i = 0; i < NumUnits; i++) {
8732001f49Smrg         if (TexEnabled[i])
8832001f49Smrg            glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i,
8932001f49Smrg                                 tex_coords[j], tex_coords[j+1]);
9032001f49Smrg      }
9132001f49Smrg      glVertex2f( vtx_coords[j], vtx_coords[j+1] );
9232001f49Smrg   }
9332001f49Smrg   glEnd();
9432001f49Smrg}
9532001f49Smrg
9632001f49Smrg
9732001f49Smrgstatic void Display( void )
9832001f49Smrg{
9932001f49Smrg   glClear( GL_COLOR_BUFFER_BIT );
10032001f49Smrg
10132001f49Smrg   glPushMatrix();
10232001f49Smrg      glRotatef(Xrot, 1.0, 0.0, 0.0);
10332001f49Smrg      glRotatef(Yrot, 0.0, 1.0, 0.0);
10432001f49Smrg      glRotatef(Zrot, 0.0, 0.0, 1.0);
10532001f49Smrg      glScalef(5.0, 5.0, 5.0);
10632001f49Smrg      DrawObject();
10732001f49Smrg   glPopMatrix();
10832001f49Smrg
10932001f49Smrg   glutSwapBuffers();
11032001f49Smrg
11132001f49Smrg   Frames++;
11232001f49Smrg
11332001f49Smrg   {
11432001f49Smrg      GLint t = glutGet(GLUT_ELAPSED_TIME);
11532001f49Smrg      if (t - T0 >= 5000) {
11632001f49Smrg	 GLfloat seconds = (t - T0) / 1000.0;
11732001f49Smrg	 GLfloat fps = Frames / seconds;
11832001f49Smrg	 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
11932001f49Smrg	 fflush(stdout);
12032001f49Smrg	 T0 = t;
12132001f49Smrg	 Frames = 0;
12232001f49Smrg      }
12332001f49Smrg   }
12432001f49Smrg}
12532001f49Smrg
12632001f49Smrg
12732001f49Smrgstatic void Reshape( int width, int height )
12832001f49Smrg{
12932001f49Smrg   glViewport( 0, 0, width, height );
13032001f49Smrg   glMatrixMode( GL_PROJECTION );
13132001f49Smrg   glLoadIdentity();
13232001f49Smrg   glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
13332001f49Smrg   /*glOrtho( -6.0, 6.0, -6.0, 6.0, 10.0, 100.0 );*/
13432001f49Smrg   glMatrixMode( GL_MODELVIEW );
13532001f49Smrg   glLoadIdentity();
13632001f49Smrg   glTranslatef( 0.0, 0.0, -70.0 );
13732001f49Smrg}
13832001f49Smrg
13932001f49Smrg
14032001f49Smrgstatic void ToggleUnit(int unit)
14132001f49Smrg{
14232001f49Smrg   TexEnabled[unit] = !TexEnabled[unit];
14332001f49Smrg   glActiveTextureARB(GL_TEXTURE0_ARB + unit);
14432001f49Smrg   if (TexEnabled[unit])
14532001f49Smrg      glEnable(GL_TEXTURE_2D);
14632001f49Smrg   else
14732001f49Smrg      glDisable(GL_TEXTURE_2D);
14832001f49Smrg   printf("Enabled: ");
14932001f49Smrg   for (unit = 0; unit < NumUnits; unit++)
15032001f49Smrg      printf("%d ", (int) TexEnabled[unit]);
15132001f49Smrg   printf("\n");
15232001f49Smrg}
15332001f49Smrg
15432001f49Smrg
15532001f49Smrgstatic void ModeMenu(int entry)
15632001f49Smrg{
15732001f49Smrg   if (entry >= TEX0 && entry <= TEX7) {
15832001f49Smrg      /* toggle */
15932001f49Smrg      GLint i = entry - TEX0;
16032001f49Smrg      ToggleUnit(i);
16132001f49Smrg   }
16232001f49Smrg   else if (entry==ANIMATE) {
16332001f49Smrg      Animate = !Animate;
16432001f49Smrg      if (Animate)
16532001f49Smrg         glutIdleFunc(Idle);
16632001f49Smrg      else
16732001f49Smrg         glutIdleFunc(NULL);
16832001f49Smrg   }
16932001f49Smrg   else if (entry==QUIT) {
17032001f49Smrg      exit(0);
17132001f49Smrg   }
17232001f49Smrg
17332001f49Smrg   glutPostRedisplay();
17432001f49Smrg}
17532001f49Smrg
17632001f49Smrg
17732001f49Smrgstatic void Key( unsigned char key, int x, int y )
17832001f49Smrg{
17932001f49Smrg   (void) x;
18032001f49Smrg   (void) y;
18132001f49Smrg   switch (key) {
18232001f49Smrg   case 'a':
18332001f49Smrg      Animate = !Animate;
18432001f49Smrg      break;
18532001f49Smrg   case '0':
18632001f49Smrg      ToggleUnit(0);
18732001f49Smrg      break;
18832001f49Smrg   case '1':
18932001f49Smrg      ToggleUnit(1);
19032001f49Smrg      break;
19132001f49Smrg   case '2':
19232001f49Smrg      ToggleUnit(2);
19332001f49Smrg      break;
19432001f49Smrg   case '3':
19532001f49Smrg      ToggleUnit(3);
19632001f49Smrg      break;
19732001f49Smrg   case '4':
19832001f49Smrg      ToggleUnit(4);
19932001f49Smrg      break;
20032001f49Smrg   case '5':
20132001f49Smrg      ToggleUnit(5);
20232001f49Smrg      break;
20332001f49Smrg   case '6':
20432001f49Smrg      ToggleUnit(6);
20532001f49Smrg      break;
20632001f49Smrg   case '7':
20732001f49Smrg      ToggleUnit(7);
20832001f49Smrg      break;
20932001f49Smrg   case 27:
21032001f49Smrg      exit(0);
21132001f49Smrg      break;
21232001f49Smrg   }
21332001f49Smrg   glutPostRedisplay();
21432001f49Smrg}
21532001f49Smrg
21632001f49Smrg
21732001f49Smrgstatic void SpecialKey( int key, int x, int y )
21832001f49Smrg{
21932001f49Smrg   float step = 3.0;
22032001f49Smrg   (void) x;
22132001f49Smrg   (void) y;
22232001f49Smrg
22332001f49Smrg   switch (key) {
22432001f49Smrg      case GLUT_KEY_UP:
22532001f49Smrg         Xrot += step;
22632001f49Smrg         break;
22732001f49Smrg      case GLUT_KEY_DOWN:
22832001f49Smrg         Xrot -= step;
22932001f49Smrg         break;
23032001f49Smrg      case GLUT_KEY_LEFT:
23132001f49Smrg         Yrot += step;
23232001f49Smrg         break;
23332001f49Smrg      case GLUT_KEY_RIGHT:
23432001f49Smrg         Yrot -= step;
23532001f49Smrg         break;
23632001f49Smrg   }
23732001f49Smrg   glutPostRedisplay();
23832001f49Smrg}
23932001f49Smrg
24032001f49Smrg
24132001f49Smrgstatic void Init( int argc, char *argv[] )
24232001f49Smrg{
24332001f49Smrg   GLuint texObj[8];
24432001f49Smrg   GLint size, i;
24532001f49Smrg
24632001f49Smrg   const char *exten = (const char *) glGetString(GL_EXTENSIONS);
24732001f49Smrg   if (!strstr(exten, "GL_ARB_multitexture")) {
24832001f49Smrg      printf("Sorry, GL_ARB_multitexture not supported by this renderer.\n");
24932001f49Smrg      exit(1);
25032001f49Smrg   }
25132001f49Smrg
25232001f49Smrg   glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &NumUnits);
25332001f49Smrg   printf("%d texture units supported\n", NumUnits);
25432001f49Smrg   if (NumUnits > 8)
25532001f49Smrg      NumUnits = 8;
25632001f49Smrg
25732001f49Smrg   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
25832001f49Smrg   printf("%d x %d max texture size\n", size, size);
25932001f49Smrg
26032001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
26132001f49Smrg
26232001f49Smrg   for (i = 0; i < NumUnits; i++) {
26332001f49Smrg      if (i < 2)
26432001f49Smrg         TexEnabled[i] = GL_TRUE;
26532001f49Smrg      else
26632001f49Smrg         TexEnabled[i] = GL_FALSE;
26732001f49Smrg   }
26832001f49Smrg
26932001f49Smrg   /* allocate two texture objects */
27032001f49Smrg   glGenTextures(NumUnits, texObj);
27132001f49Smrg
27232001f49Smrg   /* setup the texture objects */
27332001f49Smrg   for (i = 0; i < NumUnits; i++) {
27432001f49Smrg
27532001f49Smrg      glActiveTextureARB(GL_TEXTURE0_ARB + i);
27632001f49Smrg      glBindTexture(GL_TEXTURE_2D, texObj[i]);
27732001f49Smrg
27832001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
27932001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
28032001f49Smrg
28132001f49Smrg      if (i == 0) {
28232001f49Smrg         if (!LoadRGBMipmaps(TEXTURE_1_FILE, GL_RGB)) {
28332001f49Smrg            printf("Error: couldn't load texture image\n");
28432001f49Smrg            exit(1);
28532001f49Smrg         }
28632001f49Smrg      }
28732001f49Smrg      else if (i == 1) {
28832001f49Smrg         if (!LoadRGBMipmaps(TEXTURE_2_FILE, GL_RGB)) {
28932001f49Smrg            printf("Error: couldn't load texture image\n");
29032001f49Smrg            exit(1);
29132001f49Smrg         }
29232001f49Smrg      }
29332001f49Smrg      else {
29432001f49Smrg         /* checker */
29532001f49Smrg         GLubyte image[8][8][3];
29632001f49Smrg         GLint i, j;
29732001f49Smrg         for (i = 0; i < 8; i++) {
29832001f49Smrg            for (j = 0; j < 8; j++) {
29932001f49Smrg               if ((i + j) & 1) {
30032001f49Smrg                  image[i][j][0] = 50;
30132001f49Smrg                  image[i][j][1] = 50;
30232001f49Smrg                  image[i][j][2] = 50;
30332001f49Smrg               }
30432001f49Smrg               else {
30532001f49Smrg                  image[i][j][0] = 25;
30632001f49Smrg                  image[i][j][1] = 25;
30732001f49Smrg                  image[i][j][2] = 25;
30832001f49Smrg               }
30932001f49Smrg            }
31032001f49Smrg         }
31132001f49Smrg         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0,
31232001f49Smrg                      GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) image);
31332001f49Smrg      }
31432001f49Smrg
31532001f49Smrg      /* Bind texObj[i] to ith texture unit */
31632001f49Smrg      if (i < 2)
31732001f49Smrg         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
31832001f49Smrg      else
31932001f49Smrg         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
32032001f49Smrg
32132001f49Smrg      if (TexEnabled[i])
32232001f49Smrg         glEnable(GL_TEXTURE_2D);
32332001f49Smrg   }
32432001f49Smrg
32532001f49Smrg   glShadeModel(GL_FLAT);
32632001f49Smrg   glClearColor(0.3, 0.3, 0.4, 1.0);
32732001f49Smrg
32832001f49Smrg   if (argc > 1 && strcmp(argv[1], "-info")==0) {
32932001f49Smrg      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
33032001f49Smrg      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
33132001f49Smrg      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
33232001f49Smrg      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
33332001f49Smrg   }
33432001f49Smrg}
33532001f49Smrg
33632001f49Smrg
33732001f49Smrgint main( int argc, char *argv[] )
33832001f49Smrg{
33932001f49Smrg   GLint i;
34032001f49Smrg
34132001f49Smrg   glutInitWindowSize( 300, 300 );
34232001f49Smrg   glutInit( &argc, argv );
34332001f49Smrg   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
34432001f49Smrg   glutCreateWindow(argv[0] );
34532001f49Smrg   glewInit();
34632001f49Smrg
34732001f49Smrg   Init( argc, argv );
34832001f49Smrg
34932001f49Smrg   glutReshapeFunc( Reshape );
35032001f49Smrg   glutKeyboardFunc( Key );
35132001f49Smrg   glutSpecialFunc( SpecialKey );
35232001f49Smrg   glutDisplayFunc( Display );
35332001f49Smrg   if (Animate)
35432001f49Smrg      glutIdleFunc(Idle);
35532001f49Smrg
35632001f49Smrg   glutCreateMenu(ModeMenu);
35732001f49Smrg
35832001f49Smrg   for (i = 0; i < NumUnits; i++) {
35932001f49Smrg      char s[100];
36032001f49Smrg      sprintf(s, "Toggle Texture %d", i);
36132001f49Smrg      glutAddMenuEntry(s, TEX0 + i);
36232001f49Smrg   }
36332001f49Smrg   glutAddMenuEntry("Toggle Animation", ANIMATE);
36432001f49Smrg   glutAddMenuEntry("Quit", QUIT);
36532001f49Smrg   glutAttachMenu(GLUT_RIGHT_BUTTON);
36632001f49Smrg
36732001f49Smrg   glutMainLoop();
36832001f49Smrg   return 0;
36932001f49Smrg}
370