1/* 2 * GL_ATI_fragment_shader test 3 * Roland Scheidegger 4 * 5 * Command line options: 6 * -info print GL implementation information 7 */ 8 9 10#include <math.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <GL/glew.h> 15#include "glut_wrap.h" 16 17#include "readtex.h" 18 19#define TEXTURE_1_FILE DEMOS_DATA_DIR "girl.rgb" 20#define TEXTURE_2_FILE DEMOS_DATA_DIR "reflect.rgb" 21 22#define TEX0 1 23#define TEX7 8 24#define ANIMATE 10 25#define SHADER 20 26#define QUIT 100 27 28static GLboolean Animate = GL_TRUE; 29static GLint NumUnits = 6; 30static GLboolean TexEnabled[8]; 31static GLuint boringshaderID = 0; 32static GLuint boring2passID = 0; 33static GLboolean Shader = GL_FALSE; 34 35static GLfloat Drift = 0.0; 36static GLfloat drift_increment = 0.005; 37static GLfloat Xrot = 20.0, Yrot = 30.0, Zrot = 0.0; 38static GLfloat shaderconstant[4] = {0.5, 0.0, 0.0, 0.0}; 39 40static void Idle( void ) 41{ 42 if (Animate) { 43 GLint i; 44 45 Drift += drift_increment; 46 if (Drift >= 1.0) 47 Drift = 0.0; 48 49 for (i = 0; i < NumUnits; i++) { 50 glActiveTextureARB(GL_TEXTURE0_ARB + i); 51 glMatrixMode(GL_TEXTURE); 52 glLoadIdentity(); 53 if (i == 0) { 54 glTranslatef(Drift, 0.0, 0.0); 55 glScalef(2, 2, 1); 56 } 57 else if (i == 1) { 58 glTranslatef(0.0, Drift, 0.0); 59 } 60 else { 61 glTranslatef(0.5, 0.5, 0.0); 62 glRotatef(180.0 * Drift, 0, 0, 1); 63 glScalef(1.0/i, 1.0/i, 1.0/i); 64 glTranslatef(-0.5, -0.5, 0.0); 65 } 66 } 67 glMatrixMode(GL_MODELVIEW); 68 69 glutPostRedisplay(); 70 } 71} 72 73 74static void DrawObject(void) 75{ 76 GLint i; 77 GLint j; 78 static const GLfloat tex_coords[] = { 0.0, 0.0, 1.0, 1.0, 0.0 }; 79 static const GLfloat vtx_coords[] = { -1.0, -1.0, 1.0, 1.0, -1.0 }; 80 81 if (!TexEnabled[0] && !TexEnabled[1]) 82 glColor3f(0.1, 0.1, 0.1); /* add onto this */ 83 else 84 glColor3f(1, 1, 1); /* modulate this */ 85 86 glBegin(GL_QUADS); 87 88 /* Toggle between the vector and scalar entry points. This is done purely 89 * to hit multiple paths in the driver. 90 */ 91 if ( Drift > 0.49 ) { 92 for (j = 0; j < 4; j++ ) { 93 for (i = 0; i < NumUnits; i++) 94 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + i, 95 tex_coords[j], tex_coords[j+1]); 96 glVertex2f( vtx_coords[j], vtx_coords[j+1] ); 97 } 98 } 99 else { 100 for (j = 0; j < 4; j++ ) { 101 for (i = 0; i < NumUnits; i++) 102 glMultiTexCoord2fvARB(GL_TEXTURE0_ARB + i, & tex_coords[j]); 103 glVertex2fv( & vtx_coords[j] ); 104 } 105 } 106 107 glEnd(); 108} 109 110 111 112static void Display( void ) 113{ 114 static GLint T0 = 0; 115 static GLint Frames = 0; 116 GLint t; 117 118 glClear( GL_COLOR_BUFFER_BIT ); 119 120 glPushMatrix(); 121 glRotatef(Xrot, 1.0, 0.0, 0.0); 122 glRotatef(Yrot, 0.0, 1.0, 0.0); 123 glRotatef(Zrot, 0.0, 0.0, 1.0); 124 glScalef(5.0, 5.0, 5.0); 125 DrawObject(); 126 glPopMatrix(); 127 128 glutSwapBuffers(); 129 130 Frames++; 131 132 t = glutGet(GLUT_ELAPSED_TIME); 133 if (t - T0 >= 2500) { 134 GLfloat seconds = (t - T0) / 1000.0; 135 GLfloat fps = Frames / seconds; 136 drift_increment = 2.2 * seconds / Frames; 137 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); 138 T0 = t; 139 Frames = 0; 140 } 141} 142 143 144static void Reshape( int width, int height ) 145{ 146 glViewport( 0, 0, width, height ); 147 glMatrixMode( GL_PROJECTION ); 148 glLoadIdentity(); 149 glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); 150 /*glOrtho( -6.0, 6.0, -6.0, 6.0, 10.0, 100.0 );*/ 151 glMatrixMode( GL_MODELVIEW ); 152 glLoadIdentity(); 153 glTranslatef( 0.0, 0.0, -70.0 ); 154} 155 156 157static void ModeMenu(int entry) 158{ 159 if (entry >= TEX0 && entry <= TEX7) { 160 /* toggle */ 161 GLint i = entry - TEX0; 162 TexEnabled[i] = !TexEnabled[i]; 163 glActiveTextureARB(GL_TEXTURE0_ARB + i); 164 if (TexEnabled[i]) 165 glEnable(GL_TEXTURE_2D); 166 else 167 glDisable(GL_TEXTURE_2D); 168 printf("Enabled: "); 169 for (i = 0; i < NumUnits; i++) 170 printf("%d ", (int) TexEnabled[i]); 171 printf("\n"); 172 } 173 else if (entry==ANIMATE) { 174 Animate = !Animate; 175 } 176 else if (entry==SHADER) { 177 Shader = !Shader; 178 if (Shader) { 179 fprintf(stderr, "using 2-pass shader\n"); 180 glBindFragmentShaderATI(boring2passID); 181 } 182 else { 183 fprintf(stderr, "using 1-pass shader\n"); 184 glBindFragmentShaderATI(boringshaderID); 185 } 186 } 187 else if (entry==QUIT) { 188 exit(0); 189 } 190 191 glutPostRedisplay(); 192} 193 194 195static void Key( unsigned char key, int x, int y ) 196{ 197 (void) x; 198 (void) y; 199 switch (key) { 200 case 27: 201 exit(0); 202 break; 203 } 204 glutPostRedisplay(); 205} 206 207 208static void SpecialKey( int key, int x, int y ) 209{ 210 float step = 3.0; 211 (void) x; 212 (void) y; 213 214 switch (key) { 215 case GLUT_KEY_UP: 216 Xrot += step; 217 break; 218 case GLUT_KEY_DOWN: 219 Xrot -= step; 220 break; 221 case GLUT_KEY_LEFT: 222 Yrot += step; 223 break; 224 case GLUT_KEY_RIGHT: 225 Yrot -= step; 226 break; 227 } 228 glutPostRedisplay(); 229} 230 231 232static void Init( int argc, char *argv[] ) 233{ 234 GLuint texObj[8]; 235 GLint size, i; 236 237 const char *exten = (const char *) glGetString(GL_EXTENSIONS); 238 if (!strstr(exten, "GL_ATI_fragment_shader")) { 239 printf("Sorry, GL_ATI_fragment_shader not supported by this renderer.\n"); 240 exit(1); 241 } 242 243 244 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); 245 printf("%d x %d max texture size\n", size, size); 246 247 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 248 249 for (i = 0; i < NumUnits; i++) { 250 if (i < 6) 251 TexEnabled[i] = GL_TRUE; 252 else 253 TexEnabled[i] = GL_FALSE; 254 } 255 256 /* allocate two texture objects */ 257 glGenTextures(NumUnits, texObj); 258 259 /* setup the texture objects */ 260 for (i = 0; i < NumUnits; i++) { 261 262 glActiveTextureARB(GL_TEXTURE0_ARB + i); 263 glBindTexture(GL_TEXTURE_2D, texObj[i]); 264 265 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 267 268 if (i == 0) { 269 if (!LoadRGBMipmaps(TEXTURE_1_FILE, GL_RGB)) { 270 printf("Error: couldn't load texture image\n"); 271 exit(1); 272 } 273 } 274 else if (i == 1) { 275 if (!LoadRGBMipmaps(TEXTURE_2_FILE, GL_RGB)) { 276 printf("Error: couldn't load texture image\n"); 277 exit(1); 278 } 279 } 280 else { 281 /* checker */ 282 GLubyte image[8][8][3]; 283 GLint i, j; 284 for (i = 0; i < 8; i++) { 285 for (j = 0; j < 8; j++) { 286 if ((i + j) & 1) { 287 image[i][j][0] = 50; 288 image[i][j][1] = 50; 289 image[i][j][2] = 50; 290 } 291 else { 292 image[i][j][0] = 25; 293 image[i][j][1] = 25; 294 image[i][j][2] = 25; 295 } 296 } 297 } 298 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, 299 GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) image); 300 } 301 302 /* Bind texObj[i] to ith texture unit */ 303/* if (i < 2) 304 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 305 else 306 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);*/ 307 308 if (TexEnabled[i]) 309 glEnable(GL_TEXTURE_2D); 310 } 311 312 boringshaderID = glGenFragmentShadersATI(1); 313 boring2passID = glGenFragmentShadersATI(1); 314 if (boring2passID == 0) 315 { 316 fprintf(stderr, "couldn't get frag shader id\n"); 317 exit(1); 318 } 319 glBindFragmentShaderATI(boringshaderID); 320/* maybe not the most creative shader but at least I know how it should look like! */ 321 glBeginFragmentShaderATI(); 322 glSampleMapATI(GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI); 323 glSampleMapATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI); 324 glSampleMapATI(GL_REG_2_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI); 325 glSampleMapATI(GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI); 326 glSampleMapATI(GL_REG_4_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI); 327 glSampleMapATI(GL_REG_5_ATI, GL_TEXTURE5_ARB, GL_SWIZZLE_STR_ATI); 328 glColorFragmentOp2ATI(GL_MUL_ATI, 329 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 330 GL_REG_0_ATI, GL_NONE, GL_NONE, 331 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 332 glAlphaFragmentOp1ATI(GL_MOV_ATI, 333 GL_REG_0_ATI, GL_NONE, 334 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 335 glColorFragmentOp3ATI(GL_MAD_ATI, 336 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 337 GL_REG_0_ATI, GL_NONE, GL_NONE, 338 GL_REG_1_ATI, GL_NONE, GL_NONE, 339 GL_REG_2_ATI, GL_NONE, GL_NONE); 340 glColorFragmentOp2ATI(GL_ADD_ATI, 341 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 342 GL_REG_0_ATI, GL_NONE, GL_NONE, 343 GL_REG_3_ATI, GL_NONE, GL_NONE); 344 glColorFragmentOp2ATI(GL_ADD_ATI, 345 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 346 GL_REG_0_ATI, GL_NONE, GL_NONE, 347 GL_REG_4_ATI, GL_NONE, GL_NONE); 348 glColorFragmentOp2ATI(GL_ADD_ATI, 349 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 350 GL_REG_0_ATI, GL_NONE, GL_NONE, 351 GL_REG_5_ATI, GL_NONE, GL_NONE); 352 glEndFragmentShaderATI(); 353 354/* mathematically equivalent to first shader but using 2 passes together with 355 some tex coord rerouting */ 356 glBindFragmentShaderATI(boring2passID); 357 glBeginFragmentShaderATI(); 358 glPassTexCoordATI(GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI); 359 glSampleMapATI(GL_REG_2_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI); 360 glSampleMapATI(GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI); 361 glSampleMapATI(GL_REG_4_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI); 362 glSampleMapATI(GL_REG_5_ATI, GL_TEXTURE5_ARB, GL_SWIZZLE_STR_ATI); 363 glColorFragmentOp2ATI(GL_ADD_ATI, 364 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 365 GL_REG_2_ATI, GL_NONE, GL_NONE, 366 GL_REG_3_ATI, GL_NONE, GL_NONE); 367 glColorFragmentOp2ATI(GL_ADD_ATI, 368 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 369 GL_REG_0_ATI, GL_NONE, GL_NONE, 370 GL_REG_4_ATI, GL_NONE, GL_NONE); 371 glColorFragmentOp2ATI(GL_ADD_ATI, 372 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 373 GL_REG_0_ATI, GL_NONE, GL_NONE, 374 GL_REG_5_ATI, GL_NONE, GL_NONE); 375 /* not really a dependant read */ 376 glSampleMapATI(GL_REG_0_ATI, GL_REG_1_ATI, GL_SWIZZLE_STR_ATI); 377 glSampleMapATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI); 378 glPassTexCoordATI(GL_REG_5_ATI, GL_REG_0_ATI, GL_SWIZZLE_STR_ATI); 379 glColorFragmentOp2ATI(GL_MUL_ATI, 380 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 381 GL_REG_0_ATI, GL_NONE, GL_NONE, 382 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 383 glAlphaFragmentOp1ATI(GL_MOV_ATI, 384 GL_REG_0_ATI, GL_NONE, 385 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 386 glColorFragmentOp3ATI(GL_MAD_ATI, 387 GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI, 388 GL_REG_0_ATI, GL_NONE, GL_NONE, 389 GL_REG_1_ATI, GL_NONE, GL_NONE, 390 GL_REG_5_ATI, GL_NONE, GL_NONE); 391 /* in principle we're finished here, but to test a bit more 392 we do some fun with dot ops, replication et al. */ 393 glSetFragmentShaderConstantATI(GL_CON_3_ATI, shaderconstant); 394 glColorFragmentOp2ATI(GL_DOT4_ATI, 395 GL_REG_3_ATI, GL_GREEN_BIT_ATI, GL_EIGHTH_BIT_ATI, 396 GL_ZERO, GL_NONE, GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI, 397 GL_CON_3_ATI, GL_RED, GL_2X_BIT_ATI); 398 /* those args must get ignored, except dstReg */ 399 glAlphaFragmentOp2ATI(GL_DOT4_ATI, 400 GL_REG_4_ATI, GL_NONE, 401 GL_ZERO, GL_NONE, GL_NONE, 402 GL_ZERO, GL_NONE, GL_NONE); 403 /* -> reg3 g = reg4 alpha = -0.5 */ 404 glAlphaFragmentOp2ATI(GL_ADD_ATI, 405 GL_REG_5_ATI, GL_NONE, 406 GL_REG_3_ATI, GL_GREEN, GL_NONE, 407 GL_REG_4_ATI, GL_NONE, GL_NONE); 408 /* -> reg5 a = -1 */ 409 glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, 410 GL_REG_4_ATI, GL_BLUE_BIT_ATI, GL_HALF_BIT_ATI, 411 GL_REG_5_ATI, GL_ALPHA, GL_NEGATE_BIT_ATI, 412 GL_ONE, GL_NONE, GL_BIAS_BIT_ATI, 413 GL_ONE, GL_ALPHA, GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI); 414 /* -> reg 4 b = -0.5 */ 415 glColorFragmentOp2ATI(GL_MUL_ATI, 416 GL_REG_0_ATI, GL_NONE, GL_NONE, 417 GL_REG_4_ATI, GL_BLUE, GL_NEGATE_BIT_ATI | GL_2X_BIT_ATI, 418 GL_REG_0_ATI, GL_NONE, GL_NONE); 419 glEndFragmentShaderATI(); 420 421 glBindFragmentShaderATI(boringshaderID); 422 glEnable(GL_FRAGMENT_SHADER_ATI); 423 424 glShadeModel(GL_FLAT); 425 glClearColor(0.3, 0.3, 0.4, 1.0); 426 427 if (argc > 1 && strcmp(argv[1], "-info")==0) { 428 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 429 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 430 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 431 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 432 } 433 printf("output should be identical with both shaders to multiarb demo when 6 textures are enabled\n"); 434} 435 436 437int main( int argc, char *argv[] ) 438{ 439/* GLint i;*/ 440 441 glutInit( &argc, argv ); 442 glutInitWindowSize( 300, 300 ); 443 glutInitWindowPosition( 0, 0 ); 444 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 445 glutCreateWindow(argv[0] ); 446 glewInit(); 447 448 Init( argc, argv ); 449 450 glutReshapeFunc( Reshape ); 451 glutKeyboardFunc( Key ); 452 glutSpecialFunc( SpecialKey ); 453 glutDisplayFunc( Display ); 454 glutIdleFunc( Idle ); 455 456 glutCreateMenu(ModeMenu); 457 458/* for (i = 0; i < NumUnits; i++) { 459 char s[100]; 460 sprintf(s, "Toggle Texture %d", i); 461 glutAddMenuEntry(s, TEX0 + i); 462 }*/ 463 glutAddMenuEntry("Toggle 1/2 Pass Shader", SHADER); 464 glutAddMenuEntry("Toggle Animation", ANIMATE); 465 glutAddMenuEntry("Quit", QUIT); 466 glutAttachMenu(GLUT_RIGHT_BUTTON); 467 468 glutMainLoop(); 469 return 0; 470} 471