| /* |
| * Test the GL_MESA_program_debug extension |
| */ |
| |
| |
| #include <assert.h> |
| #include <ctype.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <math.h> |
| #define GL_GLEXT_PROTOTYPES |
| #include <GL/glut.h> |
| |
| |
| /* |
| * Print the string with line numbers |
| */ |
| static void list_program(const GLubyte *string, GLsizei len) |
| { |
| const char *c = (const char *) string; |
| int i, line = 1, printNumber = 1; |
| |
| for (i = 0; i < len; i++) { |
| if (printNumber) { |
| printf("%3d ", line); |
| printNumber = 0; |
| } |
| if (*c == '\n') { |
| line++; |
| printNumber = 1; |
| } |
| putchar(*c); |
| c++; |
| } |
| putchar('\n'); |
| } |
| |
| |
| /* |
| * Return the line number and column number that corresponds to the |
| * given program position. Also return a null-terminated copy of that |
| * line of the program string. |
| */ |
| static const GLubyte * |
| find_line_column(const GLubyte *string, const GLubyte *pos, |
| GLint *line, GLint *col) |
| { |
| const GLubyte *lineStart = string; |
| const GLubyte *p = string; |
| GLubyte *s; |
| int len; |
| |
| *line = 1; |
| |
| while (p != pos) { |
| if (*p == (GLubyte) '\n') { |
| (*line)++; |
| lineStart = p + 1; |
| } |
| p++; |
| } |
| |
| *col = (pos - lineStart) + 1; |
| |
| /* return copy of this line */ |
| while (*p != 0 && *p != '\n') |
| p++; |
| len = p - lineStart; |
| s = (GLubyte *) malloc(len + 1); |
| memcpy(s, lineStart, len); |
| s[len] = 0; |
| |
| return s; |
| } |
| |
| |
| #define ARB_VERTEX_PROGRAM 1 |
| #define ARB_FRAGMENT_PROGRAM 2 |
| #define NV_VERTEX_PROGRAM 3 |
| #define NV_FRAGMENT_PROGRAM 4 |
| |
| |
| struct breakpoint { |
| enum {PIXEL, LINE} type; |
| int x, y; |
| int line; |
| GLboolean enabled; |
| }; |
| |
| #define MAX_BREAKPOINTS 100 |
| static struct breakpoint Breakpoints[MAX_BREAKPOINTS]; |
| static int NumBreakpoints = 0; |
| |
| |
| |
| /* |
| * Interactive debugger |
| */ |
| static void Debugger2(GLenum target, GLvoid *data) |
| { |
| static GLuint skipCount = 0; |
| const GLubyte *ln; |
| GLint pos, line, column; |
| GLint id; |
| int progType; |
| GLint len; |
| GLubyte *program; |
| GLboolean stop; |
| int i; |
| |
| /* Sigh, GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV so it's a bit |
| * hard to distinguish between them. |
| */ |
| if (target == GL_FRAGMENT_PROGRAM_ARB) |
| progType = ARB_FRAGMENT_PROGRAM; |
| else if (target == GL_FRAGMENT_PROGRAM_NV) |
| progType = NV_FRAGMENT_PROGRAM; |
| else |
| progType = NV_VERTEX_PROGRAM; |
| |
| /* Until we hit zero, continue rendering */ |
| if (skipCount > 0) { |
| skipCount--; |
| return; |
| } |
| |
| /* Get id of the program and current position */ |
| switch (progType) { |
| case ARB_FRAGMENT_PROGRAM: |
| glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id); |
| glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos); |
| break; |
| case NV_FRAGMENT_PROGRAM: |
| glGetIntegerv(GL_FRAGMENT_PROGRAM_BINDING_NV, &id); |
| glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos); |
| break; |
| case ARB_VERTEX_PROGRAM: |
| glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id); |
| glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos); |
| break; |
| case NV_VERTEX_PROGRAM: |
| glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &id); |
| glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos); |
| break; |
| default: |
| abort(); |
| } |
| |
| /* get program string */ |
| if (progType == ARB_VERTEX_PROGRAM || |
| progType == ARB_FRAGMENT_PROGRAM) |
| glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &len); |
| else |
| glGetProgramivNV(id, GL_PROGRAM_LENGTH_NV, &len); |
| program = malloc(len + 1); |
| if (progType == ARB_VERTEX_PROGRAM || |
| progType == ARB_FRAGMENT_PROGRAM) |
| glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, program); |
| else |
| glGetProgramStringNV(id, GL_PROGRAM_STRING_NV, program); |
| |
| |
| /* Get current line number, column, line string */ |
| ln = find_line_column(program, program + pos, &line, &column); |
| |
| /* test breakpoints */ |
| if (NumBreakpoints > 0) |
| stop = GL_FALSE; |
| else |
| stop = GL_TRUE; |
| for (i = 0; i < NumBreakpoints; i++) { |
| if (Breakpoints[i].enabled) { |
| switch (Breakpoints[i].type) { |
| case PIXEL: |
| if (progType == ARB_FRAGMENT_PROGRAM) { |
| |
| } |
| else if (progType == NV_FRAGMENT_PROGRAM) { |
| GLfloat pos[4]; |
| int px, py; |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| 6, (GLubyte *) "f[WPOS]", pos); |
| px = (int) pos[0]; |
| py = (int) pos[1]; |
| printf("%d, %d\n", px, py); |
| if (px == Breakpoints[i].x && |
| py == Breakpoints[i].y) { |
| printf("Break at pixel (%d, %d)\n", px, py); |
| stop = GL_TRUE; |
| } |
| } |
| break; |
| case LINE: |
| if (line == Breakpoints[i].line) { |
| /* hit a breakpoint! */ |
| printf("Break at line %d\n", line); |
| stop = GL_TRUE; |
| } |
| break; |
| } |
| } |
| } |
| if (!stop) { |
| free(program); |
| return; |
| } |
| |
| printf("%d: %s\n", line, ln); |
| |
| /* get commands from stdin */ |
| while (1) { |
| char command[1000], *cmd; |
| |
| /* print prompt and get command */ |
| printf("(%s %d) ", (target == GL_VERTEX_PROGRAM_ARB ? "vert" : "frag"), |
| line); |
| fgets(command, 999, stdin); |
| |
| /* skip leading whitespace */ |
| for (cmd = command; cmd[0] == ' '; cmd++) |
| ; |
| |
| if (!cmd[0]) |
| /* nothing (repeat the previous cmd?) */ |
| continue; |
| |
| switch (cmd[0]) { |
| case 's': |
| /* skip N instructions */ |
| i = atoi(cmd + 2); |
| skipCount = i; |
| printf("Skipping %d instructions\n", i); |
| return; |
| case 'n': |
| /* next */ |
| return; |
| case 'c': |
| return; |
| case 'd': |
| /* dump machine state */ |
| if (progType == NV_FRAGMENT_PROGRAM) { |
| static const char *inRegs[] = { |
| "f[WPOS]", "f[COL0]", "f[COL1]", "f[FOGC]", |
| "f[TEX0]", "f[TEX1]", "f[TEX2]", "f[TEX3]", |
| NULL |
| }; |
| static const char *outRegs[] = { |
| "o[COLR]", "o[COLH]", "o[DEPR]", NULL |
| }; |
| GLfloat v[4]; |
| int i; |
| printf("Fragment input attributes:\n"); |
| for (i = 0; inRegs[i]; i++) { |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| strlen(inRegs[i]), |
| (const GLubyte *) inRegs[i], v); |
| printf(" %s: %g, %g, %g, %g\n", inRegs[i], |
| v[0], v[1], v[2], v[3]); |
| } |
| printf("Fragment output attributes:\n"); |
| for (i = 0; outRegs[i]; i++) { |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| strlen(outRegs[i]), |
| (const GLubyte *) outRegs[i], v); |
| printf(" %s: %g, %g, %g, %g\n", outRegs[i], |
| v[0], v[1], v[2], v[3]); |
| } |
| printf("Temporaries:\n"); |
| for (i = 0; i < 4; i++) { |
| char temp[100]; |
| GLfloat v[4]; |
| sprintf(temp, "R%d", i); |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| strlen(temp), |
| (const GLubyte *) temp, v); |
| printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]); |
| } |
| } |
| else if (progType == NV_VERTEX_PROGRAM) { |
| GLfloat v[4]; |
| int i; |
| static const char *inRegs[] = { |
| "v[OPOS]", "v[WGHT]", "v[NRML]", "v[COL0]", |
| "v[COL1]", "v[FOGC]", "v[6]", "v[7]", |
| "v[TEX0]", "v[TEX1]", "v[TEX2]", "v[TEX3]", |
| "v[TEX4]", "v[TEX5]", "v[TEX6]", "v[TEX7]", |
| NULL |
| }; |
| static const char *outRegs[] = { |
| "o[HPOS]", "o[COL0]", "o[COL1]", "o[BFC0]", |
| "o[BFC1]", "o[FOGC]", "o[PSIZ]", |
| "o[TEX0]", "o[TEX1]", "o[TEX2]", "o[TEX3]", |
| "o[TEX4]", "o[TEX5]", "o[TEX6]", "o[TEX7]", |
| NULL |
| }; |
| printf("Vertex input attributes:\n"); |
| for (i = 0; inRegs[i]; i++) { |
| glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV, |
| strlen(inRegs[i]), |
| (const GLubyte *) inRegs[i], v); |
| printf(" %s: %g, %g, %g, %g\n", inRegs[i], |
| v[0], v[1], v[2], v[3]); |
| } |
| printf("Vertex output attributes:\n"); |
| for (i = 0; outRegs[i]; i++) { |
| glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV, |
| strlen(outRegs[i]), |
| (const GLubyte *) outRegs[i], v); |
| printf(" %s: %g, %g, %g, %g\n", outRegs[i], |
| v[0], v[1], v[2], v[3]); |
| } |
| printf("Temporaries:\n"); |
| for (i = 0; i < 4; i++) { |
| char temp[100]; |
| GLfloat v[4]; |
| sprintf(temp, "R%d", i); |
| glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV, |
| strlen(temp), |
| (const GLubyte *) temp, v); |
| printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]); |
| } |
| } |
| break; |
| case 'l': |
| /* list */ |
| list_program(program, len); |
| break; |
| case 'p': |
| /* print */ |
| { |
| GLfloat v[4]; |
| char *c; |
| cmd++; |
| while (*cmd == ' ') |
| cmd++; |
| c = cmd; |
| while (*c) { |
| if (*c == '\n' || *c == '\r') |
| *c = 0; |
| else |
| c++; |
| } |
| glGetProgramRegisterfvMESA(target, strlen(cmd), |
| (const GLubyte *) cmd, v); |
| if (glGetError() == GL_NO_ERROR) |
| printf("%s = %g, %g, %g, %g\n", cmd, v[0], v[1], v[2], v[3]); |
| else |
| printf("Invalid expression\n"); |
| } |
| break; |
| case 'b': |
| if (cmd[1] == ' ' && isdigit(cmd[2])) { |
| char *comma = strchr(cmd, ','); |
| if (comma) { |
| /* break at pixel */ |
| int x = atoi(cmd + 2); |
| int y = atoi(comma + 1); |
| if (NumBreakpoints < MAX_BREAKPOINTS) { |
| Breakpoints[NumBreakpoints].type = PIXEL; |
| Breakpoints[NumBreakpoints].x = x; |
| Breakpoints[NumBreakpoints].y = y; |
| Breakpoints[NumBreakpoints].enabled = GL_TRUE; |
| NumBreakpoints++; |
| printf("Breakpoint %d: break at pixel (%d, %d)\n", |
| NumBreakpoints, x, y); |
| } |
| } |
| else { |
| /* break at line */ |
| int l = atoi(cmd + 2); |
| if (l && NumBreakpoints < MAX_BREAKPOINTS) { |
| Breakpoints[NumBreakpoints].type = LINE; |
| Breakpoints[NumBreakpoints].line = l; |
| Breakpoints[NumBreakpoints].enabled = GL_TRUE; |
| NumBreakpoints++; |
| printf("Breakpoint %d: break at line %d\n", |
| NumBreakpoints, l); |
| } |
| } |
| } |
| else { |
| /* list breakpoints */ |
| printf("Breakpoints:\n"); |
| for (i = 0; i < NumBreakpoints; i++) { |
| switch (Breakpoints[i].type) { |
| case LINE: |
| printf(" %d: break at line %d\n", |
| i + 1, Breakpoints[i].line); |
| break; |
| case PIXEL: |
| printf(" %d: break at pixel (%d, %d)\n", |
| i + 1, Breakpoints[i].x, Breakpoints[i].y); |
| break; |
| } |
| } |
| } |
| break; |
| case 'h': |
| /* help */ |
| printf("Debugger commands:\n"); |
| printf(" b list breakpoints\n"); |
| printf(" b N break at line N\n"); |
| printf(" b x,y break at pixel x,y\n"); |
| printf(" c continue execution\n"); |
| printf(" d display register values\n"); |
| printf(" h help\n"); |
| printf(" l list program\n"); |
| printf(" n next instruction\n"); |
| printf(" p V print value V\n"); |
| printf(" s N skip N instructions\n"); |
| break; |
| default: |
| printf("Unknown command: %c\n", cmd[0]); |
| } |
| } |
| } |
| |
| |
| /* |
| * Print current line, some registers, and continue. |
| */ |
| static void Debugger(GLenum target, GLvoid *data) |
| { |
| GLint pos; |
| const GLubyte *ln; |
| GLint line, column; |
| GLfloat v[4]; |
| |
| assert(target == GL_FRAGMENT_PROGRAM_NV); |
| |
| glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos); |
| |
| ln = find_line_column((const GLubyte *) data, (const GLubyte *) data + pos, |
| &line, &column); |
| printf("%d:%d: %s\n", line, column, (char *) ln); |
| |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| 2, (const GLubyte *) "R0", v); |
| printf(" R0 = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]); |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| 7, (const GLubyte *) "f[WPOS]", v); |
| printf(" o[WPOS] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]); |
| glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV, |
| 7, (const GLubyte *) "o[COLR]", v); |
| printf(" o[COLR] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]); |
| |
| free((void *) ln); |
| } |
| |
| |
| |
| |
| /**********************************************************************/ |
| |
| static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 }; |
| static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 }; |
| static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 }; |
| static GLfloat Delta = 1.0; |
| |
| static GLuint FragProg; |
| static GLuint VertProg; |
| static GLboolean Anim = GL_TRUE; |
| static GLboolean Wire = GL_FALSE; |
| static GLboolean PixelLight = GL_TRUE; |
| |
| static GLfloat Xrot = 0, Yrot = 0; |
| |
| |
| #define NAMED_PARAMETER4FV(prog, name, v) \ |
| glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v) |
| |
| |
| static void Display( void ) |
| { |
| glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); |
| |
| if (PixelLight) { |
| NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos); |
| glEnable(GL_FRAGMENT_PROGRAM_NV); |
| glEnable(GL_VERTEX_PROGRAM_NV); |
| glDisable(GL_LIGHTING); |
| } |
| else { |
| glLightfv(GL_LIGHT0, GL_POSITION, LightPos); |
| glDisable(GL_FRAGMENT_PROGRAM_NV); |
| glDisable(GL_VERTEX_PROGRAM_NV); |
| glEnable(GL_LIGHTING); |
| } |
| |
| glPushMatrix(); |
| glRotatef(Xrot, 1, 0, 0); |
| glRotatef(Yrot, 0, 1, 0); |
| |
| #if 1 |
| glutSolidSphere(2.0, 10, 5); |
| #else |
| { |
| GLUquadricObj *q = gluNewQuadric(); |
| gluQuadricNormals(q, GL_SMOOTH); |
| gluQuadricTexture(q, GL_TRUE); |
| glRotatef(90, 1, 0, 0); |
| glTranslatef(0, 0, -1); |
| gluCylinder(q, 1.0, 1.0, 2.0, 24, 1); |
| gluDeleteQuadric(q); |
| } |
| #endif |
| |
| glPopMatrix(); |
| |
| glutSwapBuffers(); |
| } |
| |
| |
| static void Idle(void) |
| { |
| LightPos[0] += Delta; |
| if (LightPos[0] > 25.0) |
| Delta = -1.0; |
| else if (LightPos[0] <- 25.0) |
| Delta = 1.0; |
| glutPostRedisplay(); |
| } |
| |
| |
| static void Reshape( int width, int height ) |
| { |
| glViewport( 0, 0, width, height ); |
| glMatrixMode( GL_PROJECTION ); |
| glLoadIdentity(); |
| glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); |
| /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/ |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| glTranslatef( 0.0, 0.0, -15.0 ); |
| } |
| |
| |
| static void Key( unsigned char key, int x, int y ) |
| { |
| (void) x; |
| (void) y; |
| switch (key) { |
| case ' ': |
| Anim = !Anim; |
| if (Anim) |
| glutIdleFunc(Idle); |
| else |
| glutIdleFunc(NULL); |
| break; |
| case 'x': |
| LightPos[0] -= 1.0; |
| break; |
| case 'X': |
| LightPos[0] += 1.0; |
| break; |
| case 'w': |
| Wire = !Wire; |
| if (Wire) |
| glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
| else |
| glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
| break; |
| case 'p': |
| PixelLight = !PixelLight; |
| if (PixelLight) { |
| printf("Per-pixel lighting\n"); |
| } |
| else { |
| printf("Conventional lighting\n"); |
| } |
| break; |
| case 27: |
| exit(0); |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| static void SpecialKey( int key, int x, int y ) |
| { |
| const GLfloat step = 3.0; |
| (void) x; |
| (void) y; |
| switch (key) { |
| case GLUT_KEY_UP: |
| Xrot -= step; |
| break; |
| case GLUT_KEY_DOWN: |
| Xrot += step; |
| break; |
| case GLUT_KEY_LEFT: |
| Yrot -= step; |
| break; |
| case GLUT_KEY_RIGHT: |
| Yrot += step; |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| |
| static void Init( int argc, char *argv[] ) |
| { |
| static const char *fragProgramText = |
| "!!FP1.0\n" |
| "DECLARE Diffuse; \n" |
| "DECLARE Specular; \n" |
| "DECLARE LightPos; \n" |
| |
| "# Compute normalized LightPos, put it in R0\n" |
| "DP3 R0.x, LightPos, LightPos;\n" |
| "RSQ R0.y, R0.x;\n" |
| "MUL R0, LightPos, R0.y;\n" |
| |
| "# Compute normalized normal, put it in R1\n" |
| "DP3 R1, f[TEX0], f[TEX0]; \n" |
| "RSQ R1.y, R1.x;\n" |
| "MUL R1, f[TEX0], R1.y;\n" |
| |
| "# Compute dot product of light direction and normal vector\n" |
| "DP3 R2, R0, R1;\n" |
| |
| "MUL R3, Diffuse, R2; # diffuse attenuation\n" |
| |
| "POW R4, R2.x, {20.0}.x; # specular exponent\n" |
| |
| "MUL R5, Specular, R4; # specular attenuation\n" |
| |
| "ADD o[COLR], R3, R5; # add diffuse and specular colors\n" |
| "END \n" |
| ; |
| |
| static const char *vertProgramText = |
| "!!VP1.0\n" |
| "# typical modelview/projection transform\n" |
| "DP4 o[HPOS].x, c[0], v[OPOS] ;\n" |
| "DP4 o[HPOS].y, c[1], v[OPOS] ;\n" |
| "DP4 o[HPOS].z, c[2], v[OPOS] ;\n" |
| "DP4 o[HPOS].w, c[3], v[OPOS] ;\n" |
| "# transform normal by inv transpose of modelview, put in tex0\n" |
| "DP4 o[TEX0].x, c[4], v[NRML] ;\n" |
| "DP4 o[TEX0].y, c[5], v[NRML] ;\n" |
| "DP4 o[TEX0].z, c[6], v[NRML] ;\n" |
| "DP4 o[TEX0].w, c[7], v[NRML] ;\n" |
| "END\n"; |
| ; |
| |
| if (!glutExtensionSupported("GL_NV_vertex_program")) { |
| printf("Sorry, this demo requires GL_NV_vertex_program\n"); |
| exit(1); |
| } |
| if (!glutExtensionSupported("GL_NV_fragment_program")) { |
| printf("Sorry, this demo requires GL_NV_fragment_program\n"); |
| exit(1); |
| } |
| |
| glGenProgramsNV(1, &FragProg); |
| assert(FragProg > 0); |
| glGenProgramsNV(1, &VertProg); |
| assert(VertProg > 0); |
| |
| /* |
| * Fragment program |
| */ |
| glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg, |
| strlen(fragProgramText), |
| (const GLubyte *) fragProgramText); |
| assert(glIsProgramNV(FragProg)); |
| glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg); |
| |
| NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse); |
| NAMED_PARAMETER4FV(FragProg, "Specular", Specular); |
| |
| /* |
| * Vertex program |
| */ |
| glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg, |
| strlen(vertProgramText), |
| (const GLubyte *) vertProgramText); |
| assert(glIsProgramNV(VertProg)); |
| glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg); |
| glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV); |
| glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV); |
| |
| /* |
| * Misc init |
| */ |
| glClearColor(0.3, 0.3, 0.3, 0.0); |
| glEnable(GL_DEPTH_TEST); |
| glEnable(GL_LIGHT0); |
| glEnable(GL_LIGHTING); |
| glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse); |
| glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular); |
| glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0); |
| |
| printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); |
| printf("Press p to toggle between per-pixel and per-vertex lighting\n"); |
| |
| #ifdef GL_MESA_program_debug |
| if (argc > 1 && strcmp(argv[1], "fragment") == 0) { |
| printf(">> Debugging fragment program\n"); |
| glProgramCallbackMESA(GL_FRAGMENT_PROGRAM_ARB, Debugger2, |
| (GLvoid *) fragProgramText); |
| glEnable(GL_FRAGMENT_PROGRAM_CALLBACK_MESA); |
| } |
| else { |
| printf(">> Debugging vertex program\n"); |
| glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, Debugger2, |
| (GLvoid *) fragProgramText); |
| glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA); |
| } |
| #endif |
| } |
| |
| |
| int main( int argc, char *argv[] ) |
| { |
| glutInit( &argc, argv ); |
| glutInitWindowPosition( 0, 0 ); |
| glutInitWindowSize( 200, 200 ); |
| glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); |
| glutCreateWindow(argv[0]); |
| glutReshapeFunc( Reshape ); |
| glutKeyboardFunc( Key ); |
| glutSpecialFunc( SpecialKey ); |
| glutDisplayFunc( Display ); |
| if (Anim) |
| glutIdleFunc(Idle); |
| Init(argc, argv); |
| glutMainLoop(); |
| return 0; |
| } |