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

GIS编程

开发平台:

Visual C++

  1. /* softshadow2.c - by Simon Hui, 3Dfx Interactive */
  2. /* Soft shadows using a shadow texture per polygon.  Based on an algorithm   */
  3. /* described by Paul Heckbert and Michael Herf of CMU; see their web site    */
  4. /* http://www.cs.cmu.edu/ph/shadow.html for details.                         */
  5. /*                                                                           */
  6. /* This program shows two methods of using precomputed, per-polygon textures */
  7. /* to display soft shadows.  The first method is a simplified version of     */
  8. /* Heckbert and Herf's algorithm: for each polygon a texture is created that */
  9. /* encodes the full radiance, including illumination and shadows, of the     */
  10. /* polygon. The texture is created in a preprocessing step by rendering the  */
  11. /* entire scene onto the polygon from the point of view of the light. The    */
  12. /* advantage of this method is that the scene can be rerendered quickly (if  */
  13. /* only the eye moves and the scene is static), since all lighting effects   */
  14. /* have been precomputed and encoded in the texture. This method requires    */
  15. /* GL_RGB textures.                                                          */
  16. /*                                                                           */
  17. /* The second method uses the texture as an occlusion map: the texels        */
  18. /* encode only the amount of occlusion by shadowing objects, not the full    */
  19. /* radiance.  The texture is then used to modulate the lighting of the       */
  20. /* polygon during the rendering pass.  This has the disadvantage of          */
  21. /* requiring OpenGL lighting during scene rendering, but it does retain some */
  22. /* of the benefit of the first method in that all shadow effects are         */
  23. /* precomputed. This method requires GL_LUMINANCE textures.                  */
  24. /*                                                                           */
  25. /* The reason for including the occlusion map method is that some OpenGL     */
  26. /* implementations support GL_RGB textures with low color resolution,        */
  27. /* resulting in noticeable banding when using radiance maps.  However, these */
  28. /* implementations may support a higher color resolution for GL_LUMINANCE    */
  29. /* textures.                                                                 */
  30. /*                                                                           */
  31. /* To use occlusion maps instead of rediance maps, run this program with     */
  32. /* "-o" on the command line.                                                 */
  33. #include <GL/glut.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <math.h>
  37. #if !defined(GL_VERSION_1_1) && !defined(GL_VERSION_1_2)
  38. #define glBindTexture glBindTextureEXT
  39. #define glCopyTexImage2D glCopyTexImage2DEXT
  40. #endif
  41. /* whether to use radiance maps or occlusion maps */
  42. static GLboolean radianceMap = GL_TRUE;
  43. static GLint winxsize = 480, winysize = 480;
  44. static GLint texxsize = 128, texysize = 128;
  45. /* texture object names */
  46. const GLuint floorTexture = 1;
  47. const GLuint shadowTextures = 2;
  48. static GLfloat lightpos[4] = { 70.f, 70.f, -320.f, 1.f };
  49. /* number of shadow textures to make and use */
  50. static GLint numShadowTex;
  51. /* list of polygons that have shadow textures */
  52. GLfloat pts[][4][3] = {
  53.   /* floor */
  54.   -100.f, -100.f, -320.f,
  55.   -100.f, -100.f, -520.f,
  56.    100.f, -100.f, -320.f,
  57.    100.f, -100.f, -520.f,
  58.   /* left wall */
  59.   -100.f, -100.f, -320.f,
  60.   -100.f,  100.f, -320.f,
  61.   -100.f, -100.f, -520.f,
  62.   -100.f,  100.f, -520.f,
  63.   /* back wall */
  64.   -100.f, -100.f, -520.f,
  65.   -100.f,  100.f, -520.f,
  66.    100.f, -100.f, -520.f,
  67.    100.f,  100.f, -520.f,
  68.   /* right wall */
  69.    100.f, -100.f, -520.f,
  70.    100.f,  100.f, -520.f,
  71.    100.f, -100.f, -320.f,
  72.    100.f,  100.f, -320.f,
  73.   /* ceiling */
  74.   -100.f,  100.f, -520.f,
  75.   -100.f,  100.f, -320.f,
  76.    100.f,  100.f, -520.f,
  77.    100.f,  100.f, -320.f,
  78.   /* blue panel */
  79.    -60.f,  -40.f, -400.f,
  80.    -60.f,   70.f, -400.f,
  81.    -30.f,  -40.f, -480.f,
  82.    -30.f,   70.f, -480.f,
  83.   /* yellow panel */
  84.    -40.f,  -50.f, -400.f,
  85.    -40.f,   50.f, -400.f,
  86.    -10.f,  -50.f, -450.f,
  87.    -10.f,   50.f, -450.f,
  88.   /* red panel */
  89.    -20.f,  -60.f, -400.f,
  90.    -20.f,   30.f, -400.f,
  91.     10.f,  -60.f, -420.f,
  92.     10.f,   30.f, -420.f,
  93.   /* green panel */
  94.      0.f,  -70.f, -400.f,
  95.      0.f,   10.f, -400.f,
  96.     30.f,  -70.f, -395.f,
  97.     30.f,   10.f, -395.f,
  98. };
  99. GLfloat materials[][4] = {
  100.   1.0f, 1.0f, 1.0f, 1.0f, /* floor        */
  101.   1.0f, 1.0f, 1.0f, 1.0f, /* left wall    */
  102.   1.0f, 1.0f, 1.0f, 1.0f, /* back wall    */
  103.   1.0f, 1.0f, 1.0f, 1.0f, /* right wall   */
  104.   1.0f, 1.0f, 1.0f, 1.0f, /* ceiling      */
  105.   0.2f, 0.5f, 1.0f, 1.0f, /* blue panel   */
  106.   1.0f, 0.6f, 0.0f, 1.0f, /* yellow panel */
  107.   1.0f, 0.2f, 0.2f, 1.0f, /* red panel    */
  108.   0.3f, 0.9f, 0.6f, 1.0f, /* green panel  */
  109. };
  110. /* some simple vector utility routines */
  111. void
  112. vcopy(GLfloat a[3], GLfloat b[3])
  113. {
  114.   b[0] = a[0];
  115.   b[1] = a[1];
  116.   b[2] = a[2];
  117. }
  118. void
  119. vnormalize(GLfloat v[3])
  120. {
  121.   float m = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  122.   v[0] /= m;
  123.   v[1] /= m;
  124.   v[2] /= m;
  125. }
  126. void
  127. vadd(GLfloat a[3], GLfloat b[3], GLfloat c[3])
  128. {
  129.   c[0] = a[0] + b[0];
  130.   c[1] = a[1] + b[1];
  131.   c[2] = a[2] + b[2];
  132. }
  133. void
  134. vsub(GLfloat a[3], GLfloat b[3], GLfloat c[3])
  135. {
  136.   c[0] = a[0] - b[0];
  137.   c[1] = a[1] - b[1];
  138.   c[2] = a[2] - b[2];
  139. }
  140. void
  141. vcross(GLfloat a[3], GLfloat b[3], GLfloat c[3])
  142. {
  143.   c[0] = a[1] * b[2] - a[2] * b[1];
  144.   c[1] = -(a[0] * b[2] - a[2] * b[0]);
  145.   c[2] = a[0] * b[1] - a[1] * b[0];
  146. }
  147. float
  148. vdot(GLfloat a[3], GLfloat b[3])
  149. {
  150.   return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
  151. }
  152. void
  153. findNormal(GLfloat pts[][3], GLfloat normal[3]) {
  154.   GLfloat a[3], b[3];
  155.   
  156.   vsub(pts[1], pts[0], a);
  157.   vsub(pts[2], pts[0], b);
  158.   vcross(b, a, normal);
  159.   vnormalize(normal);
  160. }
  161. static GLfloat origin[4] = { 0.f, 0.f, 0.f, 1.f };
  162. static GLfloat black[4] = { 0.f, 0.f, 0.f, 1.f };
  163. static GLfloat ambient[4] = { 0.2f, 0.2f, 0.2f, 1.f };
  164. void
  165. make_shadow_texture(int index, GLfloat eyept[3], GLfloat dx, GLfloat dy)
  166. {
  167.   GLfloat xaxis[3], yaxis[3], zaxis[3];
  168.   GLfloat cov[3]; /* center of view */
  169.   GLfloat pte[3]; /* plane to eye */
  170.   GLfloat eye[3];
  171.   GLfloat tmp[3], normal[3], dist;
  172.   GLfloat (*qpts)[3] = pts[index];
  173.   GLfloat left, right, bottom, top;
  174.   GLfloat znear = 10.f, zfar = 600.f;
  175.   GLint n;
  176.   /* For simplicity, we don't compute the transformation matrix described */
  177.   /* in Heckbert and Herf's paper.  The transformation and frustum used   */
  178.   /* here is much simpler.                                                */
  179.   vcopy(eyept, eye);
  180.   vsub(qpts[1], qpts[0], yaxis);
  181.   vsub(qpts[2], qpts[0], xaxis);
  182.   vcross(yaxis, xaxis, zaxis);
  183.   vnormalize(zaxis);
  184.   vnormalize(xaxis); /* x-axis of eye coord system, in object space */
  185.   vnormalize(yaxis); /* y-axis of eye coord system, in object space */
  186.   /* jitter the eyepoint */
  187.   eye[0] += xaxis[0] * dx;
  188.   eye[1] += xaxis[1] * dx;
  189.   eye[2] += xaxis[2] * dx;
  190.   eye[0] += yaxis[0] * dy;
  191.   eye[1] += yaxis[1] * dy;
  192.   eye[2] += yaxis[2] * dy;
  193.   /* center of view is just eyepoint offset in direction of normal */ 
  194.   vadd(eye, zaxis, cov);
  195.   /* set up viewing matrix */
  196.   glPushMatrix();
  197.   glLoadIdentity();
  198.   gluLookAt(eye[0], eye[1], eye[2],
  199.     cov[0], cov[1], cov[2],
  200.     yaxis[0], yaxis[1], yaxis[2]);
  201.   /* compute a frustum that just encloses the polygon */
  202.   vsub(qpts[0], eye, tmp); /* from eye to 0th vertex */
  203.   left = vdot(tmp, xaxis);
  204.   vsub(qpts[2], eye, tmp); /* from eye to 2nd vertex */
  205.   right = vdot(tmp, xaxis);
  206.   vsub(qpts[0], eye, tmp); /* from eye to 0th vertex */
  207.   bottom = vdot(tmp, yaxis);
  208.   vsub(qpts[1], eye, tmp); /* from eye to 1st vertex */
  209.   top = vdot(tmp, yaxis);
  210.   /* scale the frustum values based on the distance to the polygon */
  211.   vsub(qpts[0], eye, pte);
  212.   dist = fabs(vdot(zaxis, pte));
  213.   left *= (znear/dist);
  214.   right *= (znear/dist);
  215.   bottom *= (znear/dist);
  216.   top *= (znear/dist);
  217.   glMatrixMode(GL_PROJECTION);
  218.   glPushMatrix();
  219.   glLoadIdentity();
  220.   glFrustum(left, right, bottom, top, znear, zfar);
  221.   glMatrixMode(GL_MODELVIEW);
  222.   if (radianceMap) {
  223.     glEnable(GL_LIGHTING);
  224.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, materials[index]);
  225.   } else {
  226.     glDisable(GL_LIGHTING);
  227.   }
  228.   glDisable(GL_TEXTURE_2D);
  229.   for (n=0; n < numShadowTex; n++) {
  230.     qpts = pts[n];
  231.     if (radianceMap) {
  232.       glColor3f(1.f, 1.f, 1.f);
  233.       findNormal(qpts, normal);
  234.       glNormal3fv(normal);
  235.       if (n == index) {
  236. /* draw this poly with ambient and diffuse lighting */
  237. glEnable(GL_LIGHT0);
  238.       } else {
  239. /* draw other polys with ambient lighting only */
  240. glDisable(GL_LIGHT0);
  241.       }
  242.     } else {
  243.       if (n == index) {
  244. /* this poly has full intensity, no occlusion */
  245. glColor3f(1.f, 1.f, 1.f);
  246.       } else {
  247. /* all other polys just occlude the light */
  248. glColor3f(0.f, 0.f, 0.f);
  249.       }
  250.     }
  251.     glBegin(GL_TRIANGLE_STRIP);
  252.     glVertex3fv(qpts[0]);
  253.     glVertex3fv(qpts[1]);
  254.     glVertex3fv(qpts[2]);
  255.     glVertex3fv(qpts[3]);
  256.     glEnd();
  257.   }
  258.   glPopMatrix();
  259.   glMatrixMode(GL_PROJECTION);
  260.   glPopMatrix();
  261.   glMatrixMode(GL_MODELVIEW);
  262. }
  263. void make_all_shadow_textures(float eye[3], float dx, float dy) {
  264.   GLint texPerRow;
  265.   GLint n;
  266.   GLfloat x, y;
  267.   texPerRow = (winxsize / texxsize);
  268.   for (n=0; n < numShadowTex; n++) {
  269.     y = (n / texPerRow) * texysize;
  270.     x = (n % texPerRow) * texxsize;
  271.     glViewport(x, y, texxsize, texysize);
  272.     make_shadow_texture(n, eye, dx, dy);
  273.   }
  274.   glViewport(0, 0, winxsize, winysize);
  275. }
  276. void store_all_shadow_textures(void) {
  277.   GLint texPerRow;
  278.   GLint n, x, y;
  279.   GLubyte *texbuf;
  280.   
  281.   texbuf = (GLubyte *) malloc(texxsize * texysize * sizeof(int));
  282.   /* how many shadow textures can fit in the window */
  283.   texPerRow = (winxsize / texxsize);
  284.   for (n=0; n < numShadowTex; n++) {
  285.     GLenum format;
  286.     x = (n % texPerRow) * texxsize;
  287.     y = (n / texPerRow) * texysize;
  288.     glBindTexture(GL_TEXTURE_2D, shadowTextures + n);
  289.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  290.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  291.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  292.     if (radianceMap) {
  293.       format = GL_RGB;
  294.     } else {
  295.       format = GL_LUMINANCE;
  296.     }
  297.     glCopyTexImage2D(GL_TEXTURE_2D, 0, format, x, y, texxsize, texysize, 0);
  298.   }
  299.   free(texbuf);
  300. }
  301. /* menu choices */
  302. enum {
  303.   NOSHADOWS, SOFTSHADOWS, HARDSHADOWS, VIEWTEXTURE, VIEWSCENE, QUIT
  304. };
  305. GLint shadowMode = HARDSHADOWS;
  306. GLboolean viewTextures = GL_FALSE;
  307. void
  308. redraw(void)
  309. {
  310.   GLint n;
  311.   GLfloat normal[3];
  312.   GLfloat (*qpts)[3];
  313.   glPushMatrix();
  314.   glLoadIdentity();
  315.   if (radianceMap && (shadowMode != NOSHADOWS)) {
  316.     glLightfv(GL_LIGHT0, GL_POSITION, origin);
  317.   } else {
  318.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  319.   }
  320.   glPopMatrix();
  321.   if (shadowMode == SOFTSHADOWS) {
  322.     GLfloat jitterSize;
  323.     GLfloat dx, dy;
  324.     GLint numSteps, i, j;
  325.     /* size of the area to jitter the light in */
  326.     jitterSize = 15.0;
  327.     /* number of times along x and y to jitter */
  328.     numSteps = 5;
  329.     glClear(GL_ACCUM_BUFFER_BIT);
  330.     for (j=0; j < numSteps; j++) {
  331.       for (i=0; i < numSteps; i++) {
  332. /* compute jitter amount, centering the jitter steps around zero */
  333. dx = (i - (numSteps - 1.0) / 2.0) / (numSteps - 1.0) * jitterSize;
  334. dy = (j - (numSteps - 1.0) / 2.0) / (numSteps - 1.0) * jitterSize;
  335. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  336. make_all_shadow_textures(lightpos, dx, dy);
  337. glAccum(GL_ACCUM, 1.0 / (numSteps * numSteps));
  338. if (viewTextures) {
  339.   glutSwapBuffers();
  340. }
  341.       }
  342.     }
  343.     glAccum(GL_RETURN, 1.0);
  344.     store_all_shadow_textures();
  345.   } else if (shadowMode == HARDSHADOWS) {
  346.     /* make shadow textures from just one frame */
  347.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
  348.     make_all_shadow_textures(lightpos, 0, 0);
  349.     store_all_shadow_textures();
  350.     if (viewTextures) {
  351.       glutSwapBuffers();
  352.     }
  353.   }
  354.   if (viewTextures) {
  355.     glutSwapBuffers();
  356.     return;
  357.   }
  358.   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  359.   glLoadIdentity();
  360.   glColor3f(1.f, 1.f, 1.f);
  361.   if (shadowMode == NOSHADOWS) {
  362.     glEnable(GL_LIGHTING);
  363.     glEnable(GL_LIGHT0); 
  364.     glDisable(GL_TEXTURE_2D);
  365.     for (n=0; n < numShadowTex; n++) {
  366.       qpts = pts[n];
  367.       findNormal(qpts, normal);
  368.       glNormal3fv(normal);
  369.       glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, materials[n]);
  370.       glBegin(GL_TRIANGLE_STRIP);
  371.       glTexCoord2f(0,0); glVertex3fv(qpts[0]);
  372.       glTexCoord2f(0,1); glVertex3fv(qpts[1]);
  373.       glTexCoord2f(1,0); glVertex3fv(qpts[2]);
  374.       glTexCoord2f(1,1); glVertex3fv(qpts[3]);
  375.       glEnd();
  376.     }
  377.   } else {
  378.     glEnable(GL_TEXTURE_2D);
  379.     if (radianceMap) {
  380.       glDisable(GL_LIGHTING);
  381.       for (n=0; n < numShadowTex; n++) {
  382. qpts = pts[n];
  383. glBindTexture(GL_TEXTURE_2D, shadowTextures + n);
  384. glBegin(GL_TRIANGLE_STRIP);
  385. glTexCoord2f(0,0); glVertex3fv(qpts[0]);
  386. glTexCoord2f(0,1); glVertex3fv(qpts[1]);
  387. glTexCoord2f(1,0); glVertex3fv(qpts[2]);
  388. glTexCoord2f(1,1); glVertex3fv(qpts[3]);
  389. glEnd();
  390.       }
  391.     } else {
  392.       /* Unfortunately, using the texture as an occlusion map requires two */
  393.       /* passes: one in which the occlusion map modulates the diffuse      */
  394.       /* lighting, and one in which the ambient lighting is added in. It's */
  395.       /* incorrect to modulate the ambient lighting, but if the result is  */
  396.       /* acceptable to you, you can include it in the first pass and       */
  397.       /* omit the second pass. */
  398.       /* draw only with diffuse light, modulating it with the texture */
  399.       glEnable(GL_LIGHTING);
  400.       glEnable(GL_LIGHT0); 
  401.       glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
  402.       for (n=0; n < numShadowTex; n++) {
  403. qpts = pts[n];
  404. findNormal(qpts, normal);
  405. glNormal3fv(normal);
  406. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, materials[n]);
  407. glBindTexture(GL_TEXTURE_2D, shadowTextures + n);
  408. glBegin(GL_TRIANGLE_STRIP);
  409. glTexCoord2f(0,0); glVertex3fv(qpts[0]);
  410. glTexCoord2f(0,1); glVertex3fv(qpts[1]);
  411. glTexCoord2f(1,0); glVertex3fv(qpts[2]);
  412. glTexCoord2f(1,1); glVertex3fv(qpts[3]);
  413. glEnd();
  414.       }
  415.       /* add in the ambient lighting */
  416.       glDisable(GL_LIGHTING);
  417.       glDisable(GL_TEXTURE_2D);
  418.       glEnable(GL_BLEND);
  419.       glBlendFunc(GL_ONE, GL_ONE);
  420.       glDepthFunc(GL_LEQUAL);
  421.       for (n=0; n < numShadowTex; n++) {
  422. qpts = pts[n];
  423. glColor4f(ambient[0] * materials[n][0],
  424.   ambient[1] * materials[n][1],
  425.   ambient[2] * materials[n][2],
  426.   ambient[3] * materials[n][3]);
  427. glBegin(GL_TRIANGLE_STRIP);
  428. glTexCoord2f(0,0); glVertex3fv(qpts[0]);
  429. glTexCoord2f(0,1); glVertex3fv(qpts[1]);
  430. glTexCoord2f(1,0); glVertex3fv(qpts[2]);
  431. glTexCoord2f(1,1); glVertex3fv(qpts[3]);
  432. glEnd();
  433.       }
  434.       /* restore the ambient colors to their defaults */
  435.       glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
  436.     }
  437.   }
  438.   /* blend in the checkerboard floor */
  439.   glEnable(GL_BLEND);
  440.   glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  441.   glDepthFunc(GL_LEQUAL);
  442.   glEnable(GL_TEXTURE_2D);
  443.   glBindTexture(GL_TEXTURE_2D, floorTexture);
  444.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, materials[0]);
  445.   glTranslatef(0.0f, 0.05f, 0.0f);
  446.   glColor3f(1.f, 1.f, 1.f);
  447.   glBegin(GL_TRIANGLE_STRIP);
  448.   glNormal3f(0.f, 1.f, 0.f);
  449.   glTexCoord2f(0.f, 0.f); glVertex3fv(pts[0][0]);
  450.   glTexCoord2f(0.f, 1.f); glVertex3fv(pts[0][1]);
  451.   glTexCoord2f(1.f, 0.f); glVertex3fv(pts[0][2]);
  452.   glTexCoord2f(1.f, 1.f); glVertex3fv(pts[0][3]);
  453.   glEnd();
  454.   /* undo some state settings that we did above */
  455.   glDisable(GL_BLEND);
  456.   glDisable(GL_TEXTURE_2D);
  457.   glDepthFunc(GL_LESS);
  458.   glTranslatef(0.0f, -0.05f, 0.0f);
  459. glutSwapBuffers();
  460. }
  461. void
  462. menu(int mode)
  463. {
  464.   switch (mode) {
  465.   case NOSHADOWS:
  466.   case SOFTSHADOWS:
  467.   case HARDSHADOWS:
  468.     shadowMode = mode;
  469.     break;
  470.   case VIEWTEXTURE:
  471.     viewTextures = GL_TRUE;
  472.     break;
  473.   case VIEWSCENE:
  474.     viewTextures = GL_FALSE;
  475.     break;
  476.   case QUIT:
  477.     exit(0);
  478.   }
  479.   glutPostRedisplay();
  480. }
  481. /* Make a checkerboard texture for the floor. */
  482. GLfloat *
  483. make_texture(int maxs, int maxt)
  484. {
  485.   GLint s, t;
  486.   static GLfloat *texture;
  487.   texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat));
  488.   for (t = 0; t < maxt; t++) {
  489.     for (s = 0; s < maxs; s++) {
  490.       texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  491.     }
  492.   }
  493.   return texture;
  494. }
  495. /* ARGSUSED1 */
  496. void
  497. keyboard(unsigned char key, int x, int y)
  498. {
  499.   if (key == 27)  /* ESC */
  500.     exit(0);
  501. }
  502. int
  503. main(int argc, char *argv[])
  504. {
  505.   GLfloat *tex;
  506.   GLint i;
  507.   for (i = 1; i < argc; ++i) {
  508.     if (!strcmp("-o", argv[i])) {
  509.       /* use textures as occlusion maps rather than radiance maps */
  510.       radianceMap = GL_FALSE;
  511.     }
  512.   }
  513.   glutInit(&argc, argv);
  514.   glutInitWindowSize(winxsize, winysize);
  515.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_ACCUM | GLUT_SINGLE);
  516.   (void) glutCreateWindow("soft shadows");
  517.   glutDisplayFunc(redraw);
  518.   glutKeyboardFunc(keyboard);
  519.   glutCreateMenu(menu);
  520.   glutAddMenuEntry("No Shadows", NOSHADOWS);
  521.   glutAddMenuEntry("Soft Shadows", SOFTSHADOWS);
  522.   glutAddMenuEntry("Hard Shadows", HARDSHADOWS);
  523.   glutAddMenuEntry("View Textures", VIEWTEXTURE);
  524.   glutAddMenuEntry("View Scene", VIEWSCENE);
  525.   glutAddMenuEntry("Quit", QUIT);
  526.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  527.   /* set up perspective projection */
  528.   glMatrixMode(GL_PROJECTION);
  529.   glFrustum(-30., 30., -30., 30., 100., 640.);
  530.   glMatrixMode(GL_MODELVIEW);
  531.   /* turn on features */
  532.   glEnable(GL_DEPTH_TEST);
  533.   glEnable(GL_LIGHTING);
  534.   glEnable(GL_LIGHT0);
  535.   glCullFace(GL_BACK);
  536.   glLightfv(GL_LIGHT0, GL_AMBIENT, black);
  537.   /* number of shadow textures to make */
  538.   numShadowTex = sizeof(pts) / sizeof(pts[0]);
  539.   tex = make_texture(texxsize, texysize);
  540.   glBindTexture(GL_TEXTURE_2D, floorTexture);
  541.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  542.   glTexImage2D(GL_TEXTURE_2D, 0, 1, texxsize, texysize, 0, GL_RED, GL_FLOAT, 
  543.        tex);
  544.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  545.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  546.   free(tex);
  547.   glutMainLoop();
  548.   return 0;             /* ANSI C requires main to return int. */
  549. }