1/* 2 * Warp a triangle mesh with a vertex program. 3 */ 4 5#include <assert.h> 6#include <string.h> 7#include <stdio.h> 8#include <stdlib.h> 9#include <math.h> 10#include <GL/glew.h> 11#include "glut_wrap.h" 12 13static float Xrot = -60.0, Yrot = 0.0, Zrot = 0.0; 14static GLboolean Anim = GL_TRUE; 15static GLfloat Phi = 0.0; 16 17 18static void Idle( void ) 19{ 20 Phi += 0.01; 21 glutPostRedisplay(); 22} 23 24 25static void DrawMesh( int rows, int cols ) 26{ 27 static const GLfloat colorA[3] = { 0, 1, 0 }; 28 static const GLfloat colorB[3] = { 0, 0, 1 }; 29 const float dx = 2.0 / (cols - 1); 30 const float dy = 2.0 / (rows - 1); 31 float x, y; 32 int i, j; 33 34#if 1 35#define COLOR3FV(c) glVertexAttrib3fvARB(3, c) 36#define VERTEX2F(x, y) glVertexAttrib2fARB(0, x, y) 37#else 38#define COLOR3FV(c) glColor3fv(c) 39#define VERTEX2F(x, y) glVertex2f(x, y) 40#endif 41 42 y = -1.0; 43 for (i = 0; i < rows - 1; i++) { 44 glBegin(GL_QUAD_STRIP); 45 x = -1.0; 46 for (j = 0; j < cols; j++) { 47 if ((i + j) & 1) 48 COLOR3FV(colorA); 49 else 50 COLOR3FV(colorB); 51 VERTEX2F(x, y); 52 VERTEX2F(x, y + dy); 53 x += dx; 54 } 55 glEnd(); 56 y += dy; 57 } 58} 59 60 61static void Display( void ) 62{ 63 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 64 65 glPushMatrix(); 66 glRotatef(Xrot, 1, 0, 0); 67 glRotatef(Yrot, 0, 1, 0); 68 glRotatef(Zrot, 0, 0, 1); 69 70 /* Position the gravity source */ 71 { 72 GLfloat x, y, z, r = 0.5; 73 x = r * cos(Phi); 74 y = r * sin(Phi); 75 z = 1.0; 76 glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 30, x, y, z, 1); 77 glDisable(GL_VERTEX_PROGRAM_ARB); 78 glBegin(GL_POINTS); 79 glColor3f(1,1,1); 80 glVertex3f(x, y, z); 81 glEnd(); 82 } 83 84 glEnable(GL_VERTEX_PROGRAM_ARB); 85 DrawMesh(8, 8); 86 glPopMatrix(); 87 88 glutSwapBuffers(); 89} 90 91 92static void Reshape( int width, int height ) 93{ 94 float ar = (float) width / (float) height; 95 glViewport( 0, 0, width, height ); 96 glMatrixMode( GL_PROJECTION ); 97 glLoadIdentity(); 98 glFrustum( -1.0 * ar, 1.0 * ar, -1.0, 1.0, 5.0, 25.0 ); 99 glMatrixMode( GL_MODELVIEW ); 100 glLoadIdentity(); 101 glTranslatef( 0.0, 0.0, -12.0 ); 102 glScalef(2, 2, 2); 103} 104 105 106static void Key( unsigned char key, int x, int y ) 107{ 108 (void) x; 109 (void) y; 110 switch (key) { 111 case 'a': 112 Anim = !Anim; 113 if (Anim) 114 glutIdleFunc(Idle); 115 else 116 glutIdleFunc(NULL); 117 break; 118 case 'p': 119 Phi += 0.2; 120 break; 121 case 'z': 122 Zrot -= 5.0; 123 break; 124 case 'Z': 125 Zrot += 5.0; 126 break; 127 case 27: 128 exit(0); 129 break; 130 } 131 glutPostRedisplay(); 132} 133 134 135static void SpecialKey( int key, int x, int y ) 136{ 137 const GLfloat step = 3.0; 138 (void) x; 139 (void) y; 140 switch (key) { 141 case GLUT_KEY_UP: 142 Xrot -= step; 143 break; 144 case GLUT_KEY_DOWN: 145 Xrot += step; 146 break; 147 case GLUT_KEY_LEFT: 148 Yrot -= step; 149 break; 150 case GLUT_KEY_RIGHT: 151 Yrot += step; 152 break; 153 } 154 glutPostRedisplay(); 155} 156 157 158static void Init( void ) 159{ 160 GLuint prognum; 161 GLint errnum; 162 163 /* 164 * c[0..3] = modelview matrix 165 * c[4..7] = inverse modelview matrix 166 * c[30] = gravity source location 167 * c[31] = gravity source strength 168 * c[32] = light pos 169 * c[35] = diffuse color 170 */ 171 static const char prog[] = 172 "!!ARBvp1.0\n" 173 "TEMP R1, R2, R3; " 174 175 "# Compute distance from vertex to gravity source\n" 176 "ADD R1, program.local[30], -vertex.position; # vector from vertex to gravity\n" 177 "DP3 R2, R1, R1; # dot product\n" 178 "RSQ R2, R2.x; # square root = distance\n" 179 "MUL R2, R2, program.local[31].xxxx; # scale by the gravity factor\n" 180 181 "# Displace vertex by gravity factor along R1 vector\n" 182 "MAD R3, R1, R2, vertex.position;\n" 183 184 "# Continue with typical modelview/projection\n" 185 "DP4 result.position.x, state.matrix.mvp.row[0], R3 ; # object x MVP -> clip\n" 186 "DP4 result.position.y, state.matrix.mvp.row[1], R3 ;\n" 187 "DP4 result.position.z, state.matrix.mvp.row[2], R3 ;\n" 188 "DP4 result.position.w, state.matrix.mvp.row[3], R3 ;\n" 189 190 "MOV result.color, vertex.attrib[3];\n # copy input color to output color\n" 191 192 "END"; 193 194 if (!glutExtensionSupported("GL_ARB_vertex_program")) { 195 printf("Sorry, this program requires GL_ARB_vertex_program\n"); 196 exit(1); 197 } 198 199 glGenProgramsARB(1, &prognum); 200 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum); 201 glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 202 strlen(prog), (const GLubyte *)prog); 203 errnum = glGetError(); 204 printf("glGetError = %d\n", errnum); 205 206 if (errnum != GL_NO_ERROR) 207 { 208 GLint errorpos; 209 210 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos); 211 printf("errorpos: %d\n", errorpos); 212 printf("%s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB)); 213 } 214 215 /* Light position */ 216 glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 32, 2, 2, 4, 1); 217 /* Diffuse material color */ 218 glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 35, 0.25, 0, 0.25, 1); 219 220 /* Gravity strength */ 221 glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 31, .5, 0, 0, 0); 222 223 glEnable(GL_DEPTH_TEST); 224 glClearColor(0.3, 0.3, 0.3, 1); 225 glShadeModel(GL_FLAT); 226 glPointSize(3); 227} 228 229 230int main( int argc, char *argv[] ) 231{ 232 glutInit( &argc, argv ); 233 glutInitWindowPosition( 0, 0 ); 234 glutInitWindowSize( 250, 250 ); 235 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); 236 glutCreateWindow(argv[0]); 237 glewInit(); 238 glutReshapeFunc( Reshape ); 239 glutKeyboardFunc( Key ); 240 glutSpecialFunc( SpecialKey ); 241 glutDisplayFunc( Display ); 242 if (Anim) 243 glutIdleFunc(Idle); 244 Init(); 245 glutMainLoop(); 246 return 0; 247} 248