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