1/* 2 * Test vertex arrays with GL_ARB_vertex_program 3 * 4 * Based on a stripped-down version of the isosurf demo. 5 * The vertex program is trivial: compute the resulting 6 * RGB color as a linear function of vertex XYZ. 7 */ 8 9#include <assert.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <math.h> 14#include "GL/glew.h" 15#include "glut_wrap.h" 16 17#define MAXVERTS 10000 18static float data[MAXVERTS][6]; 19static GLint numverts; 20 21static GLfloat xrot; 22static GLfloat yrot; 23static GLboolean useArrays = GL_TRUE; 24static GLboolean useProgram = GL_TRUE; 25static GLboolean useList = GL_FALSE; 26 27 28static void read_surface( char *filename ) 29{ 30 FILE *f; 31 32 f = fopen(filename,"r"); 33 if (!f) { 34 printf("couldn't read %s\n", filename); 35 exit(1); 36 } 37 38 numverts = 0; 39 while (numverts < MAXVERTS) { 40 int result; 41 result = fscanf( f, "%f %f %f %f %f %f", 42 &data[numverts][0], &data[numverts][1], &data[numverts][2], 43 &data[numverts][3], &data[numverts][4], &data[numverts][5] ); 44 if (result == EOF) { 45 break; 46 } 47 numverts++; 48 } 49 50 printf("%d vertices, %d triangles\n", numverts, numverts-2); 51 printf("data = %p\n", (void *) data); 52 fclose(f); 53} 54 55 56 57 58static void Display(void) 59{ 60 if (useProgram) 61 glEnable(GL_VERTEX_PROGRAM_ARB); 62 else 63 glDisable(GL_VERTEX_PROGRAM_ARB); 64 65 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 66 67 glPushMatrix(); 68 glRotatef(xrot, 1, 0, 0); 69 glRotatef(yrot, 0, 1, 0); 70 glScalef(2, 2, 2); 71 if (useArrays) { 72 if (useProgram) { 73 glVertexAttribPointerARB( 0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), data ); 74 glEnableVertexAttribArrayARB( 0 ); 75 glVertexAttribPointerARB( 2, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); 76 glEnableVertexAttribArrayARB( 2 ); 77 } 78 else { 79 glVertexPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), data ); 80 glEnableClientState( GL_VERTEX_ARRAY ); 81 glNormalPointer( GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); 82 glEnableClientState( GL_NORMAL_ARRAY ); 83 } 84 85 if (useList) { 86 /* dumb, but a good test */ 87 glNewList(1, GL_COMPILE); 88 glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); 89 glEndList(); 90 glCallList(1); 91 } 92 else { 93 glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); 94 } 95 96 glDisableVertexAttribArrayARB( 0 ); 97 glDisableVertexAttribArrayARB( 2 ); 98 glDisableClientState( GL_VERTEX_ARRAY ); 99 glDisableClientState( GL_NORMAL_ARRAY ); 100 } 101 else { 102 int i; 103 glBegin(GL_TRIANGLE_STRIP); 104 for (i = 0; i < numverts; i++) { 105 glNormal3fv( data[i] + 3 ); 106 glVertex3fv( data[i] + 0 ); 107 } 108 glEnd(); 109 } 110 glPopMatrix(); 111 112 if (glGetError()) 113 printf("Error!\n"); 114 115 glutSwapBuffers(); 116} 117 118 119static void InitMaterials(void) 120{ 121 static float ambient[] = {0.1, 0.1, 0.1, 1.0}; 122 static float diffuse[] = {0.5, 1.0, 1.0, 1.0}; 123 static float position0[] = {0.0, 0.0, 20.0, 0.0}; 124 static float position1[] = {0.0, 0.0, -20.0, 0.0}; 125 static float front_mat_shininess[] = {60.0}; 126 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0}; 127 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0}; 128 /* 129 static float back_mat_shininess[] = {60.0}; 130 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0}; 131 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0}; 132 */ 133 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0}; 134 static float lmodel_twoside[] = {GL_FALSE}; 135 136 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); 137 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 138 glLightfv(GL_LIGHT0, GL_POSITION, position0); 139 glEnable(GL_LIGHT0); 140 141 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); 142 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); 143 glLightfv(GL_LIGHT1, GL_POSITION, position1); 144 glEnable(GL_LIGHT1); 145 146 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); 147 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); 148 149 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess); 150 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular); 151 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse); 152 glEnable(GL_LIGHTING); 153} 154 155 156static void init_program(void) 157{ 158 /* 159 * c[30] = color scale 160 * c[31] = color bias 161 */ 162 static const char prog[] = 163 "!!ARBvp1.0\n" 164 165 "TEMP R0, R1, R2, R3;\n" 166 167 "# RGB is proportional to XYZ \n" 168 "MUL R0, vertex.position, program.local[30]; \n" 169 "ADD result.color.primary, R0, program.local[31]; \n" 170 171 "# Continue with typical modelview/projection\n" 172 "MOV R3, vertex.position; \n" 173 "DP4 result.position.x, state.matrix.mvp.row[0], R3 ; # object x MVP -> clip\n" 174 "DP4 result.position.y, state.matrix.mvp.row[1], R3 ;\n" 175 "DP4 result.position.z, state.matrix.mvp.row[2], R3 ;\n" 176 "DP4 result.position.w, state.matrix.mvp.row[3], R3 ;\n" 177 178 "END"; 179 180 static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0}; 181 static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0}; 182 183 if (!GLEW_ARB_vertex_program) { 184 printf("Sorry, this program requires GL_ARB_vertex_program\n"); 185 exit(1); 186 } 187 188 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 1); 189 glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 190 strlen(prog), (const GLubyte *) prog); 191 assert(glIsProgramARB(1)); 192 193 if (glGetError() != GL_NO_ERROR) 194 { 195 GLint errorpos = 0; 196 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos); 197 printf("errorpos: %d\n", errorpos); 198 printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)); 199 exit(1); 200 } 201 202 /* Load the program registers */ 203 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 30, scale); 204 glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 31, bias); 205} 206 207 208static void init(void) 209{ 210 xrot = 0; 211 yrot = 0; 212 glClearColor(0.0, 0.0, 1.0, 0.0); 213 glEnable( GL_DEPTH_TEST ); 214 glEnable(GL_NORMALIZE); 215 InitMaterials(); 216 read_surface(DEMOS_DATA_DIR "isosurf.dat"); 217 init_program(); 218} 219 220 221static void Reshape(int width, int height) 222{ 223 glViewport(0, 0, (GLint)width, (GLint)height); 224 glMatrixMode(GL_PROJECTION); 225 glLoadIdentity(); 226 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 ); 227 glMatrixMode(GL_MODELVIEW); 228 glLoadIdentity(); 229 glTranslatef(0, 0, -15); 230} 231 232 233 234static void Key( unsigned char key, int x, int y ) 235{ 236 (void) x; 237 (void) y; 238 switch (key) { 239 case 27: 240 exit(0); 241 case 'a': 242 useArrays = !useArrays; 243 printf("use arrays: %s\n", useArrays ? "yes" : "no"); 244 break; 245 case 'l': 246 useList = !useList; 247 printf("use list: %s\n", useList ? "yes" : "no"); 248 break; 249 case 'p': 250 useProgram = !useProgram; 251 printf("use program: %s\n", useProgram ? "yes" : "no"); 252 break; 253 } 254 glutPostRedisplay(); 255} 256 257 258static void SpecialKey( int key, int x, int y ) 259{ 260 (void) x; 261 (void) y; 262 switch (key) { 263 case GLUT_KEY_LEFT: 264 yrot -= 15.0; 265 break; 266 case GLUT_KEY_RIGHT: 267 yrot += 15.0; 268 break; 269 case GLUT_KEY_UP: 270 xrot += 15.0; 271 break; 272 case GLUT_KEY_DOWN: 273 xrot -= 15.0; 274 break; 275 default: 276 return; 277 } 278 glutPostRedisplay(); 279} 280 281 282 283int main(int argc, char **argv) 284{ 285 glutInit(&argc, argv); 286 glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE ); 287 glutInitWindowPosition(0, 0); 288 glutInitWindowSize(400, 400); 289 if (glutCreateWindow("Isosurface") <= 0) { 290 exit(0); 291 } 292 glewInit(); 293 glutReshapeFunc(Reshape); 294 glutKeyboardFunc(Key); 295 glutSpecialFunc(SpecialKey); 296 glutDisplayFunc(Display); 297 298 init(); 299 300 glutMainLoop(); 301 return 0; 302} 303