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

GIS编程

开发平台:

Visual C++

  1. /**
  2.    depthdof.c: depth-of-field simulator using stencilled convolutions
  3.       Jon Brandt, 1/97
  4.       converted to GLUT and libtiff by Mark Kilgard, 4/97
  5.    Compile with:
  6.      cc -o depthdof depthdof.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm
  7.     
  8.  **/
  9. #include <GL/glut.h>
  10. #include <tiffio.h>
  11. #include <assert.h>
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <strings.h>
  16. #include <unistd.h>
  17. #define FALSE 0
  18. #define TRUE 1
  19. const char *DefaultImage = "face.tif";
  20. int winWidth = 512, winHeight = 512;
  21. char *pixels = NULL;
  22. int stencilMax;
  23. int kSize = 5;
  24. int kRadius = 5 / 2;
  25. float sharpness = -1.5;
  26. float kernel[] =
  27. {.05, .1, .7, .1, .05};
  28. int passes = 5;
  29. int contour = 0;
  30. char focus = 160;
  31. float spread = 1;
  32. int focusPending = FALSE;
  33. int splitScreen = FALSE;
  34. int smoothDepth = FALSE;
  35. int frame = 0;
  36. int running = TRUE;
  37. int cursor_x, cursor_y;
  38. int multisample, hasConvolve = 0;
  39. TIFFRGBAImage img;
  40. uint32 *raster;
  41. uint32 *texture;
  42. size_t npixels;
  43. int tw, th;
  44. int angle;
  45. int hasABGR = 0;
  46. void drawFrame(int frame);
  47. void initScene(int argc, char *argv[]);
  48. void drawScene(int frame);
  49. void drawObject(float numRep);
  50. void changePassCount(int delta);
  51. void setBlurMap(void);
  52. void setKernel(void);
  53. void resize(int w, int h);
  54. void toggle(int *param, char *msg);
  55. void
  56. redraw(void)
  57. {
  58.   drawFrame(frame);
  59. }
  60. void
  61. idle(void)
  62. {
  63.   frame++;
  64.   glutPostRedisplay();
  65. }
  66. void
  67. visible(int vis)
  68. {
  69.   if (vis == GLUT_VISIBLE)
  70.     glutIdleFunc(idle);
  71.   else
  72.     glutIdleFunc(NULL);
  73. }
  74. /* ARGSUSED1 */
  75. void
  76. keyboard(unsigned char c, int x, int y)
  77. {
  78.   switch (c) {
  79.   case 27:
  80.     exit(0);
  81.     break;
  82.   case 'g':
  83.     running = !running;
  84.     if (running) {
  85.       glutIdleFunc(idle);
  86.     } else {
  87.       glutIdleFunc(NULL);
  88.     }
  89.     break;
  90.   case 'c':
  91.     toggle(&contour, NULL);
  92.     glutPostRedisplay();
  93.     break;
  94.   case 's':
  95.     toggle(&splitScreen, NULL);
  96.     glutPostRedisplay();
  97.     break;
  98.   case 'd':
  99.     toggle(&smoothDepth, "depth smoothing");
  100.     glutPostRedisplay();
  101.     break;
  102.   case ' ':
  103.     frame++;
  104.     glutPostRedisplay();
  105.     break;
  106.   case '-':
  107.     frame--;
  108.     glutPostRedisplay();
  109.     break;
  110.   case 'p':
  111.     changePassCount(1);
  112.     glutPostRedisplay();
  113.     break;
  114.   case 'P':
  115.     changePassCount(-1);
  116.     glutPostRedisplay();
  117.     break;
  118.   case 'a':
  119.     spread *= 1 / 1.2;
  120.     setBlurMap();
  121.     glutPostRedisplay();
  122.     break;
  123.   case 'A':
  124.     spread *= 1.2;
  125.     setBlurMap();
  126.     glutPostRedisplay();
  127.     break;
  128.   case 'k':
  129.     sharpness *= 1 / 1.2;
  130.     printf("sharpness == %gn", sharpness);
  131.     setKernel();
  132.     glutPostRedisplay();
  133.     break;
  134.   case 'K':
  135.     sharpness *= 1.2;
  136.     printf("sharpness == %gn", sharpness);
  137.     setKernel();
  138.     glutPostRedisplay();
  139.     break;
  140.   }
  141. }
  142. void
  143. mouse(int b, int state, int x, int y)
  144. {
  145.   if (b == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  146.     cursor_x = x;
  147.     cursor_y = winHeight - y;
  148.     focusPending = TRUE;
  149.     glutPostRedisplay();
  150.   }
  151. }
  152. void
  153. main(int argc, char *argv[])
  154. {
  155.   int c;
  156.   glutInit(&argc, argv);
  157.   while ((c = getopt(argc, argv, "p:")) != -1) {
  158.     switch (c) {
  159.     case 'p':
  160.       passes = atoi(optarg);
  161.       break;
  162.     }
  163.   }
  164.   glutInitDisplayString("samples depth stencil~8 double");
  165.   glutCreateWindow("Depth of Field via Depth-varying Convolve");
  166.   initScene(argc - optind + 1, argv + optind - 1);
  167.   changePassCount(0);
  168.   printf("Key commands:n");
  169.   printf("          c: show/hide outer blur limitn");
  170.   printf("          g: toggle free running animationn");
  171.   printf("          s: toggle split-screenn");
  172.   printf("          d: toggle depth smoothingn");
  173.   printf("    <space>: step one frame forwardn");
  174.   printf("          -: step one frame backwardn");
  175.   printf("       p(P): increment(decrement) number of passesn");
  176.   printf("       a(A): narrow(widen) lens aperturen");
  177.   printf("       k(K): increase(decrease) kernel blurinessn");
  178.   printf("      <esc>: exitn");
  179.   printf("Mouse clicking changes focus depth.n");
  180.   glutVisibilityFunc(visible);
  181.   glutKeyboardFunc(keyboard);
  182.   glutMouseFunc(mouse);
  183.   glutDisplayFunc(redraw);
  184.   glutReshapeFunc(resize);
  185.   multisample = glutGet(GLUT_WINDOW_NUM_SAMPLES) > 0;
  186.   if (glutExtensionSupported("GL_EXT_convolution")) {
  187.     hasConvolve = 1;
  188.   } else {
  189.     while (glGetError() != GL_NO_ERROR);  /* Clear any OpenGL errors. */
  190.     /* The following glDisable would be a no-op whether done on a freshly
  191.        initialized OpenGL context whether convolution is supported or not.
  192.        The only difference should be an OpenGL error should be reported if
  193.        the GL_CONVOLUTION_2D_EXT is not understood (ie, convolution is not
  194.        supported at all). */
  195.     glDisable(GL_CONVOLUTION_2D_EXT);
  196.     if (glGetError() == GL_NO_ERROR) {
  197.       /* RealityEngine only partially implements the convolve extension and
  198.          hence does not advertise the extension in its extension string (See
  199.          MACHINE DEPENDENCIES section of the glConvolutionFilter2DEXT man
  200.          page). We limit this program to use only the convolve functionality
  201.          supported by RealityEngine so we test if OpenGL lets us enable
  202.          convolution without an error (the indication that convolution is
  203.          partially supported). */
  204.       hasConvolve = 1;
  205.     }
  206.     /* Clear any further OpenGL errors (hopefully there should have only been
  207.        one or zero though). */
  208.     while (glGetError() != GL_NO_ERROR);
  209.   }
  210.   if (!hasConvolve) {
  211.     printf("nTHIS PROGRAM IS NOT VERY INTERESTING WITHOUT THE OPENGL CONVOLVUTION EXTENSIONnn");
  212.   }
  213.   glutMainLoop();
  214. }
  215. void
  216. initScene(int argc, char *argv[])
  217. {
  218.   TIFF *tif;
  219.   char emsg[1024];
  220.   int bits;
  221.   const char *fname = argc > 1 ? argv[1] : DefaultImage;
  222.   glViewport(0, 0, winWidth, winHeight);
  223.   glEnable(GL_TEXTURE_2D);
  224.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  225.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  226.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  227.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  228.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  229.   tif = TIFFOpen(fname, "r");
  230.   if (tif == NULL) {
  231.     fprintf(stderr, "Problem showing %sn", fname);
  232.     exit(1);
  233.   }
  234.   if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
  235.     npixels = img.width * img.height;
  236.     raster = (uint32 *) _TIFFmalloc((long) (npixels * sizeof(uint32)));
  237.     if (raster != NULL) {
  238.       if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
  239.         TIFFError(fname, emsg);
  240.         exit(1);
  241.       }
  242.     }
  243.     TIFFRGBAImageEnd(&img);
  244.   } else {
  245.     TIFFError(fname, emsg);
  246.     exit(1);
  247.   }
  248. #ifdef GL_EXT_abgr
  249.   if (glutExtensionSupported("GL_EXT_abgr"))
  250.     hasABGR = 1;
  251. #else
  252.   hasABGR = 0;
  253. #endif
  254.   /* If cannot directly display ABGR format, we need to reverse the component
  255.      ordering in each pixel. :-( */
  256.   if (!hasABGR) {
  257.     int i;
  258.     for (i = 0; i < npixels; i++) {
  259.       register unsigned char *cp = (unsigned char *) &raster[i];
  260.       int t;
  261.       t = cp[3];
  262.       cp[3] = cp[0];
  263.       cp[0] = t;
  264.       t = cp[2];
  265.       cp[2] = cp[1];
  266.       cp[1] = t;
  267.     }
  268.   }
  269.   /* OpenGL's default unpack (and pack) alignment is 4.  In the case of the
  270.      data returned by libtiff which is already aligned on 32-bit boundaries,
  271.      setting the pack to 1 isn't strictly necessary. */
  272.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  273.   tw = 1 << (int) ceil(log((float) img.width) / log(2.0));
  274.   th = 1 << (int) ceil(log((float) img.height) / log(2.0));
  275.   if (tw > 512)
  276.     tw = 512;
  277.   if (th > 512)
  278.     th = 512;
  279.   texture = (uint32 *) malloc(sizeof(GLubyte) * 4 * tw * th);
  280. #ifdef GL_EXT_abgr
  281. #define APPROPRIATE_FORMAT (hasABGR ? GL_ABGR_EXT : GL_RGBA)
  282. #else
  283. #define APPROPRIATE_FORMAT GL_RGBA
  284. #endif
  285.   gluScaleImage(APPROPRIATE_FORMAT,
  286.     (int) img.width, (int) img.height, GL_UNSIGNED_BYTE, raster,
  287.     tw, th, GL_UNSIGNED_BYTE, texture);
  288.   _TIFFfree(raster);
  289.   if (gluBuild2DMipmaps(GL_TEXTURE_2D, 4, tw, th,
  290.       APPROPRIATE_FORMAT, GL_UNSIGNED_BYTE, texture)) {
  291.     fprintf(stderr, "couldn't build mip map");
  292.     exit(1);
  293.   }
  294.   glGetIntegerv(GL_STENCIL_BITS, &bits);
  295.   stencilMax = (1 << bits) - 1;
  296.   printf("stencil max = %dn", stencilMax);
  297.   setBlurMap();
  298.   setKernel();
  299.   glDrawBuffer(GL_BACK);
  300.   glReadBuffer(GL_BACK);
  301.   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  302.   glLineStipple(4, 0xaaaa);
  303.   glEnable(GL_LINE_STIPPLE);
  304.   pixels = realloc(pixels, (winWidth + 4) * (winHeight + 4));
  305. }
  306. void
  307. drawFrame(int frame)
  308. {
  309.   int pass;
  310.   int activeWidth = splitScreen ? winWidth / 2 : winWidth;
  311.   glEnable(GL_DEPTH_TEST);
  312.   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  313.   glMatrixMode(GL_PROJECTION);
  314.   glLoadIdentity();
  315.   glFrustum(-1, 1, -1, 1, 1.5, 20);
  316.   glMatrixMode(GL_MODELVIEW);
  317.   glLoadIdentity();
  318. #ifdef GL_MULTISAMPLE_SGIS
  319.   if (multisample)
  320.     glEnable(GL_MULTISAMPLE_SGIS);
  321. #endif
  322.   drawScene(frame);
  323. #ifdef GL_MULTISAMPLE_SGIS
  324.   if (multisample)
  325.     glDisable(GL_MULTISAMPLE_SGIS);
  326. #endif
  327.   if (passes > 0) {
  328.     glDisable(GL_TEXTURE_2D);
  329.     glDisable(GL_DEPTH_TEST);
  330.     glMatrixMode(GL_PROJECTION);
  331.     glLoadIdentity();
  332.     glOrtho(0, winWidth, 0, winHeight, -1, 1);
  333.     glReadPixels(0, 0, activeWidth, winHeight, GL_DEPTH_COMPONENT,
  334.       GL_UNSIGNED_BYTE, pixels);
  335.     if (focusPending) {
  336.       glReadPixels(cursor_x, cursor_y, 1, 1, GL_DEPTH_COMPONENT,
  337.         GL_UNSIGNED_BYTE, &focus);
  338.       printf("focussing on depth == %dn", focus);
  339.       setBlurMap();
  340.       focusPending = FALSE;
  341.     }
  342.     if (smoothDepth && hasConvolve) {
  343. #ifdef GL_EXT_convolution
  344.       /* convolve the depth map into alpha and read it back */
  345.       glEnable(GL_SEPARABLE_2D_EXT);
  346.       glRasterPos2f(kRadius, kRadius);
  347.       glColorMask(0, 0, 0, 1);
  348.       glDrawPixels(activeWidth, winHeight, GL_ALPHA,
  349.         GL_UNSIGNED_BYTE, pixels);
  350.       glColorMask(1, 1, 1, 1);
  351.       glDisable(GL_SEPARABLE_2D_EXT);
  352.       glReadPixels(0, 0, activeWidth, winHeight, GL_ALPHA,
  353.         GL_UNSIGNED_BYTE, pixels);
  354. #endif
  355.     }
  356.     glRasterPos2f(0, 0);
  357.     glPixelTransferi(GL_MAP_STENCIL, GL_TRUE);
  358.     glDrawPixels(activeWidth, winHeight, GL_STENCIL_INDEX,
  359.       GL_UNSIGNED_BYTE, pixels);
  360.     glPixelTransferi(GL_MAP_STENCIL, GL_FALSE);
  361.     glEnable(GL_STENCIL_TEST);
  362. #ifdef GL_EXT_convolution
  363.     if (hasConvolve) {
  364.       glEnable(GL_SEPARABLE_2D_EXT);
  365.       for (pass = 0; pass < passes; pass++) {
  366.         glStencilFunc(GL_LEQUAL, (pass + 1), 255);
  367.         glRasterPos2f(kRadius, kRadius);
  368.         glCopyPixels(0, 0, activeWidth, winHeight, GL_COLOR);
  369.       }
  370.       glDisable(GL_SEPARABLE_2D_EXT);
  371.     }
  372. #endif
  373.     if (contour) {
  374.       /* mark edge of in-focus region with green contour */
  375.       glStencilFunc(GL_EQUAL, pass, 255);
  376.       glColor3f(0, 1, 0);
  377.       glBegin(GL_TRIANGLE_STRIP);
  378.       glVertex2f(0, 0);
  379.       glVertex2f(0, winHeight);
  380.       glVertex2f(winWidth, 0);
  381.       glVertex2f(winWidth, winHeight);
  382.       glEnd();
  383.     }
  384.     glDisable(GL_STENCIL_TEST);
  385.     if (splitScreen) {
  386.       /* yellow divider line */
  387.       glColor3f(1, 1, 0);
  388.       glBegin(GL_LINE_STRIP);
  389.       glVertex2f(activeWidth, 0);
  390.       glVertex2f(activeWidth, winHeight);
  391.       glEnd();
  392.     }
  393.   }
  394.   glutSwapBuffers();
  395. }
  396. void
  397. drawScene(int frame)
  398. {
  399.   glPushMatrix();
  400.   glTranslatef(0, 0, -18);
  401.   glDisable(GL_TEXTURE_2D);
  402.   glBegin(GL_TRIANGLE_STRIP);
  403.   glColor3ub(40, 0, 140);
  404.   glVertex2f(-15, -15);
  405.   glVertex2f(15, -15);
  406.   glColor3ub(52, 202, 226);
  407.   glVertex2f(-15, 15);
  408.   glVertex2f(15, 15);
  409.   glEnd();
  410.   glPopMatrix();
  411.   glPushMatrix();
  412.   glTranslatef(0, -1, 0);
  413.   glScalef(20, 20, 20);
  414.   glRotatef(90, 1, 0, 0);
  415.   drawObject(20);
  416.   glPopMatrix();
  417.   glPushMatrix();
  418.   glTranslatef(0, 0, -5 + 3 * sinf(frame * M_PI / 180));
  419.   glRotatef(frame * 3, 0, 1, 0);
  420.   drawObject(1);
  421.   glPopMatrix();
  422.   glPushMatrix();
  423.   glTranslatef(cosf(frame * M_PI / 120), 0, -6 + 4 * sinf(frame * M_PI / 210));
  424.   glRotatef(frame * 3, 1, 0, cosf(frame * M_PI / 360));
  425.   drawObject(1);
  426.   glPopMatrix();
  427.   glPushMatrix();
  428.   glTranslatef(0, 0, -5 + 3 * sinf(frame * M_PI / 300));
  429.   drawObject(1);
  430.   glPopMatrix();
  431. }
  432. void
  433. drawObject(float n)
  434. {
  435.   glEnable(GL_TEXTURE_2D);
  436.   glColor3f(1, 1, 1);
  437.   glBegin(GL_TRIANGLE_STRIP);
  438.   glTexCoord2f(0, 0);
  439.   glVertex2f(-.5, -.5);
  440.   glTexCoord2f(n, 0);
  441.   glVertex2f(.5, -.5);
  442.   glTexCoord2f(0, n);
  443.   glVertex2f(-.5, .5);
  444.   glTexCoord2f(n, n);
  445.   glVertex2f(.5, .5);
  446.   glEnd();
  447. }
  448. void
  449. setBlurMap(void)
  450. {
  451.   int i;
  452.   unsigned short blur[256];
  453.   for (i = 0; i < 256; i++) {
  454.     float del = (i - focus) / 255.;
  455.     del *= del * spread * stencilMax;
  456.     blur[i] = del < stencilMax ? del : stencilMax;
  457.   }
  458.   glPixelMapusv(GL_PIXEL_MAP_S_TO_S, 256, blur);
  459. }
  460. void
  461. setKernel(void)
  462. {
  463. #ifdef GL_EXT_convolution
  464.   float s1 = expf(sharpness), s2 = expf(2 * sharpness);
  465.   kernel[0] = kernel[4] = s2;
  466.   kernel[1] = kernel[3] = s1;
  467.   kernel[2] = 1 - 2 * (s1 + s2);
  468.   glSeparableFilter2DEXT(GL_SEPARABLE_2D_EXT, GL_LUMINANCE,
  469.     kSize, kSize, GL_RED,
  470.     GL_FLOAT, kernel, kernel);
  471. #endif
  472. }
  473. void
  474. toggle(int *param, char *msg)
  475. {
  476.   *param = !*param;
  477.   if (msg)
  478.     printf("%s == %dn", msg, *param);
  479.   drawFrame(frame);
  480. }
  481. void
  482. changePassCount(int delta)
  483. {
  484.   passes += delta;
  485.   if (passes < 0)
  486.     passes = 0;
  487.   printf("number of passes == %dn", passes);
  488. }
  489. void
  490. resize(int w, int h)
  491. {
  492.   winWidth = w;
  493.   winHeight = h;
  494.   pixels = realloc(pixels, (winWidth + 4) * (winHeight + 4));
  495.   glViewport(0, 0, winWidth, winHeight);
  496. }