envphong.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:16k
- /* envphong.c - David G. Yu, SGI */
- /**
- ** Demonstrates a use of environment texture mapping for improved highlight
- ** shading.
- **
- ** Press mouse button one to move the object, press mouse button two to
- ** move the light source. Pressing the <s> key switches between using
- ** regular lighting or texture mapping for the specular highlights. The
- ** <o> key will cycle through objects (sphere, cylinder, torus). Check
- ** out the event loop code below for other keys which do will things.
- **
- ** TBD
- ** - improve accuracy of the highlight texture map
- ** - reduce or eliminate grazing angle artifacts
- ** - improve user interaction
- **
- ** 1995 -- David G Yu
- **
- ** cc -o envphong envphong.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm
- **/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <GL/glut.h>
- /* Some <math.h> files do not define M_PI... */
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
- int win, win2;
- int needsLightUpdate = GL_TRUE;
- int useLighting = GL_TRUE;
- int useSpecularTexture = GL_FALSE;
- int useTexture = GL_FALSE;
- int useHighRes = GL_FALSE;
- int usePattern = GL_FALSE;
- int moveLight = GL_FALSE;
- int moveObject = GL_FALSE;
- int drawObj = 0, maxObj = 2;
- GLfloat lightRotX, lightRotY;
- GLfloat objectRotX, objectRotY;
- int curx, cury, width, height;
- void
- drawSphere(int numMajor, int numMinor, float radius)
- {
- double majorStep = (M_PI / numMajor);
- double minorStep = (2.0 * M_PI / numMinor);
- int i, j;
- for (i = 0; i < numMajor; ++i) {
- double a = i * majorStep;
- double b = a + majorStep;
- double r0 = radius * sin(a);
- double r1 = radius * sin(b);
- GLfloat z0 = radius * cos(a);
- GLfloat z1 = radius * cos(b);
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0; j <= numMinor; ++j) {
- double c = j * minorStep;
- GLfloat x = cos(c);
- GLfloat y = sin(c);
- glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
- glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
- glVertex3f(x * r0, y * r0, z0);
- glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
- glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
- glVertex3f(x * r1, y * r1, z1);
- }
- glEnd();
- }
- }
- void
- drawCylinder(int numMajor, int numMinor, float height, float radius)
- {
- double majorStep = height / numMajor;
- double minorStep = 2.0 * M_PI / numMinor;
- int i, j;
- for (i = 0; i < numMajor; ++i) {
- GLfloat z0 = 0.5 * height - i * majorStep;
- GLfloat z1 = z0 - majorStep;
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0; j <= numMinor; ++j) {
- double a = j * minorStep;
- GLfloat x = radius * cos(a);
- GLfloat y = radius * sin(a);
- glNormal3f(x / radius, y / radius, 0.0);
- glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
- glVertex3f(x, y, z0);
- glNormal3f(x / radius, y / radius, 0.0);
- glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
- glVertex3f(x, y, z1);
- }
- glEnd();
- }
- }
- void
- drawTorus(int numMajor, int numMinor, float majorRadius, float minorRadius)
- {
- double majorStep = 2.0 * M_PI / numMajor;
- double minorStep = 2.0 * M_PI / numMinor;
- int i, j;
- for (i = 0; i < numMajor; ++i) {
- double a0 = i * majorStep;
- double a1 = a0 + majorStep;
- GLfloat x0 = cos(a0);
- GLfloat y0 = sin(a0);
- GLfloat x1 = cos(a1);
- GLfloat y1 = sin(a1);
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0; j <= numMinor; ++j) {
- double b = j * minorStep;
- GLfloat c = cos(b);
- GLfloat r = minorRadius * c + majorRadius;
- GLfloat z = minorRadius * sin(b);
- glNormal3f(x0 * c, y0 * c, z / minorRadius);
- glTexCoord2f(i / (GLfloat) numMajor, j / (GLfloat) numMinor);
- glVertex3f(x0 * r, y0 * r, z);
- glNormal3f(x1 * c, y1 * c, z / minorRadius);
- glTexCoord2f((i + 1) / (GLfloat) numMajor, j / (GLfloat) numMinor);
- glVertex3f(x1 * r, y1 * r, z);
- }
- glEnd();
- }
- }
- void
- setNullTexture(void)
- {
- GLubyte texPixel[4] =
- {0xff, 0xff, 0xff, 0xff};
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 1, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, texPixel);
- }
- void
- setCheckTexture(void)
- {
- int texWidth = 64;
- int texHeight = 64;
- GLubyte *texPixels, *p;
- int i, j;
- texPixels = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
- if (texPixels == NULL) {
- return;
- }
- p = texPixels;
- for (i = 0; i < texHeight; ++i) {
- for (j = 0; j < texWidth; ++j) {
- if ((i ^ j) & 8) {
- p[0] = 0xff;
- p[1] = 0xff;
- p[2] = 0xff;
- p[3] = 0xff;
- } else {
- p[0] = 0x08;
- p[1] = 0x08;
- p[2] = 0x08;
- p[3] = 0xff;
- }
- p += 4;
- }
- }
- glTexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
- GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
- free(texPixels);
- }
- void
- setLight(void)
- {
- GLfloat light0Pos[4] =
- {0.70, 0.70, 1.25, 0.00};
- GLfloat light0Amb[4] =
- {0.00, 0.00, 0.00, 1.00};
- GLfloat light0Diff[4] =
- {1.00, 1.00, 1.00, 1.00};
- GLfloat light0Spec[4] =
- {1.00, 1.00, 1.00, 1.00};
- GLfloat light0SpotDir[3] =
- {0.00, 0.00, -1.00};
- GLfloat light0SpotExp = 0.00;
- GLfloat light0SpotCutoff = 180.00;
- GLfloat light0Atten0 = 1.00;
- GLfloat light0Atten1 = 0.00;
- GLfloat light0Atten2 = 0.00;
- glEnable(GL_LIGHT0);
- glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, light0Amb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diff);
- glLightfv(GL_LIGHT0, GL_SPECULAR, light0Spec);
- glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0SpotDir);
- glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, light0SpotExp);
- glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, light0SpotCutoff);
- glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, light0Atten0);
- glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, light0Atten1);
- glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0Atten2);
- }
- #define MAT_ALL 0
- #define MAT_NO_SPECULAR 1
- #define MAT_SPECULAR_ONLY 2
- #define MAT_SPECULAR_TEXTURE_ONLY 3
- #define MAT_GEN_SPECULAR_TEXTURE 4
- void
- setMaterial(int mode)
- {
- static GLubyte *texPixels;
- int texWidth = 128;
- int texHeight = 128;
- GLfloat matZero[4] =
- {0.00, 0.00, 0.00, 1.00};
- GLfloat matOne[4] =
- {1.00, 1.00, 1.00, 1.00};
- GLfloat matEm[4] =
- {0.00, 0.00, 0.00, 1.00};
- GLfloat matAmb[4] =
- {0.01, 0.01, 0.01, 1.00};
- GLfloat matDiff[4] =
- {0.02, 0.20, 0.16, 1.00};
- GLfloat matSpec[4] =
- {0.50, 0.50, 0.50, 1.00};
- GLfloat matShine = 20.00;
- if ((mode == MAT_ALL) || (mode == MAT_NO_SPECULAR)) {
- glMaterialfv(GL_FRONT, GL_EMISSION, matEm);
- glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
- } else {
- glMaterialfv(GL_FRONT, GL_EMISSION, matZero);
- glMaterialfv(GL_FRONT, GL_AMBIENT, matZero);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, matZero);
- }
- if ((mode == MAT_ALL) || (mode == MAT_SPECULAR_ONLY)) {
- glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
- glMaterialf(GL_FRONT, GL_SHININESS, matShine);
- } else {
- glMaterialfv(GL_FRONT, GL_SPECULAR, matZero);
- glMaterialf(GL_FRONT, GL_SHININESS, 1);
- }
- if (mode == MAT_SPECULAR_TEXTURE_ONLY) {
- if (texPixels == NULL) {
- return;
- }
- glMaterialfv(GL_FRONT, GL_SPECULAR, matOne);
- glMaterialf(GL_FRONT, GL_SHININESS, 0);
- glTexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
- GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
- }
- if (mode == MAT_GEN_SPECULAR_TEXTURE) {
- if (texPixels == NULL) {
- texPixels = (GLubyte *)
- malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
- if (texPixels == NULL) {
- return;
- }
- }
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- setMaterial(MAT_SPECULAR_ONLY);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(-1, 1, -1, 1, 1, 3);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glTranslatef(0, 0, -2);
- glPushMatrix();
- glRotatef(lightRotY, 0, 1, 0);
- glRotatef(lightRotX, 1, 0, 0);
- setLight();
- glPopMatrix();
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glViewport(0, 0, 128, 128);
- glClearColor(.25, .25, .25, .25);
- glClear(GL_COLOR_BUFFER_BIT);
- drawSphere(128, 128, 1.0);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glReadPixels(0, 0, texWidth, texHeight,
- GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
- glPopAttrib();
- }
- }
- void
- initialize(void)
- {
- glMatrixMode(GL_PROJECTION);
- glFrustum(-0.50, 0.50, -0.50, 0.50, 1.0, 3.0);
- glMatrixMode(GL_MODELVIEW);
- glTranslatef(0.0, 0.0, -2.0);
- glDepthFunc(GL_LEQUAL);
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
- }
- void
- redraw(void)
- {
- glClearColor(0.1, 0.1, 0.1, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glBegin(GL_QUADS);
- glColor3f(0.9, 0.0, 1.0);
- glVertex3f(-2.0, -2.0, -1.0);
- glColor3f(0.9, 0.0, 1.0);
- glVertex3f(2.0, -2.0, -1.0);
- glColor3f(0.0, 0.1, 0.1);
- glVertex3f(2.0, 2.0, -1.0);
- glColor3f(0.0, 0.1, 0.1);
- glVertex3f(-2.0, 2.0, -1.0);
- glEnd();
- glEnable(GL_DEPTH_TEST);
- if (useLighting) {
- glEnable(GL_LIGHTING);
- glPushMatrix();
- glRotatef(lightRotY, 0, 1, 0);
- glRotatef(lightRotX, 1, 0, 0);
- setLight();
- glPopMatrix();
- } else {
- glColor3f(0.2, 0.2, 0.2);
- }
- if (useTexture || useSpecularTexture) {
- glEnable(GL_TEXTURE_2D);
- }
- if (useTexture) {
- setCheckTexture();
- } else {
- setNullTexture();
- }
- if (useSpecularTexture) {
- /* pass one */
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ZERO);
- setMaterial(MAT_NO_SPECULAR);
- } else {
- setMaterial(MAT_ALL);
- }
- glPushMatrix();
- glRotatef(objectRotY, 0, 1, 0);
- glRotatef(objectRotX, 1, 0, 0);
- if (useHighRes) {
- switch (drawObj) {
- case 0:
- drawSphere(64, 64, 0.8);
- break;
- case 1:
- drawCylinder(32, 64, 1.0, 0.4);
- break;
- case 2:
- drawTorus(64, 64, 0.6, 0.2);
- break;
- default:
- break;
- }
- } else {
- switch (drawObj) {
- case 0:
- drawSphere(16, 32, 0.8);
- break;
- case 1:
- drawCylinder(6, 16, 1.0, 0.4);
- break;
- case 2:
- drawTorus(32, 16, 0.6, 0.2);
- break;
- default:
- break;
- }
- }
- glPopMatrix();
- if (useSpecularTexture) {
- /* pass two */
- if (!useLighting) {
- glColor3f(1.0, 1.0, 1.0);
- }
- glBlendFunc(GL_ONE, GL_ONE);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- setMaterial(MAT_SPECULAR_TEXTURE_ONLY);
- glPushMatrix();
- glRotatef(objectRotY, 0, 1, 0);
- glRotatef(objectRotX, 1, 0, 0);
- if (useHighRes) {
- switch (drawObj) {
- case 0:
- drawSphere(64, 64, 0.8);
- break;
- case 1:
- drawCylinder(32, 64, 1.0, 0.4);
- break;
- case 2:
- drawTorus(64, 64, 0.6, 0.2);
- break;
- default:
- break;
- }
- } else {
- switch (drawObj) {
- case 0:
- drawSphere(16, 32, 0.8);
- break;
- case 1:
- drawCylinder(6, 16, 1.0, 0.4);
- break;
- case 2:
- drawTorus(32, 16, 0.6, 0.2);
- break;
- default:
- break;
- }
- }
- glPopMatrix();
- }
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- }
- void
- checkErrors(void)
- {
- GLenum error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- fprintf(stderr, "Error: %sn", (char *) gluErrorString(error));
- }
- }
- void
- usage(char *name)
- {
- fprintf(stderr, "n");
- fprintf(stderr, "usage: %s [ options ]n", name);
- fprintf(stderr, "n");
- fprintf(stderr, " Options:n");
- fprintf(stderr, " nonen");
- fprintf(stderr, "n");
- }
- void
- help(void)
- {
- printf("'h' - helpn");
- printf("'l' - toggle lightingn");
- printf("'o' - switch objectsn");
- printf("'r' - toggle resolutionn");
- printf("'s' - toggle two pass lightingn");
- printf("'t' - toggle texturingn");
- printf("left mouse - move objectn");
- printf("middle mouse - move lightn");
- }
- void
- motion(int x, int y)
- {
- if (moveLight || moveObject) {
- GLfloat dx = (y - cury) * 360.0 / height;
- GLfloat dy = (x - curx) * 360.0 / width;
- if (moveLight) {
- lightRotX += dx;
- if (lightRotX > 360)
- lightRotX -= 360;
- if (lightRotX < 0)
- lightRotX += 360;
- lightRotY += dy;
- if (lightRotY > 360)
- lightRotY -= 360;
- if (lightRotY < 0)
- lightRotY += 360;
- needsLightUpdate = GL_TRUE;
- } else if (moveObject) {
- objectRotX += dx;
- if (objectRotX > 360)
- objectRotX -= 360;
- if (objectRotX < 0)
- objectRotX += 360;
- objectRotY += dy;
- if (objectRotY > 360)
- objectRotY -= 360;
- if (objectRotY < 0)
- objectRotY += 360;
- }
- curx = x;
- cury = y;
- }
- glutPostRedisplay();
- }
- void
- mouse(int button, int state, int x, int y)
- {
- if (state == GLUT_DOWN) {
- switch (button) {
- case GLUT_LEFT_BUTTON:
- moveObject = GL_TRUE;
- motion(curx = x, cury = y);
- break;
- case GLUT_MIDDLE_BUTTON:
- moveLight = GL_TRUE;
- motion(curx = x, cury = y);
- break;
- }
- } else if (state == GLUT_UP) {
- switch (button) {
- case GLUT_LEFT_BUTTON:
- moveObject = GL_FALSE;
- break;
- case GLUT_MIDDLE_BUTTON:
- moveLight = GL_FALSE;
- break;
- }
- }
- }
- void
- display(void)
- {
- if (useSpecularTexture && needsLightUpdate) {
- setMaterial(MAT_GEN_SPECULAR_TEXTURE);
- needsLightUpdate = GL_FALSE;
- }
- redraw();
- glFlush();
- glutSwapBuffers();
- checkErrors();
- }
- void
- reshape(int w, int h)
- {
- glViewport(0, 0, width = w, height = h);
- }
- /* ARGSUSED1 */
- void
- key(unsigned char key, int x, int y)
- {
- switch (key) {
- case 'h':
- help();
- break;
- case ' ':
- break;
- case 'l':
- useLighting = !useLighting;
- break;
- case 's':
- useSpecularTexture = !useSpecularTexture;
- needsLightUpdate = GL_TRUE;
- break;
- case 't':
- useTexture = !useTexture;
- break;
- case 'r':
- useHighRes = !useHighRes;
- break;
- case 'o':
- ++drawObj;
- if (drawObj > maxObj)
- drawObj = 0;
- break;
- case ' 33':
- exit(0);
- }
- glutPostRedisplay();
- }
- /* ARGSUSED1 */
- void
- domenu(int value)
- {
- key((unsigned char) value, 0, 0);
- }
- int
- main(int argc, char **argv)
- {
- int i;
- glutInit(&argc, argv);
- glutInitWindowSize(width = 300, height = 300);
- glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
- for (i = 1; i < argc; ++i) {
- usage(argv[0]);
- exit(1);
- }
- win = glutCreateWindow("envphong");
- glutDisplayFunc(display);
- glutKeyboardFunc(key);
- glutReshapeFunc(reshape);
- glutMouseFunc(mouse);
- glutMotionFunc(motion);
- glutCreateMenu(domenu);
- glutAddMenuEntry("Toggle lighting", 'l');
- glutAddMenuEntry("Toggle checker texture", 't');
- glutAddMenuEntry("Toggle two-pass textured specular", 's');
- glutAddMenuEntry("Toggle object resolution", 'r');
- glutAddMenuEntry("Switch object", 'o');
- glutAddMenuEntry("Print help", 'h');
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- initialize();
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }