/* * Test vertex arrays with GL_ARB_vertex_program * * Based on a stripped-down version of the isosurf demo. * The vertex program is trivial: compute the resulting * RGB color as a linear function of vertex XYZ. */ #include #include #include #include #include #include "GL/glew.h" #include "glut_wrap.h" #define MAXVERTS 10000 static float data[MAXVERTS][6]; static GLint numverts; static GLfloat xrot; static GLfloat yrot; static GLboolean useArrays = GL_TRUE; static GLboolean useProgram = GL_TRUE; static GLboolean useList = GL_FALSE; static void read_surface( char *filename ) { FILE *f; f = fopen(filename,"r"); if (!f) { printf("couldn't read %s\n", filename); exit(1); } numverts = 0; while (numverts < MAXVERTS) { int result; result = fscanf( f, "%f %f %f %f %f %f", &data[numverts][0], &data[numverts][1], &data[numverts][2], &data[numverts][3], &data[numverts][4], &data[numverts][5] ); if (result == EOF) { break; } numverts++; } printf("%d vertices, %d triangles\n", numverts, numverts-2); printf("data = %p\n", (void *) data); fclose(f); } static void Display(void) { if (useProgram) glEnable(GL_VERTEX_PROGRAM_ARB); else glDisable(GL_VERTEX_PROGRAM_ARB); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); glRotatef(xrot, 1, 0, 0); glRotatef(yrot, 0, 1, 0); glScalef(2, 2, 2); if (useArrays) { if (useProgram) { glVertexAttribPointerARB( 0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), data ); glEnableVertexAttribArrayARB( 0 ); glVertexAttribPointerARB( 2, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); glEnableVertexAttribArrayARB( 2 ); } else { glVertexPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), data ); glEnableClientState( GL_VERTEX_ARRAY ); glNormalPointer( GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); glEnableClientState( GL_NORMAL_ARRAY ); } if (useList) { /* dumb, but a good test */ glNewList(1, GL_COMPILE); glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); glEndList(); glCallList(1); } else { glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); } glDisableVertexAttribArrayARB( 0 ); glDisableVertexAttribArrayARB( 2 ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); } else { int i; glBegin(GL_TRIANGLE_STRIP); for (i = 0; i < numverts; i++) { glNormal3fv( data[i] + 3 ); glVertex3fv( data[i] + 0 ); } glEnd(); } glPopMatrix(); if (glGetError()) printf("Error!\n"); glutSwapBuffers(); } static void InitMaterials(void) { static float ambient[] = {0.1, 0.1, 0.1, 1.0}; static float diffuse[] = {0.5, 1.0, 1.0, 1.0}; static float position0[] = {0.0, 0.0, 20.0, 0.0}; static float position1[] = {0.0, 0.0, -20.0, 0.0}; static float front_mat_shininess[] = {60.0}; static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0}; static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0}; /* static float back_mat_shininess[] = {60.0}; static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0}; static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0}; */ static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0}; static float lmodel_twoside[] = {GL_FALSE}; glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position0); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT1, GL_POSITION, position1); glEnable(GL_LIGHT1); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse); glEnable(GL_LIGHTING); } static void init_program(void) { /* * c[30] = color scale * c[31] = color bias */ static const char prog[] = "!!ARBvp1.0\n" "TEMP R0, R1, R2, R3;\n" "# RGB is proportional to XYZ \n" "MUL R0, vertex.position, program.local[30]; \n" "ADD result.color.primary, R0, program.local[31]; \n" "# Continue with typical modelview/projection\n" "MOV R3, vertex.position; \n" "DP4 result.position.x, state.matrix.mvp.row[0], R3 ; # object x MVP -> clip\n" "DP4 result.position.y, state.matrix.mvp.row[1], R3 ;\n" "DP4 result.position.z, state.matrix.mvp.row[2], R3 ;\n" "DP4 result.position.w, state.matrix.mvp.row[3], R3 ;\n" "END"; static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0}; static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0}; if (!GLEW_ARB_vertex_program) { printf("Sorry, this program requires GL_ARB_vertex_program\n"); exit(1); } glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 1); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(prog), (const GLubyte *) prog); assert(glIsProgramARB(1)); if (glGetError() != GL_NO_ERROR) { GLint errorpos = 0; glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos); printf("errorpos: %d\n", errorpos); printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)); exit(1); } /* Load the program registers */ glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 30, scale); glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 31, bias); } static void init(void) { xrot = 0; yrot = 0; glClearColor(0.0, 0.0, 1.0, 0.0); glEnable( GL_DEPTH_TEST ); glEnable(GL_NORMALIZE); InitMaterials(); read_surface(DEMOS_DATA_DIR "isosurf.dat"); init_program(); } static void Reshape(int width, int height) { glViewport(0, 0, (GLint)width, (GLint)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -15); } static void Key( unsigned char key, int x, int y ) { (void) x; (void) y; switch (key) { case 27: exit(0); case 'a': useArrays = !useArrays; printf("use arrays: %s\n", useArrays ? "yes" : "no"); break; case 'l': useList = !useList; printf("use list: %s\n", useList ? "yes" : "no"); break; case 'p': useProgram = !useProgram; printf("use program: %s\n", useProgram ? "yes" : "no"); break; } glutPostRedisplay(); } static void SpecialKey( int key, int x, int y ) { (void) x; (void) y; switch (key) { case GLUT_KEY_LEFT: yrot -= 15.0; break; case GLUT_KEY_RIGHT: yrot += 15.0; break; case GLUT_KEY_UP: xrot += 15.0; break; case GLUT_KEY_DOWN: xrot -= 15.0; break; default: return; } glutPostRedisplay(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE ); glutInitWindowPosition(0, 0); glutInitWindowSize(400, 400); if (glutCreateWindow("Isosurface") <= 0) { exit(0); } glewInit(); glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutSpecialFunc(SpecialKey); glutDisplayFunc(Display); init(); glutMainLoop(); return 0; }