shadowmap.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:11k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* shadowmap.c - by Tom McReynolds, SGI */
  2. /* Shadows: Shadow volumes. */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include <GL/glut.h>
  7. /* This program demonstrates shadows on IR using single pass projective
  8.    texture method.  1. Render the scene with light position as the viewpoint
  9.    and save the depth-map into texture image.  2. Use texgen to generate
  10.    texture co-ordinates which are identical to vertex co-ordinates. The
  11.    texture matrix then transforms each pixel coods back to light co-ods. The
  12.    'z' or the depth-value is now available in the 'r' texture co-ordinate.
  13.    3. Render the normal scene enabling texgen and shadow texture comparison. 
  14.    Left mouse button: controls rotation of the scene
  15.    Right mouse button: controls light (and shadow position) */
  16. #define SCENE 10
  17. enum {
  18.   M_NORMAL, M_SHADOW, M_PROJTEX, M_LIGHT
  19. };
  20. GLfloat rotv[] =
  21. {0.0, 0.0, 0.0};        /* rotation vector for scene */
  22. GLfloat rotl[] =
  23. {0.0, 0.0, 0.0};        /* rotation vector for light */
  24. GLfloat lv[] =
  25. {10.0, 10.0, 10.0, 1.0};  /* default light position */
  26. GLfloat perspective_mat[16], modelview_mat[16], temp[16];
  27. int width = 512, height = 512;
  28. int mouse_button, mouse_state;
  29. static int do_light = 0;
  30. static int do_proj = 0; /* Use projective textures instead of shadows */
  31. /* are shadow extensions supported? */
  32. GLboolean shadows_supported = GL_FALSE;
  33. GLboolean ambient_shadows = GL_FALSE;
  34. GLboolean depth_texture = GL_FALSE;
  35. static void generate_shadow_map(void);
  36. static void 
  37. reshape(int w, int h)
  38. {
  39.   glViewport(0, 0, w, h);
  40.   width = w;
  41.   height = h;
  42.   glMatrixMode(GL_PROJECTION);
  43.   glLoadIdentity();
  44.   gluPerspective(40.0, (GLfloat) w / (GLfloat) h, 2.0, 30.0);
  45.   glMatrixMode(GL_MODELVIEW);
  46.   glLoadIdentity();
  47.   gluLookAt(0, 0, 15,
  48.     0, 0, 0,
  49.     0, 1, 0);
  50. }
  51. /* ARGSUSED1 */
  52. static void 
  53. key(unsigned char key, int x, int y)
  54. {
  55.   switch (key) {
  56.   case '33':
  57.     exit(0);
  58.   }
  59. }
  60. /* ARGSUSED2 */
  61. static void 
  62. mouse(int button, int state, int x, int y)
  63. {
  64.   mouse_button = button;
  65.   mouse_state = state;
  66. }
  67. static void 
  68. motion(int x, int y)
  69. {
  70.   if (mouse_state == GLUT_UP)
  71.     return;
  72.   switch (mouse_button) {
  73.   case GLUT_LEFT_BUTTON:
  74.     rotv[1] = 180.0 * x / 400.0 - 90.0;
  75.     rotv[0] = 180.0 * y / 400.0 - 90.0;
  76.     break;
  77.   case GLUT_MIDDLE_BUTTON:
  78.     rotl[0] = 180.0 * x / 400.0 - 90.0;
  79.     rotl[1] = 180.0 * y / 400.0 - 90.0;
  80.     break;
  81.   }
  82.   glutPostRedisplay();
  83. }
  84. static void 
  85. display(void)
  86. {
  87.   /* Render the scene with the light source as the viewpoint and save the
  88.      depth values in the texture map.  */
  89.   generate_shadow_map();
  90.   /* Now render the normal scene using projective textures to get the depth
  91.      value from the light's point of view into the r-cood of the texture.  */
  92.   glEnable(GL_TEXTURE_2D);
  93.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  94.   glGetFloatv(GL_PROJECTION_MATRIX, perspective_mat);
  95.   glMatrixMode(GL_TEXTURE);
  96.   glLoadIdentity();
  97.   glTranslatef(0.5, 0.5, 0.4994);
  98.   glScalef(0.5, 0.5, 0.5);
  99.   glMultMatrixf(perspective_mat);
  100.   glMultMatrixf(modelview_mat);
  101.   glMatrixMode(GL_MODELVIEW);
  102.   glPushMatrix();
  103.   glRotatef(rotv[0], 1, 0, 0);
  104.   glRotatef(rotv[1], 0, 1, 0);
  105.   glRotatef(rotv[2], 0, 0, 1);
  106.   glCallList(SCENE);
  107.   glPopMatrix();
  108.   glutSwapBuffers();
  109. }
  110. static void 
  111. render_normal_view(void)
  112. {
  113.   glDisable(GL_TEXTURE_2D);
  114.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  115.   glMatrixMode(GL_MODELVIEW);
  116.   glPushMatrix();
  117.   glLoadIdentity();
  118.   gluLookAt(0, 0, 15,
  119.     0, 0, 0,
  120.     0, 1, 0);
  121.   glRotatef(rotv[0], 1, 0, 0);
  122.   glRotatef(rotv[1], 0, 1, 0);
  123.   glRotatef(rotv[2], 0, 0, 1);
  124.   glCallList(SCENE);
  125.   glPopMatrix();
  126.   glutSwapBuffers();
  127. }
  128. static void 
  129. render_light_view(void)
  130. {
  131.   glDisable(GL_TEXTURE_2D);
  132.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  133.   glMatrixMode(GL_MODELVIEW);
  134.   glPushMatrix();
  135.   glLoadIdentity();
  136.   gluLookAt(lv[0], lv[1], lv[2],
  137.     0, 0, 0,
  138.     0, 1, 0);
  139.   glRotatef(rotl[0], 1, 0, 0);
  140.   glRotatef(rotl[1], 0, 1, 0);
  141.   glRotatef(rotl[2], 0, 0, 1);
  142.   glGetFloatv(GL_MODELVIEW_MATRIX, modelview_mat);
  143.   glCallList(SCENE);
  144.   glPopMatrix();
  145.   if (do_light)
  146.     glutSwapBuffers();
  147. }
  148. static void 
  149. generate_shadow_map(void)
  150. {
  151.   int x, y;
  152.   GLfloat log2 = log(2.0);
  153.   x = 1 << ((int) (log((float) width) / log2));
  154.   y = 1 << ((int) (log((float) height) / log2));
  155.   glViewport(0, 0, x, y);
  156.   render_light_view();
  157.   /* Read in frame-buffer into a depth texture map */
  158. #if defined(GL_EXT_subtexture) && defined(GL_EXT_copy_texture)
  159. #ifdef GL_SGIX_depth_texture
  160.   if (do_proj && depth_texture)
  161. #endif
  162.     glCopyTexImage2DEXT(GL_TEXTURE_2D, 0, GL_RGBA,
  163.       0, 0, x, y, 0);
  164. #ifdef GL_SGIX_depth_texture
  165.   else
  166.     glCopyTexImage2DEXT(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_SGIX,
  167.       0, 0, x, y, 0);
  168. #endif
  169. #endif
  170.   glViewport(0, 0, width, height);
  171. }
  172. static void 
  173. menu(int mode)
  174. {
  175.   switch (mode) {
  176.   case M_NORMAL:
  177.     do_light = 0;
  178.     do_proj = 0;
  179. #ifdef GL_SGIX_shadow
  180.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
  181. #endif
  182.     glutDisplayFunc(render_normal_view);
  183.     break;
  184.   case M_SHADOW:
  185. #ifdef GL_SGIX_shadow
  186.     do_light = 0;
  187.     do_proj = 0;
  188.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
  189.     glutDisplayFunc(display);
  190. #endif
  191.     break;
  192.   case M_PROJTEX:
  193.     do_light = 0;
  194.     do_proj = 1;
  195. #ifdef GL_SGIX_shadow
  196.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
  197. #endif
  198.     glutDisplayFunc(display);
  199.     break;
  200.   case M_LIGHT:
  201.     do_light = 1;
  202.     if (do_light)
  203.       glutDisplayFunc(render_light_view);
  204.     else
  205.       glutDisplayFunc(display);
  206.     break;
  207.   }
  208.   glutPostRedisplay();
  209. }
  210. #define XFORM(cmds) 
  211.   glMatrixMode(GL_TEXTURE); 
  212.   cmds; 
  213.   glMatrixMode(GL_MODELVIEW); 
  214.   cmds
  215. static void 
  216. create_scene(void)
  217. {
  218.   GLfloat floor_col[] =
  219.   {0.7, 0.7, 0.7};
  220.   GLfloat floor_norm[] =
  221.   {0.0, 0.0, 1.0};
  222.   GLfloat floor_verts[4][3] =
  223.   {
  224.     {4.0, 4.0, 0.0},
  225.     {-4.0, 4.0, 0.0},
  226.     {-4.0, -4.0, 0.0},
  227.     {4.0, -4.0, 0.0}};
  228.   GLfloat sphere_col[] =
  229.   {0.7, 0.1, 0.2};
  230.   GLfloat box_col[] =
  231.   {0.1, 0.2, 0.7};
  232.   GLfloat box_verts[6][4][3] =
  233.   {
  234.     {
  235.       {1.0, -1.0, -1.0},
  236.       {-1.0, -1.0, -1.0},
  237.       {-1.0, 1.0, -1.0},
  238.       {1.0, 1.0, -1.0}},
  239.     {
  240.       {1.0, -1.0, 1.0},
  241.       {1.0, -1.0, -1.0},
  242.       {1.0, 1.0, -1.0},
  243.       {1.0, 1.0, 1.0}},
  244.     {
  245.       {-1.0, -1.0, 1.0},
  246.       {1.0, -1.0, 1.0},
  247.       {1.0, 1.0, 1.0},
  248.       {-1.0, 1.0, 1.0}},
  249.     {
  250.       {-1.0, -1.0, -1.0},
  251.       {-1.0, -1.0, 1.0},
  252.       {-1.0, 1.0, 1.0},
  253.       {-1.0, 1.0, -1.0}},
  254.     {
  255.       {1.0, 1.0, 1.0},
  256.       {1.0, 1.0, -1.0},
  257.       {-1.0, 1.0, -1.0},
  258.       {-1.0, 1.0, 1.0}},
  259.     {
  260.       {1.0, -1.0, -1.0},
  261.       {1.0, -1.0, 1.0},
  262.       {-1.0, -1.0, 1.0},
  263.       {-1.0, -1.0, -1.0}}};
  264.   GLfloat box_norm[6][3] =
  265.   {
  266.     {0, 0, -1},
  267.     {1, 0, 0},
  268.     {0, 0, 1},
  269.     {-1, 0, 0},
  270.     {0, 1, 0},
  271.     {0, -1, 0}};
  272.   GLUquadricObj *q;
  273.   int i;
  274.   glNewList(SCENE, GL_COMPILE);
  275.   glBegin(GL_QUADS);    /* draw the floor */
  276.   glNormal3fv(floor_norm);
  277.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, floor_col);
  278.   for (i = 0; i < 4; i++)
  279.     glVertex3fv(floor_verts[i]);
  280.   glEnd();
  281.   q = gluNewQuadric();
  282.   XFORM(glPushMatrix();
  283.     glTranslatef(1.0, 1.0, 1.01));
  284.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_col);
  285.   gluSphere(q, 1.0, 40, 40);
  286.   XFORM(glPopMatrix());
  287.   XFORM(glPushMatrix();
  288.     glTranslatef(-1.0, -1.0, 1.01));
  289.   for (i = 0; i < 6; i++) {
  290.     glBegin(GL_QUADS);
  291.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, box_col);
  292.     glNormal3fv(box_norm[i]);
  293.     glVertex3fv(box_verts[i][0]);
  294.     glVertex3fv(box_verts[i][1]);
  295.     glVertex3fv(box_verts[i][2]);
  296.     glVertex3fv(box_verts[i][3]);
  297.     glEnd();
  298.   }
  299.   XFORM(glPopMatrix());
  300.   glEndList();
  301. }
  302. static void 
  303. init(void)
  304. {
  305.   GLfloat ambient[] =
  306.   {0.1, 0.1, 0.1, 1.0};
  307.   GLfloat diffuse[] =
  308.   {0.8, 0.7, 0.8, 1.0};
  309.   GLfloat specular[] =
  310.   {0.5, 0.6, 0.8, 1.0};
  311.   GLfloat p[4];
  312.   create_scene();
  313.   glClearColor(0.0, 0.0, 0.0, 1.0);
  314.   glClearDepth(1.0);
  315.   glEnable(GL_DEPTH_TEST);
  316.   glEnable(GL_POLYGON_SMOOTH);
  317.   glEnable(GL_LIGHTING);
  318.   glEnable(GL_LIGHT0);
  319.   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  320.   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  321.   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  322.   glLightfv(GL_LIGHT0, GL_POSITION, lv);
  323.   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  324.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  325.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  326.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  327.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  328.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  329.   if (shadows_supported) {
  330. #ifdef GL_SGIX_shadow_ambient
  331.     if (ambient_shadows)
  332.       glTexParameterf(GL_TEXTURE_2D, GL_SHADOW_AMBIENT_SGIX, 0.6);
  333. #endif
  334. #ifdef GL_SGIX_shadow
  335.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
  336.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
  337.       GL_TEXTURE_LEQUAL_R_SGIX);
  338. #endif
  339.   }
  340.   /* Enable texgen to get texture-coods (x, y, z, w) at every point.These
  341.      texture co-ordinates are then transformed by the texture matrix.  */
  342.   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  343.   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  344.   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  345.   glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  346.   p[0] = 1.0;
  347.   p[1] = p[2] = p[3] = 0.0;
  348.   glTexGenfv(GL_S, GL_OBJECT_PLANE, p);
  349.   p[0] = 0.0;
  350.   p[1] = 1.0;
  351.   p[2] = p[3] = 0.0;
  352.   glTexGenfv(GL_T, GL_OBJECT_PLANE, p);
  353.   p[0] = p[1] = 0.0;
  354.   p[2] = 1.0, p[3] = 0.0;
  355.   glTexGenfv(GL_R, GL_OBJECT_PLANE, p);
  356.   p[0] = p[1] = p[2] = 0.0;
  357.   p[3] = 1.0;
  358.   glTexGenfv(GL_Q, GL_OBJECT_PLANE, p);
  359.   glEnable(GL_TEXTURE_GEN_S);
  360.   glEnable(GL_TEXTURE_GEN_T);
  361.   glEnable(GL_TEXTURE_GEN_R);
  362.   glEnable(GL_TEXTURE_GEN_Q);
  363. }
  364. int
  365. main(int argc, char *argv[])
  366. {
  367.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  368.   glutInitWindowSize(width, height);
  369.   glutCreateWindow("Shadow Map");
  370.   if (glutExtensionSupported("GL_SGIX_shadow") &&
  371.     glutExtensionSupported("GL_EXT_subtexture") &&
  372.     glutExtensionSupported("GL_EXT_copy_texture")) {
  373.     shadows_supported = GL_TRUE;
  374.     ambient_shadows = glutExtensionSupported("GL_SGIX_shadow_ambient");
  375.     depth_texture = glutExtensionSupported("GL_SGIX_depth_texture");
  376.   } else {
  377.     fprintf(stderr, "shadowmap: uses several OpenGL extensions to operate fully:n");
  378.     fprintf(stderr, "  GL_SGIX_shadown");
  379.     fprintf(stderr, "  GL_SGIX_shadow_ambientn");
  380.     fprintf(stderr, "  GL_SGIS_depth_texturen");
  381.     fprintf(stderr, "  GL_EXT_subtexturen");
  382.     fprintf(stderr, "  GL_EXT_copy_texturen");
  383.   }
  384.   init();
  385.   glutReshapeFunc(reshape);
  386.   glutDisplayFunc(display);
  387.   glutMotionFunc(motion);
  388.   glutMouseFunc(mouse);
  389.   glutKeyboardFunc(key);
  390.   glutCreateMenu(menu);
  391.   glutAddMenuEntry("Normal view", M_NORMAL);
  392.   glutAddMenuEntry("Light view", M_LIGHT);
  393.   glutAddMenuEntry("Projective textures", M_PROJTEX);
  394.   if (shadows_supported)
  395.     glutAddMenuEntry("Shadows", M_SHADOW);
  396.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  397.   glutMainLoop();
  398.   return 0;             /* ANSI C requires main to return int. */
  399. }