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

GIS编程

开发平台:

Visual C++

  1. /* shadowvol.c - by Tom McReynolds, SGI */
  2. /* Shadows: Shadow maps */
  3. #include <GL/glut.h>
  4. #include <stdlib.h>
  5. /* Demonstrate shadow volumes */
  6. /* Create a single component texture map */
  7. GLfloat *
  8. make_texture(int maxs, int maxt)
  9. {
  10.   int s, t;
  11.   static GLfloat *texture;
  12.   texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat));
  13.   for (t = 0; t < maxt; t++) {
  14.     for (s = 0; s < maxs; s++) {
  15.       texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  16.     }
  17.   }
  18.   return texture;
  19. }
  20. enum {
  21.   SPHERE = 1, CONE, LIGHT, SHADOWVOL
  22. };
  23. typedef struct {
  24.   GLfloat *verticies;
  25.   GLfloat *normal;
  26.   int n;                /* number of verticies */
  27. } ShadObj;
  28. GLfloat shadVerts[] =
  29. {30.f, 30.f, -350.f,
  30.   60.f, 20.f, -340.f,
  31.   40.f, 40.f, -400.f};
  32. GLfloat shadNormal[] =
  33. {1.f, 1.f, 1.f};
  34. ShadObj shadower;
  35. enum {
  36.   X, Y, Z
  37. };
  38. /* simple way to extend a point to build shadow volume */
  39. void
  40. extend(GLfloat new[3], GLfloat light[3], GLfloat vertex[3], GLfloat t)
  41. {
  42.   GLfloat delta[3];
  43.   delta[X] = vertex[X] - light[X];
  44.   delta[Y] = vertex[Y] - light[Y];
  45.   delta[Z] = vertex[Z] - light[Z];
  46.   new[X] = light[X] + delta[X] * t;
  47.   new[Y] = light[Y] + delta[Y] * t;
  48.   new[Z] = light[Z] + delta[Z] * t;
  49. }
  50. /* Create a shadow volume in a display list */
  51. /* XXX light should have 4 compoents */
  52. void
  53. makeShadowVolume(ShadObj * shadower, GLfloat light[3],
  54.   GLfloat t, GLint dlist)
  55. {
  56.   int i;
  57.   GLfloat newv[3];
  58.   glNewList(dlist, GL_COMPILE);
  59.   glDisable(GL_LIGHTING);
  60.   glBegin(GL_QUADS);
  61.   /* for debugging */
  62.   glColor3f(.2f, .8f, .4f);
  63.   for (i = 0; i < shadower->n; i++) {
  64.     glVertex3fv(&shadower->verticies[i * 3]);
  65.     extend(newv, light, &shadower->verticies[i * 3], t);
  66.     glVertex3fv(newv);
  67.     extend(newv, light, &shadower->verticies[((i + 1) % shadower->n) * 3],
  68.       t);
  69.     glVertex3fv(newv);
  70.     glVertex3fv(&shadower->verticies[((i + 1) % shadower->n) * 3]);
  71.   }
  72.   glEnd();
  73.   glEnable(GL_LIGHTING);
  74.   glEndList();
  75. }
  76. void 
  77. sphere(void)
  78. {
  79.   glPushMatrix();
  80.   glTranslatef(60.f, -50.f, -360.f);
  81.   glCallList(SPHERE);
  82.   glPopMatrix();
  83. }
  84. void 
  85. cone(void)
  86. {
  87.   glPushMatrix();
  88.   glTranslatef(-40.f, -40.f, -400.f);
  89.   glCallList(CONE);
  90.   glPopMatrix();
  91. }
  92. enum {
  93.   NONE, NOLIGHT, VOLUME, SHADOW
  94. };
  95. int rendermode = NONE;
  96. void
  97. menu(int mode)
  98. {
  99.   rendermode = mode;
  100.   glutPostRedisplay();
  101. }
  102. GLfloat leftwallshadow[4][4];
  103. GLfloat floorshadow[4][4];
  104. GLfloat lightpos[] =
  105. {50.f, 50.f, -340.f, 1.f};
  106. /* render while jittering the shadows */
  107. void
  108. render(ShadObj * obj)
  109. {
  110.   static GLfloat shad_mat[] =
  111.   {1.f, .1f, .1f, 1.f};
  112.   GLfloat *v;           /* vertex pointer */
  113.   int i;
  114.   /* material properties for objects in scene */
  115.   static GLfloat wall_mat[] =
  116.   {1.f, 1.f, 1.f, 1.f};
  117.   /* Note: wall verticies are ordered so they are all front facing this lets
  118.      me do back face culling to speed things up.  */
  119.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  120.   /* floor */
  121.   /* make the floor textured */
  122.   glEnable(GL_TEXTURE_2D);
  123.   /* Since we want to turn texturing on for floor only, we have to make floor 
  124.      a separate glBegin()/glEnd() sequence. You can't turn texturing on and
  125.      off between begin and end calls */
  126.   glBegin(GL_QUADS);
  127.   glNormal3f(0.f, 1.f, 0.f);
  128.   glTexCoord2i(0, 0);
  129.   glVertex3f(-100.f, -100.f, -320.f);
  130.   glTexCoord2i(1, 0);
  131.   glVertex3f(100.f, -100.f, -320.f);
  132.   glTexCoord2i(1, 1);
  133.   glVertex3f(100.f, -100.f, -520.f);
  134.   glTexCoord2i(0, 1);
  135.   glVertex3f(-100.f, -100.f, -520.f);
  136.   glEnd();
  137.   glDisable(GL_TEXTURE_2D);
  138.   /* walls */
  139.   glBegin(GL_QUADS);
  140.   /* left wall */
  141.   glNormal3f(1.f, 0.f, 0.f);
  142.   glVertex3f(-100.f, -100.f, -320.f);
  143.   glVertex3f(-100.f, -100.f, -520.f);
  144.   glVertex3f(-100.f, 100.f, -520.f);
  145.   glVertex3f(-100.f, 100.f, -320.f);
  146.   /* right wall */
  147.   glNormal3f(-1.f, 0.f, 0.f);
  148.   glVertex3f(100.f, -100.f, -320.f);
  149.   glVertex3f(100.f, 100.f, -320.f);
  150.   glVertex3f(100.f, 100.f, -520.f);
  151.   glVertex3f(100.f, -100.f, -520.f);
  152.   /* ceiling */
  153.   glNormal3f(0.f, -1.f, 0.f);
  154.   glVertex3f(-100.f, 100.f, -320.f);
  155.   glVertex3f(-100.f, 100.f, -520.f);
  156.   glVertex3f(100.f, 100.f, -520.f);
  157.   glVertex3f(100.f, 100.f, -320.f);
  158.   /* back wall */
  159.   glNormal3f(0.f, 0.f, 1.f);
  160.   glVertex3f(-100.f, -100.f, -520.f);
  161.   glVertex3f(100.f, -100.f, -520.f);
  162.   glVertex3f(100.f, 100.f, -520.f);
  163.   glVertex3f(-100.f, 100.f, -520.f);
  164.   glEnd();
  165.   cone();
  166.   sphere();
  167.   glCallList(LIGHT);
  168.   /* draw shadowing object */
  169.   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, shad_mat);
  170.   glBegin(GL_POLYGON);
  171.   glNormal3fv(obj->normal);
  172.   for (v = obj->verticies, i = 0; i < obj->n; i++) {
  173.     glVertex3fv(v);
  174.     v += 3;
  175.   }
  176.   glEnd();
  177. }
  178. void
  179. redraw(void)
  180. {
  181.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  182.   switch (rendermode) {
  183.   case NONE:
  184.     render(&shadower);
  185.     break;
  186.   case NOLIGHT:
  187.     glDisable(GL_LIGHT0);
  188.     render(&shadower);
  189.     glEnable(GL_LIGHT0);
  190.     break;
  191.   case VOLUME:
  192.     render(&shadower);
  193.     glCallList(SHADOWVOL);
  194.     break;
  195.   case SHADOW:
  196.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  197.     render(&shadower);  /* render scene in depth buffer */
  198.     glEnable(GL_STENCIL_TEST);
  199.     glDepthMask(GL_FALSE);
  200.     glStencilFunc(GL_ALWAYS, 0, 0);
  201.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  202.     glCullFace(GL_BACK);  /* increment using front face of shadow volume */
  203.     glCallList(SHADOWVOL);
  204.     glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
  205.     glCullFace(GL_FRONT);  /* increment using front face of shadow volume */
  206.     glCallList(SHADOWVOL);
  207.     glDepthMask(GL_TRUE);
  208.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  209.     glCullFace(GL_BACK);
  210.     glDepthFunc(GL_LEQUAL);
  211.     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  212.     glStencilFunc(GL_EQUAL, 1, 1);  /* draw shadowed part */
  213.     glDisable(GL_LIGHT0);
  214.     render(&shadower);
  215.     glStencilFunc(GL_EQUAL, 0, 1);  /* draw lit part */
  216.     glEnable(GL_LIGHT0);
  217.     render(&shadower);
  218.     glDepthFunc(GL_LESS);
  219.     glDisable(GL_STENCIL_TEST);
  220.     break;
  221.   }
  222.   glutSwapBuffers();    /* high end machines may need this */
  223. }
  224. /* ARGSUSED1 */
  225. void 
  226. key(unsigned char key, int x, int y)
  227. {
  228.   if (key == '33')
  229.     exit(0);
  230. }
  231. const int TEXDIM = 256;
  232. /* Parse arguments, and set up interface between OpenGL and window system */
  233. int
  234. main(int argc, char *argv[])
  235. {
  236.   GLfloat *tex;
  237.   GLUquadricObj *sphere, *cone, *base;
  238.   static GLfloat sphere_mat[] =
  239.   {1.f, .5f, 0.f, 1.f};
  240.   static GLfloat cone_mat[] =
  241.   {0.f, .5f, 1.f, 1.f};
  242.   glutInit(&argc, argv);
  243.   glutInitWindowSize(512, 512);
  244.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE);
  245.   (void) glutCreateWindow("shadow volumes");
  246.   glutDisplayFunc(redraw);
  247.   glutKeyboardFunc(key);
  248.   glutCreateMenu(menu);
  249.   glutAddMenuEntry("No Shadows", NONE);
  250.   glutAddMenuEntry("No Light", NOLIGHT);
  251.   glutAddMenuEntry("Show Volume", VOLUME);
  252.   glutAddMenuEntry("Shadows", SHADOW);
  253.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  254.   /* draw a perspective scene */
  255.   glMatrixMode(GL_PROJECTION);
  256.   glFrustum(-100., 100., -100., 100., 320., 640.);
  257.   glMatrixMode(GL_MODELVIEW);
  258.   /* turn on features */
  259.   glEnable(GL_DEPTH_TEST);
  260.   glEnable(GL_LIGHTING);
  261.   glEnable(GL_LIGHT0);
  262.   glEnable(GL_CULL_FACE);
  263.   /* place light 0 in the right place */
  264.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  265.   /* remove back faces to speed things up */
  266.   glCullFace(GL_BACK);
  267.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  268.   /* make display lists for sphere and cone; for efficiency */
  269.   glNewList(SPHERE, GL_COMPILE);
  270.   sphere = gluNewQuadric();
  271.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  272.   gluSphere(sphere, 20.f, 20, 20);
  273.   gluDeleteQuadric(sphere);
  274.   glEndList();
  275.   glNewList(CONE, GL_COMPILE);
  276.   cone = gluNewQuadric();
  277.   base = gluNewQuadric();
  278.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  279.   glRotatef(-90.f, 1.f, 0.f, 0.f);
  280.   gluDisk(base, 0., 20., 20, 1);
  281.   gluCylinder(cone, 20., 0., 60., 20, 20);
  282.   gluDeleteQuadric(cone);
  283.   gluDeleteQuadric(base);
  284.   glEndList();
  285.   glNewList(LIGHT, GL_COMPILE);
  286.   sphere = gluNewQuadric();
  287.   glPushMatrix();
  288.   glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  289.   glDisable(GL_LIGHTING);
  290.   glColor3f(.9f, .9f, .6f);
  291.   gluSphere(sphere, 5.f, 20, 20);
  292.   glEnable(GL_LIGHTING);
  293.   glPopMatrix();
  294.   gluDeleteQuadric(sphere);
  295.   glEndList();
  296.   /* load pattern for current 2d texture */
  297.   tex = make_texture(TEXDIM, TEXDIM);
  298.   glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  299.   free(tex);
  300.   shadower.verticies = shadVerts;
  301.   shadower.normal = shadNormal;
  302.   shadower.n = sizeof(shadVerts) / (3 * sizeof(GLfloat));
  303.   makeShadowVolume(&shadower, lightpos, 10.f, SHADOWVOL);
  304.   glutMainLoop();
  305.   return 0;             /* ANSI C requires main to return int. */
  306. }