shadowmap.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:11k
- /* shadowmap.c - by Tom McReynolds, SGI */
- /* Shadows: Shadow volumes. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <GL/glut.h>
- /* This program demonstrates shadows on IR using single pass projective
- texture method. 1. Render the scene with light position as the viewpoint
- and save the depth-map into texture image. 2. Use texgen to generate
- texture co-ordinates which are identical to vertex co-ordinates. The
- texture matrix then transforms each pixel coods back to light co-ods. The
- 'z' or the depth-value is now available in the 'r' texture co-ordinate.
- 3. Render the normal scene enabling texgen and shadow texture comparison.
- Left mouse button: controls rotation of the scene
- Right mouse button: controls light (and shadow position) */
- #define SCENE 10
- enum {
- M_NORMAL, M_SHADOW, M_PROJTEX, M_LIGHT
- };
- GLfloat rotv[] =
- {0.0, 0.0, 0.0}; /* rotation vector for scene */
- GLfloat rotl[] =
- {0.0, 0.0, 0.0}; /* rotation vector for light */
- GLfloat lv[] =
- {10.0, 10.0, 10.0, 1.0}; /* default light position */
- GLfloat perspective_mat[16], modelview_mat[16], temp[16];
- int width = 512, height = 512;
- int mouse_button, mouse_state;
- static int do_light = 0;
- static int do_proj = 0; /* Use projective textures instead of shadows */
- /* are shadow extensions supported? */
- GLboolean shadows_supported = GL_FALSE;
- GLboolean ambient_shadows = GL_FALSE;
- GLboolean depth_texture = GL_FALSE;
- static void generate_shadow_map(void);
- static void
- reshape(int w, int h)
- {
- glViewport(0, 0, w, h);
- width = w;
- height = h;
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(40.0, (GLfloat) w / (GLfloat) h, 2.0, 30.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt(0, 0, 15,
- 0, 0, 0,
- 0, 1, 0);
- }
- /* ARGSUSED1 */
- static void
- key(unsigned char key, int x, int y)
- {
- switch (key) {
- case ' 33':
- exit(0);
- }
- }
- /* ARGSUSED2 */
- static void
- mouse(int button, int state, int x, int y)
- {
- mouse_button = button;
- mouse_state = state;
- }
- static void
- motion(int x, int y)
- {
- if (mouse_state == GLUT_UP)
- return;
- switch (mouse_button) {
- case GLUT_LEFT_BUTTON:
- rotv[1] = 180.0 * x / 400.0 - 90.0;
- rotv[0] = 180.0 * y / 400.0 - 90.0;
- break;
- case GLUT_MIDDLE_BUTTON:
- rotl[0] = 180.0 * x / 400.0 - 90.0;
- rotl[1] = 180.0 * y / 400.0 - 90.0;
- break;
- }
- glutPostRedisplay();
- }
- static void
- display(void)
- {
- /* Render the scene with the light source as the viewpoint and save the
- depth values in the texture map. */
- generate_shadow_map();
- /* Now render the normal scene using projective textures to get the depth
- value from the light's point of view into the r-cood of the texture. */
- glEnable(GL_TEXTURE_2D);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glGetFloatv(GL_PROJECTION_MATRIX, perspective_mat);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef(0.5, 0.5, 0.4994);
- glScalef(0.5, 0.5, 0.5);
- glMultMatrixf(perspective_mat);
- glMultMatrixf(modelview_mat);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glRotatef(rotv[0], 1, 0, 0);
- glRotatef(rotv[1], 0, 1, 0);
- glRotatef(rotv[2], 0, 0, 1);
- glCallList(SCENE);
- glPopMatrix();
- glutSwapBuffers();
- }
- static void
- render_normal_view(void)
- {
- glDisable(GL_TEXTURE_2D);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- gluLookAt(0, 0, 15,
- 0, 0, 0,
- 0, 1, 0);
- glRotatef(rotv[0], 1, 0, 0);
- glRotatef(rotv[1], 0, 1, 0);
- glRotatef(rotv[2], 0, 0, 1);
- glCallList(SCENE);
- glPopMatrix();
- glutSwapBuffers();
- }
- static void
- render_light_view(void)
- {
- glDisable(GL_TEXTURE_2D);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- gluLookAt(lv[0], lv[1], lv[2],
- 0, 0, 0,
- 0, 1, 0);
- glRotatef(rotl[0], 1, 0, 0);
- glRotatef(rotl[1], 0, 1, 0);
- glRotatef(rotl[2], 0, 0, 1);
- glGetFloatv(GL_MODELVIEW_MATRIX, modelview_mat);
- glCallList(SCENE);
- glPopMatrix();
- if (do_light)
- glutSwapBuffers();
- }
- static void
- generate_shadow_map(void)
- {
- int x, y;
- GLfloat log2 = log(2.0);
- x = 1 << ((int) (log((float) width) / log2));
- y = 1 << ((int) (log((float) height) / log2));
- glViewport(0, 0, x, y);
- render_light_view();
- /* Read in frame-buffer into a depth texture map */
- #if defined(GL_EXT_subtexture) && defined(GL_EXT_copy_texture)
- #ifdef GL_SGIX_depth_texture
- if (do_proj && depth_texture)
- #endif
- glCopyTexImage2DEXT(GL_TEXTURE_2D, 0, GL_RGBA,
- 0, 0, x, y, 0);
- #ifdef GL_SGIX_depth_texture
- else
- glCopyTexImage2DEXT(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_SGIX,
- 0, 0, x, y, 0);
- #endif
- #endif
- glViewport(0, 0, width, height);
- }
- static void
- menu(int mode)
- {
- switch (mode) {
- case M_NORMAL:
- do_light = 0;
- do_proj = 0;
- #ifdef GL_SGIX_shadow
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
- #endif
- glutDisplayFunc(render_normal_view);
- break;
- case M_SHADOW:
- #ifdef GL_SGIX_shadow
- do_light = 0;
- do_proj = 0;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
- glutDisplayFunc(display);
- #endif
- break;
- case M_PROJTEX:
- do_light = 0;
- do_proj = 1;
- #ifdef GL_SGIX_shadow
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
- #endif
- glutDisplayFunc(display);
- break;
- case M_LIGHT:
- do_light = 1;
- if (do_light)
- glutDisplayFunc(render_light_view);
- else
- glutDisplayFunc(display);
- break;
- }
- glutPostRedisplay();
- }
- #define XFORM(cmds)
- glMatrixMode(GL_TEXTURE);
- cmds;
- glMatrixMode(GL_MODELVIEW);
- cmds
- static void
- create_scene(void)
- {
- GLfloat floor_col[] =
- {0.7, 0.7, 0.7};
- GLfloat floor_norm[] =
- {0.0, 0.0, 1.0};
- GLfloat floor_verts[4][3] =
- {
- {4.0, 4.0, 0.0},
- {-4.0, 4.0, 0.0},
- {-4.0, -4.0, 0.0},
- {4.0, -4.0, 0.0}};
- GLfloat sphere_col[] =
- {0.7, 0.1, 0.2};
- GLfloat box_col[] =
- {0.1, 0.2, 0.7};
- GLfloat box_verts[6][4][3] =
- {
- {
- {1.0, -1.0, -1.0},
- {-1.0, -1.0, -1.0},
- {-1.0, 1.0, -1.0},
- {1.0, 1.0, -1.0}},
- {
- {1.0, -1.0, 1.0},
- {1.0, -1.0, -1.0},
- {1.0, 1.0, -1.0},
- {1.0, 1.0, 1.0}},
- {
- {-1.0, -1.0, 1.0},
- {1.0, -1.0, 1.0},
- {1.0, 1.0, 1.0},
- {-1.0, 1.0, 1.0}},
- {
- {-1.0, -1.0, -1.0},
- {-1.0, -1.0, 1.0},
- {-1.0, 1.0, 1.0},
- {-1.0, 1.0, -1.0}},
- {
- {1.0, 1.0, 1.0},
- {1.0, 1.0, -1.0},
- {-1.0, 1.0, -1.0},
- {-1.0, 1.0, 1.0}},
- {
- {1.0, -1.0, -1.0},
- {1.0, -1.0, 1.0},
- {-1.0, -1.0, 1.0},
- {-1.0, -1.0, -1.0}}};
- GLfloat box_norm[6][3] =
- {
- {0, 0, -1},
- {1, 0, 0},
- {0, 0, 1},
- {-1, 0, 0},
- {0, 1, 0},
- {0, -1, 0}};
- GLUquadricObj *q;
- int i;
- glNewList(SCENE, GL_COMPILE);
- glBegin(GL_QUADS); /* draw the floor */
- glNormal3fv(floor_norm);
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, floor_col);
- for (i = 0; i < 4; i++)
- glVertex3fv(floor_verts[i]);
- glEnd();
- q = gluNewQuadric();
- XFORM(glPushMatrix();
- glTranslatef(1.0, 1.0, 1.01));
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_col);
- gluSphere(q, 1.0, 40, 40);
- XFORM(glPopMatrix());
- XFORM(glPushMatrix();
- glTranslatef(-1.0, -1.0, 1.01));
- for (i = 0; i < 6; i++) {
- glBegin(GL_QUADS);
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, box_col);
- glNormal3fv(box_norm[i]);
- glVertex3fv(box_verts[i][0]);
- glVertex3fv(box_verts[i][1]);
- glVertex3fv(box_verts[i][2]);
- glVertex3fv(box_verts[i][3]);
- glEnd();
- }
- XFORM(glPopMatrix());
- glEndList();
- }
- static void
- init(void)
- {
- GLfloat ambient[] =
- {0.1, 0.1, 0.1, 1.0};
- GLfloat diffuse[] =
- {0.8, 0.7, 0.8, 1.0};
- GLfloat specular[] =
- {0.5, 0.6, 0.8, 1.0};
- GLfloat p[4];
- create_scene();
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glClearDepth(1.0);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_POLYGON_SMOOTH);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
- glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT0, GL_POSITION, lv);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- if (shadows_supported) {
- #ifdef GL_SGIX_shadow_ambient
- if (ambient_shadows)
- glTexParameterf(GL_TEXTURE_2D, GL_SHADOW_AMBIENT_SGIX, 0.6);
- #endif
- #ifdef GL_SGIX_shadow
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
- GL_TEXTURE_LEQUAL_R_SGIX);
- #endif
- }
- /* Enable texgen to get texture-coods (x, y, z, w) at every point.These
- texture co-ordinates are then transformed by the texture matrix. */
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- p[0] = 1.0;
- p[1] = p[2] = p[3] = 0.0;
- glTexGenfv(GL_S, GL_OBJECT_PLANE, p);
- p[0] = 0.0;
- p[1] = 1.0;
- p[2] = p[3] = 0.0;
- glTexGenfv(GL_T, GL_OBJECT_PLANE, p);
- p[0] = p[1] = 0.0;
- p[2] = 1.0, p[3] = 0.0;
- glTexGenfv(GL_R, GL_OBJECT_PLANE, p);
- p[0] = p[1] = p[2] = 0.0;
- p[3] = 1.0;
- glTexGenfv(GL_Q, GL_OBJECT_PLANE, p);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- glEnable(GL_TEXTURE_GEN_R);
- glEnable(GL_TEXTURE_GEN_Q);
- }
- int
- main(int argc, char *argv[])
- {
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
- glutInitWindowSize(width, height);
- glutCreateWindow("Shadow Map");
- if (glutExtensionSupported("GL_SGIX_shadow") &&
- glutExtensionSupported("GL_EXT_subtexture") &&
- glutExtensionSupported("GL_EXT_copy_texture")) {
- shadows_supported = GL_TRUE;
- ambient_shadows = glutExtensionSupported("GL_SGIX_shadow_ambient");
- depth_texture = glutExtensionSupported("GL_SGIX_depth_texture");
- } else {
- fprintf(stderr, "shadowmap: uses several OpenGL extensions to operate fully:n");
- fprintf(stderr, " GL_SGIX_shadown");
- fprintf(stderr, " GL_SGIX_shadow_ambientn");
- fprintf(stderr, " GL_SGIS_depth_texturen");
- fprintf(stderr, " GL_EXT_subtexturen");
- fprintf(stderr, " GL_EXT_copy_texturen");
- }
- init();
- glutReshapeFunc(reshape);
- glutDisplayFunc(display);
- glutMotionFunc(motion);
- glutMouseFunc(mouse);
- glutKeyboardFunc(key);
- glutCreateMenu(menu);
- glutAddMenuEntry("Normal view", M_NORMAL);
- glutAddMenuEntry("Light view", M_LIGHT);
- glutAddMenuEntry("Projective textures", M_PROJTEX);
- if (shadows_supported)
- glutAddMenuEntry("Shadows", M_SHADOW);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }