1
2/* GL_NV_texture_rectangle test
3 *
4 * Brian Paul
5 * 14 June 2002
6 */
7
8
9#include <math.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <GL/glew.h>
14#include "glut_wrap.h"
15#include "readtex.h"
16
17#define TEXTURE_0_FILE DEMOS_DATA_DIR "girl.rgb"
18#define TEXTURE_1_FILE DEMOS_DATA_DIR "reflect.rgb"
19
20#define TEX0 1
21#define TEX7 8
22#define ANIMATE 10
23#define CLAMP 20
24#define CLAMP_TO_EDGE 21
25#define CLAMP_TO_BORDER 22
26#define LINEAR_FILTER 30
27#define NEAREST_FILTER 31
28#define QUIT 100
29
30static GLboolean Animate = GL_FALSE;
31static GLint NumUnits = 2;
32static GLboolean TexEnabled[8];
33static GLint Width[8], Height[8];  /* image sizes */
34static GLenum Format[8];
35
36static GLfloat Xrot = 00.0, Yrot = 00.0, Zrot = 0.0;
37
38
39static void Idle( void )
40{
41   Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.01;
42   glutPostRedisplay();
43}
44
45
46static void DrawObject(void)
47{
48   GLint i;
49   GLfloat d = 10;  /* so we can see how borders are handled */
50
51   glColor3f(.1, .1, .1);  /* modulate this */
52
53   glPushMatrix();
54
55      glRotatef(Zrot, 0, 0, 1);
56
57      glBegin(GL_QUADS);
58
59      for (i = 0; i < NumUnits; i++)
60         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i, -d, -d);
61      glVertex2f(-1.0, -1.0);
62
63      for (i = 0; i < NumUnits; i++)
64         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i, Width[i]+d, -d);
65      glVertex2f(1.0, -1.0);
66
67      for (i = 0; i < NumUnits; i++)
68         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i, Width[i]+d, Height[i]+d);
69      glVertex2f(1.0, 1.0);
70
71      for (i = 0; i < NumUnits; i++)
72         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i, -d, Height[i]+d);
73      glVertex2f(-1.0, 1.0);
74
75      glEnd();
76   glPopMatrix();
77}
78
79
80static void Display( void )
81{
82   glClear( GL_COLOR_BUFFER_BIT );
83
84   glPushMatrix();
85      glRotatef(Xrot, 1.0, 0.0, 0.0);
86      glRotatef(Yrot, 0.0, 1.0, 0.0);
87      glRotatef(Zrot, 0.0, 0.0, 1.0);
88      glScalef(5.0, 5.0, 5.0);
89      DrawObject();
90   glPopMatrix();
91
92   glutSwapBuffers();
93}
94
95
96static void Reshape( int width, int height )
97{
98   glViewport( 0, 0, width, height );
99   glMatrixMode( GL_PROJECTION );
100   glLoadIdentity();
101   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 100.0 );
102   glMatrixMode( GL_MODELVIEW );
103   glLoadIdentity();
104   glTranslatef( 0.0, 0.0, -35.0 );
105}
106
107
108static void ModeMenu(int entry)
109{
110   GLint i;
111   if (entry >= TEX0 && entry < TEX0 + NumUnits) {
112      /* toggle */
113      i = entry - TEX0;
114      TexEnabled[i] = !TexEnabled[i];
115      glActiveTextureARB(GL_TEXTURE0_ARB + i);
116      if (TexEnabled[i]) {
117         glEnable(GL_TEXTURE_RECTANGLE_NV);
118      }
119      else {
120         glDisable(GL_TEXTURE_RECTANGLE_NV);
121      }
122      printf("Enabled: ");
123      for (i = 0; i < NumUnits; i++)
124         printf("%d ", (int) TexEnabled[i]);
125      printf("\n");
126   }
127   else if (entry==ANIMATE) {
128      Animate = !Animate;
129      if (Animate)
130         glutIdleFunc(Idle);
131      else
132         glutIdleFunc(NULL);
133   }
134   else if (entry==CLAMP) {
135      for (i = 0; i < NumUnits; i++) {
136         glActiveTextureARB(GL_TEXTURE0_ARB + i);
137         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
138         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
139      }
140   }
141   else if (entry==CLAMP_TO_EDGE) {
142      for (i = 0; i < NumUnits; i++) {
143         glActiveTextureARB(GL_TEXTURE0_ARB + i);
144         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
145         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
146      }
147   }
148   else if (entry==CLAMP_TO_BORDER) {
149      for (i = 0; i < NumUnits; i++) {
150         glActiveTextureARB(GL_TEXTURE0_ARB + i);
151         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
152         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
153      }
154   }
155   else if (entry==NEAREST_FILTER) {
156      for (i = 0; i < NumUnits; i++) {
157         glActiveTextureARB(GL_TEXTURE0_ARB + i);
158         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
159         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
160      }
161   }
162   else if (entry==LINEAR_FILTER) {
163      for (i = 0; i < NumUnits; i++) {
164         glActiveTextureARB(GL_TEXTURE0_ARB + i);
165         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
166         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
167      }
168   }
169
170   else if (entry==QUIT) {
171      exit(0);
172   }
173
174   glutPostRedisplay();
175}
176
177
178static void Key( unsigned char key, int x, int y )
179{
180   (void) x;
181   (void) y;
182   switch (key) {
183      case 'z':
184         Zrot -= 1.0;
185         break;
186      case 'Z':
187         Zrot += 1.0;
188         break;
189      case 'a':
190         Animate = !Animate;
191         if (Animate)
192            glutIdleFunc(Idle);
193         else
194            glutIdleFunc(NULL);
195         break;
196      case 27:
197         exit(0);
198         break;
199   }
200   glutPostRedisplay();
201}
202
203
204static void SpecialKey( int key, int x, int y )
205{
206   float step = 3.0;
207   (void) x;
208   (void) y;
209
210   switch (key) {
211      case GLUT_KEY_UP:
212         Xrot += step;
213         break;
214      case GLUT_KEY_DOWN:
215         Xrot -= step;
216         break;
217      case GLUT_KEY_LEFT:
218         Yrot += step;
219         break;
220      case GLUT_KEY_RIGHT:
221         Yrot -= step;
222         break;
223   }
224   glutPostRedisplay();
225}
226
227
228static void Init( int argc, char *argv[] )
229{
230   const GLenum wrap = GL_CLAMP;
231   GLuint texObj[8];
232   GLint size, i;
233
234   if (!glutExtensionSupported("GL_ARB_multitexture")) {
235      printf("Sorry, GL_ARB_multitexture needed by this program\n");
236      exit(1);
237   }
238
239   if (!glutExtensionSupported("GL_NV_texture_rectangle")) {
240      printf("Sorry, GL_NV_texture_rectangle needed by this program\n");
241      exit(1);
242   }
243
244   glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &NumUnits);
245   printf("%d texture units supported, using 2.\n", NumUnits);
246   if (NumUnits > 2)
247      NumUnits = 2;
248
249   glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &size);
250   printf("%d x %d max texture rectangle size\n", size, size);
251
252   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
253
254   for (i = 0; i < NumUnits; i++) {
255      TexEnabled[i] = GL_TRUE;
256   }
257
258   /* allocate two texture objects */
259   glGenTextures(NumUnits, texObj);
260
261   /* setup the texture objects */
262   for (i = 0; i < NumUnits; i++) {
263
264      glActiveTextureARB(GL_TEXTURE0_ARB + i);
265
266      glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj[i]);
267      glTexParameteri(GL_TEXTURE_RECTANGLE_NV,
268                      GL_TEXTURE_MIN_FILTER, GL_NEAREST);
269      glTexParameteri(GL_TEXTURE_RECTANGLE_NV,
270                      GL_TEXTURE_MAG_FILTER, GL_NEAREST);
271      glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, wrap);
272      glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, wrap);
273
274      if (i == 0) {
275         GLubyte *img = LoadRGBImage(TEXTURE_0_FILE, &Width[0], &Height[0],
276                                     &Format[0]);
277         if (!img) {
278            printf("Error: couldn't load texture image\n");
279            exit(1);
280         }
281         printf("Texture %d:  %s (%d x %d)\n", i,
282                TEXTURE_0_FILE, Width[0], Height[0]);
283         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB,
284                      Width[0], Height[0], 0,
285                      Format[0], GL_UNSIGNED_BYTE, img);
286      }
287      else {
288         GLubyte *img = LoadRGBImage(TEXTURE_1_FILE, &Width[1], &Height[1],
289                                     &Format[1]);
290         if (!img) {
291            printf("Error: couldn't load texture image\n");
292            exit(1);
293         }
294         printf("Texture %d:  %s (%d x %d)\n", i,
295                TEXTURE_1_FILE, Width[1], Height[1]);
296         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB,
297                      Width[1], Height[1], 0,
298                      Format[1], GL_UNSIGNED_BYTE, img);
299      }
300
301      if (i < 1)
302         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
303      else
304         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
305
306      if (TexEnabled[i])
307         glEnable(GL_TEXTURE_RECTANGLE_NV);
308   }
309
310   glShadeModel(GL_FLAT);
311   glClearColor(0.3, 0.3, 0.4, 1.0);
312
313   if (argc > 1 && strcmp(argv[1], "-info")==0) {
314      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
315      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
316      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
317      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
318   }
319}
320
321
322int main( int argc, char *argv[] )
323{
324   GLint i;
325
326   glutInit( &argc, argv );
327   glutInitWindowSize( 300, 300 );
328   glutInitWindowPosition( 0, 0 );
329   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
330   glutCreateWindow(argv[0] );
331   glewInit();
332
333   Init( argc, argv );
334
335   glutReshapeFunc( Reshape );
336   glutKeyboardFunc( Key );
337   glutSpecialFunc( SpecialKey );
338   glutDisplayFunc( Display );
339   if (Animate)
340      glutIdleFunc( Idle );
341
342   glutCreateMenu(ModeMenu);
343
344   for (i = 0; i < NumUnits; i++) {
345      char s[100];
346      sprintf(s, "Toggle Texture %d", i);
347      glutAddMenuEntry(s, TEX0 + i);
348   }
349   glutAddMenuEntry("Toggle Animation", ANIMATE);
350   glutAddMenuEntry("GL_CLAMP", CLAMP);
351   glutAddMenuEntry("GL_CLAMP_TO_EDGE", CLAMP_TO_EDGE);
352   glutAddMenuEntry("GL_CLAMP_TO_BORDER", CLAMP_TO_BORDER);
353   glutAddMenuEntry("GL_NEAREST", NEAREST_FILTER);
354   glutAddMenuEntry("GL_LINEAR", LINEAR_FILTER);
355   glutAddMenuEntry("Quit", QUIT);
356   glutAttachMenu(GLUT_RIGHT_BUTTON);
357
358   glutMainLoop();
359   return 0;
360}
361