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

GIS编程

开发平台:

Visual C++

  1. /* softshadow.c - by Tom McReynolds, SGI */
  2. /* Using the accumulation buffer for soft shadows. */
  3. #include <GL/glut.h>
  4. #include <stdlib.h>
  5. /* Demonstrate the use of accumulation buffer to create soft shadows */
  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, LEFTWALL, FLOOR
  22. };
  23. /* create a matrix that will project the desired shadow */
  24. void
  25. shadowmatrix(GLfloat shadowMat[4][4],
  26.   GLfloat groundplane[4],
  27.   GLfloat lightpos[4])
  28. {
  29.   GLfloat dot;
  30.   /* find dot product between light position vector and ground plane normal */
  31.   dot = groundplane[0] * lightpos[0] +
  32.     groundplane[1] * lightpos[1] +
  33.     groundplane[2] * lightpos[2] +
  34.     groundplane[3] * lightpos[3];
  35.   shadowMat[0][0] = dot - lightpos[0] * groundplane[0];
  36.   shadowMat[1][0] = 0.f - lightpos[0] * groundplane[1];
  37.   shadowMat[2][0] = 0.f - lightpos[0] * groundplane[2];
  38.   shadowMat[3][0] = 0.f - lightpos[0] * groundplane[3];
  39.   shadowMat[0][1] = 0.f - lightpos[1] * groundplane[0];
  40.   shadowMat[1][1] = dot - lightpos[1] * groundplane[1];
  41.   shadowMat[2][1] = 0.f - lightpos[1] * groundplane[2];
  42.   shadowMat[3][1] = 0.f - lightpos[1] * groundplane[3];
  43.   shadowMat[0][2] = 0.f - lightpos[2] * groundplane[0];
  44.   shadowMat[1][2] = 0.f - lightpos[2] * groundplane[1];
  45.   shadowMat[2][2] = dot - lightpos[2] * groundplane[2];
  46.   shadowMat[3][2] = 0.f - lightpos[2] * groundplane[3];
  47.   shadowMat[0][3] = 0.f - lightpos[3] * groundplane[0];
  48.   shadowMat[1][3] = 0.f - lightpos[3] * groundplane[1];
  49.   shadowMat[2][3] = 0.f - lightpos[3] * groundplane[2];
  50.   shadowMat[3][3] = dot - lightpos[3] * groundplane[3];
  51. }
  52. enum {
  53.   X, Y, Z
  54. };
  55. enum {
  56.   A, B, C, D
  57. };
  58. /* find the plane equation given 3 points */
  59. void
  60. findplane(GLfloat plane[4],
  61.   GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
  62. {
  63.   GLfloat vec0[3], vec1[3];
  64.   /* need 2 vectors to find cross product */
  65.   vec0[X] = v1[X] - v0[X];
  66.   vec0[Y] = v1[Y] - v0[Y];
  67.   vec0[Z] = v1[Z] - v0[Z];
  68.   vec1[X] = v2[X] - v0[X];
  69.   vec1[Y] = v2[Y] - v0[Y];
  70.   vec1[Z] = v2[Z] - v0[Z];
  71.   /* find cross product to get A, B, and C of plane equation */
  72.   plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
  73.   plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
  74.   plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
  75.   plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
  76. }
  77. void 
  78. sphere(void)
  79. {
  80.   glPushMatrix();
  81.   glTranslatef(60.f, -50.f, -360.f);
  82.   glCallList(SPHERE);
  83.   glPopMatrix();
  84. }
  85. void 
  86. cone(void)
  87. {
  88.   glPushMatrix();
  89.   glTranslatef(-40.f, -40.f, -400.f);
  90.   glCallList(CONE);
  91.   glPopMatrix();
  92. }
  93. enum {
  94.   NONE, SHADOW
  95. };
  96. int rendermode = NONE;
  97. void
  98. menu(int mode)
  99. {
  100.   rendermode = mode;
  101.   glutPostRedisplay();
  102. }
  103. GLfloat leftwallshadow[4][4];
  104. GLfloat floorshadow[4][4];
  105. GLfloat lightpos[] =
  106. {50.f, 50.f, -320.f, 1.f};
  107. /* render while jittering the shadows */
  108. void
  109. render(GLfloat dx, GLfloat dy, GLfloat dz)
  110. {
  111.   /* material properties for objects in scene */
  112.   static GLfloat wall_mat[] =
  113.   {1.f, 1.f, 1.f, 1.f};
  114.   static GLfloat sphere_mat[] =
  115.   {1.f, .5f, 0.f, 1.f};
  116.   static GLfloat cone_mat[] =
  117.   {0.f, .5f, 1.f, 1.f};
  118.   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  119.   /* Note: wall verticies are ordered so they are all front facing this lets
  120.      me do back face culling to speed things up.  */
  121.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  122.   /* floor */
  123.   /* make the floor textured */
  124.   glEnable(GL_TEXTURE_2D);
  125.   /* Since we want to turn texturing on for floor only, we have to make floor 
  126.      a separate glBegin()/glEnd() sequence. You can't turn texturing on and
  127.      off between begin and end calls */
  128.   glBegin(GL_QUADS);
  129.   glNormal3f(0.f, 1.f, 0.f);
  130.   glTexCoord2i(0, 0);
  131.   glVertex3f(-100.f, -100.f, -320.f);
  132.   glTexCoord2i(1, 0);
  133.   glVertex3f(100.f, -100.f, -320.f);
  134.   glTexCoord2i(1, 1);
  135.   glVertex3f(100.f, -100.f, -520.f);
  136.   glTexCoord2i(0, 1);
  137.   glVertex3f(-100.f, -100.f, -520.f);
  138.   glEnd();
  139.   glDisable(GL_TEXTURE_2D);
  140.   if (rendermode == SHADOW) {
  141.     glDisable(GL_DEPTH_TEST);
  142.     glDisable(GL_LIGHTING);
  143.     glColor3f(0.f, 0.f, 0.f);  /* shadow color */
  144.     glPushMatrix();
  145.     glMultMatrixf((GLfloat *) floorshadow);
  146.     glTranslatef(dx, dy, dz);
  147.     cone();
  148.     glPopMatrix();
  149.     glPushMatrix();
  150.     glMultMatrixf((GLfloat *) floorshadow);
  151.     glTranslatef(dx, dy, dz);
  152.     sphere();
  153.     glPopMatrix();
  154.     glEnable(GL_DEPTH_TEST);
  155.     glEnable(GL_LIGHTING);
  156.   }
  157.   /* walls */
  158.   if (rendermode == SHADOW) {
  159.     glEnable(GL_STENCIL_TEST);
  160.     glStencilFunc(GL_ALWAYS, 1, 0);
  161.     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  162.   }
  163.   glBegin(GL_QUADS);
  164.   /* left wall */
  165.   glNormal3f(1.f, 0.f, 0.f);
  166.   glVertex3f(-100.f, -100.f, -320.f);
  167.   glVertex3f(-100.f, -100.f, -520.f);
  168.   glVertex3f(-100.f, 100.f, -520.f);
  169.   glVertex3f(-100.f, 100.f, -320.f);
  170.   glEnd();
  171.   if (rendermode == SHADOW) {
  172.     glStencilFunc(GL_EQUAL, 1, 1);
  173.     glDisable(GL_DEPTH_TEST);
  174.     glDisable(GL_LIGHTING);
  175.     glColor3f(0.f, 0.f, 0.f);  /* shadow color */
  176.     glDisable(GL_DEPTH_TEST);
  177.     glPushMatrix();
  178.     glMultMatrixf((GLfloat *) leftwallshadow);
  179.     glTranslatef(dx, dy, dz);
  180.     cone();
  181.     glPopMatrix();
  182.     glEnable(GL_DEPTH_TEST);
  183.     glDisable(GL_STENCIL_TEST);
  184.     glEnable(GL_DEPTH_TEST);
  185.     glEnable(GL_LIGHTING);
  186.   }
  187.   glBegin(GL_QUADS);
  188.   /* right wall */
  189.   glNormal3f(-1.f, 0.f, 0.f);
  190.   glVertex3f(100.f, -100.f, -320.f);
  191.   glVertex3f(100.f, 100.f, -320.f);
  192.   glVertex3f(100.f, 100.f, -520.f);
  193.   glVertex3f(100.f, -100.f, -520.f);
  194.   /* ceiling */
  195.   glNormal3f(0.f, -1.f, 0.f);
  196.   glVertex3f(-100.f, 100.f, -320.f);
  197.   glVertex3f(-100.f, 100.f, -520.f);
  198.   glVertex3f(100.f, 100.f, -520.f);
  199.   glVertex3f(100.f, 100.f, -320.f);
  200.   /* back wall */
  201.   glNormal3f(0.f, 0.f, 1.f);
  202.   glVertex3f(-100.f, -100.f, -520.f);
  203.   glVertex3f(100.f, -100.f, -520.f);
  204.   glVertex3f(100.f, 100.f, -520.f);
  205.   glVertex3f(-100.f, 100.f, -520.f);
  206.   glEnd();
  207.   glPushMatrix();
  208.   glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  209.   glDisable(GL_LIGHTING);
  210.   glColor3f(1.f, 1.f, .7f);
  211.   glCallList(LIGHT);
  212.   glEnable(GL_LIGHTING);
  213.   glPopMatrix();
  214.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  215.   cone();
  216.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  217.   sphere();
  218. }
  219. void
  220. redraw(void)
  221. {
  222.   int dx, dy, dz;
  223.   dy = 0;
  224.   /* jitter the light around */
  225.   if (rendermode == SHADOW) {
  226.     glClear(GL_ACCUM_BUFFER_BIT);
  227.     for (dz = -4; dz < 5; dz += 2) {
  228.       for (dx = -4; dx < 5; dx += 2) {
  229.         render((GLfloat) dx, (GLfloat) dy, (GLfloat) dz);
  230.         glAccum(GL_ACCUM, 1.f / 25);
  231.       }
  232.     }
  233.     glAccum(GL_RETURN, 1.f);
  234.   } else
  235.     render(0.f, 0.f, 0.f);
  236.   glutSwapBuffers();
  237. }
  238. /* ARGSUSED1 */
  239. void 
  240. key(unsigned char key, int x, int y)
  241. {
  242.   if (key == '33')
  243.     exit(0);
  244. }
  245. const int TEXDIM = 256;
  246. /* Parse arguments, and set up interface between OpenGL and window system */
  247. int
  248. main(int argc, char *argv[])
  249. {
  250.   GLfloat *tex;
  251.   GLUquadricObj *sphere, *cone, *base;
  252.   GLfloat plane[4];
  253.   GLfloat v0[3], v1[3], v2[3];
  254.   glutInit(&argc, argv);
  255.   glutInitWindowSize(512, 512);
  256.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE | GLUT_ACCUM);
  257.   (void) glutCreateWindow("soft shadows");
  258.   glutDisplayFunc(redraw);
  259.   glutKeyboardFunc(key);
  260.   glutCreateMenu(menu);
  261.   glutAddMenuEntry("No Shadows", NONE);
  262.   glutAddMenuEntry("Shadows", SHADOW);
  263.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  264.   /* draw a perspective scene */
  265.   glMatrixMode(GL_PROJECTION);
  266.   glFrustum(-100., 100., -100., 100., 320., 640.);
  267.   glMatrixMode(GL_MODELVIEW);
  268.   /* turn on features */
  269.   glEnable(GL_DEPTH_TEST);
  270.   glEnable(GL_LIGHTING);
  271.   glEnable(GL_LIGHT0);
  272.   /* make shadow matricies */
  273.   /* 3 points on floor */
  274.   v0[X] = -100.f;
  275.   v0[Y] = -100.f;
  276.   v0[Z] = -320.f;
  277.   v1[X] = 100.f;
  278.   v1[Y] = -100.f;
  279.   v1[Z] = -320.f;
  280.   v2[X] = 100.f;
  281.   v2[Y] = -100.f;
  282.   v2[Z] = -520.f;
  283.   findplane(plane, v0, v1, v2);
  284.   shadowmatrix(floorshadow, plane, lightpos);
  285.   /* 3 points on left wall */
  286.   v0[X] = -100.f;
  287.   v0[Y] = -100.f;
  288.   v0[Z] = -320.f;
  289.   v1[X] = -100.f;
  290.   v1[Y] = -100.f;
  291.   v1[Z] = -520.f;
  292.   v2[X] = -100.f;
  293.   v2[Y] = 100.f;
  294.   v2[Z] = -520.f;
  295.   findplane(plane, v0, v1, v2);
  296.   shadowmatrix(leftwallshadow, plane, lightpos);
  297.   /* place light 0 in the right place */
  298.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  299.   /* remove back faces to speed things up */
  300.   glCullFace(GL_BACK);
  301.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  302.   /* make display lists for sphere and cone; for efficiency */
  303.   glNewList(SPHERE, GL_COMPILE);
  304.   sphere = gluNewQuadric();
  305.   gluSphere(sphere, 20.f, 20, 20);
  306.   gluDeleteQuadric(sphere);
  307.   glEndList();
  308.   glNewList(LIGHT, GL_COMPILE);
  309.   sphere = gluNewQuadric();
  310.   gluSphere(sphere, 5.f, 20, 20);
  311.   gluDeleteQuadric(sphere);
  312.   glEndList();
  313.   glNewList(CONE, GL_COMPILE);
  314.   cone = gluNewQuadric();
  315.   base = gluNewQuadric();
  316.   glRotatef(-90.f, 1.f, 0.f, 0.f);
  317.   gluDisk(base, 0., 20., 20, 1);
  318.   gluCylinder(cone, 20., 0., 60., 20, 20);
  319.   gluDeleteQuadric(cone);
  320.   gluDeleteQuadric(base);
  321.   glEndList();
  322.   glNewList(FLOOR, GL_COMPILE);
  323.   glEndList();
  324.   glNewList(LEFTWALL, GL_COMPILE);
  325.   glEndList();
  326.   /* load pattern for current 2d texture */
  327.   tex = make_texture(TEXDIM, TEXDIM);
  328.   glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  329.   free(tex);
  330.   glutMainLoop();
  331.   return 0;             /* ANSI C requires main to return int. */
  332. }