Main Page | Class List | File List | Class Members | File Members

depth_of_field.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1993-1997, Silicon Graphics, Inc.
00003  * ALL RIGHTS RESERVED 
00004  * Permission to use, copy, modify, and distribute this software for 
00005  * any purpose and without fee is hereby granted, provided that the above
00006  * copyright notice appear in all copies and that both the copyright notice
00007  * and this permission notice appear in supporting documentation, and that 
00008  * the name of Silicon Graphics, Inc. not be used in advertising
00009  * or publicity pertaining to distribution of the software without specific,
00010  * written prior permission. 
00011  *
00012  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
00013  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
00014  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
00015  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
00016  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
00017  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
00018  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
00019  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
00020  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
00021  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
00022  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
00023  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
00024  * 
00025  * US Government Users Restricted Rights 
00026  * Use, duplication, or disclosure by the Government is subject to
00027  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
00028  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
00029  * clause at DFARS 252.227-7013 and/or in similar or successor
00030  * clauses in the FAR or the DOD or NASA FAR Supplement.
00031  * Unpublished-- rights reserved under the copyright laws of the
00032  * United States.  Contractor/manufacturer is Silicon Graphics,
00033  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
00034  *
00035  * OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
00036  */
00037 
00038 /*
00039  *  dof.c
00040  *  This program demonstrates use of the accumulation buffer to
00041  *  create an out-of-focus depth-of-field effect.  The teapots
00042  *  are drawn several times into the accumulation buffer.  The
00043  *  viewing volume is jittered, except at the focal point, where
00044  *  the viewing volume is at the same position, each time.  In
00045  *  this case, the gold teapot remains in focus.
00046  */
00047  
00048 #include <GL/glut.h>
00049 #include <GL/glu.h>
00050 #include <stdlib.h>
00051 #include <math.h>
00052 #include "jitter.h"
00053 
00054 #ifdef WIN32
00055 #define near zNear
00056 #define far zFar
00057 #endif
00058 
00059 #define PI_ 3.14159265358979323846
00060 
00061 
00062 // File a little bit modified in order to give the user ability to 
00063 // change the number of jitter point during runtime and focus distance.
00064 // After some change scene first draw sharp and then jittered in accumulation
00065 // buffer in order to get depth of field effect.
00066 
00067 #include <stdio.h>
00068 
00069 
00070 //focus
00071 float z = 5.0;
00072 
00073 bool changed = false;
00074 
00075 
00076 
00077 //rotation variables
00078 float AngleX=0, AngleY=0;
00079 bool RotateUp = false, RotateDown = false, RotateLeft = false, RotateRight = false;
00080 
00081 float CameraX = 0, CameraY = 0, CameraZ = 5.0f;
00082 
00083 int LastTime = 0;
00084 int TimerDelay;
00085 float FPS = 0;
00086 
00087 //helper function from Bastian
00088 void glutString( char *pstr )
00089 {
00090   while (*pstr!=char(0)) {
00091     glutBitmapCharacter( GLUT_BITMAP_8_BY_13, int( *pstr ));
00092     pstr++;
00093   }
00094 }
00095 
00096 //
00097 enum { JITTER_2 = 0, JITTER_3, JITTER_4, JITTER_8, JITTER_15, JITTER_24, JITTER_66, JITTER_N};
00098 
00099 int njitters[JITTER_N] = { 2, 3, 4, 8, 15, 24, 66 };
00100 
00101 jitter_point* jitters[JITTER_N];
00102 
00103 int current_jitter = JITTER_8;
00104 
00105 GLuint teapotList;
00106 
00107 /* accFrustum()
00108  * The first 6 arguments are identical to the glFrustum() call.
00109  *  
00110  * pixdx and pixdy are anti-alias jitter in pixels. 
00111  * Set both equal to 0.0 for no anti-alias jitter.
00112  * eyedx and eyedy are depth-of field jitter in pixels. 
00113  * Set both equal to 0.0 for no depth of field effects.
00114  *
00115  * focus is distance from eye to plane in focus. 
00116  * focus must be greater than, but not equal to 0.0.
00117  *
00118  * Note that accFrustum() calls glTranslatef().  You will 
00119  * probably want to insure that your ModelView matrix has been 
00120  * initialized to identity before calling accFrustum().
00121  */
00122 void accFrustum(GLdouble left, GLdouble right, GLdouble bottom, 
00123    GLdouble top, GLdouble near, GLdouble far, GLdouble pixdx, 
00124    GLdouble pixdy, GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00125 {
00126    GLdouble xwsize, ywsize; 
00127    GLdouble dx, dy;
00128    GLint viewport[4];
00129 
00130    glGetIntegerv (GL_VIEWPORT, viewport);
00131         
00132    xwsize = right - left;
00133    ywsize = top - bottom;
00134         
00135    dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
00136    dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);
00137         
00138    glMatrixMode(GL_PROJECTION);
00139    glLoadIdentity();
00140    glFrustum (left + dx, right + dx, bottom + dy, top + dy, near, far);
00141    glMatrixMode(GL_MODELVIEW);
00142    glLoadIdentity();
00143    glTranslatef (-eyedx, -eyedy, 0.0);
00144 }
00145 
00146 /*  accPerspective()
00147  * 
00148  *  The first 4 arguments are identical to the gluPerspective() call.
00149  *  pixdx and pixdy are anti-alias jitter in pixels. 
00150  *  Set both equal to 0.0 for no anti-alias jitter.
00151  *  eyedx and eyedy are depth-of field jitter in pixels. 
00152  *  Set both equal to 0.0 for no depth of field effects.
00153  *
00154  *  focus is distance from eye to plane in focus. 
00155  *  focus must be greater than, but not equal to 0.0.
00156  *
00157  *  Note that accPerspective() calls accFrustum().
00158  */
00159 void accPerspective(GLdouble fovy, GLdouble aspect, 
00160    GLdouble near, GLdouble far, GLdouble pixdx, GLdouble pixdy, 
00161    GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00162 {
00163    GLdouble fov2,left,right,bottom,top;
00164 
00165    fov2 = ((fovy*PI_) / 180.0) / 2.0;
00166 
00167    top = near / (cos(fov2) / sin(fov2));
00168    bottom = -top;
00169 
00170    right = top * aspect;
00171    left = -right;
00172 
00173    accFrustum (left, right, bottom, top, near, far,
00174                pixdx, pixdy, eyedx, eyedy, focus);
00175 }
00176 
00177 void init(void)
00178 {
00179 jitters[0] = j2;
00180 jitters[1] = j3;
00181 jitters[2] = j4;
00182 jitters[3] = j8;
00183 jitters[4] = j15;
00184 jitters[5] = j24;
00185 jitters[6] = j66;
00186 
00187 GLenum performance = GL_FASTEST; //GL_NICEST
00188 glHint(GL_POINT_SMOOTH_HINT, performance );
00189 glHint(GL_LINE_SMOOTH_HINT, performance );
00190 glHint(GL_POLYGON_SMOOTH_HINT, performance );
00191 glHint(GL_FOG_HINT, performance );
00192 glHint(GL_PERSPECTIVE_CORRECTION_HINT, performance );
00193 
00194 /*
00195   glEnable(GL_DEPTH_TEST);
00196   glDepthFunc(GL_LESS);
00197   glShadeModel(GL_SMOOTH);
00198   glEnable(GL_LIGHTING);
00199   glDisable( GL_CULL_FACE );
00200   glEnable( GL_NORMALIZE );
00201   */
00202    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
00203    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
00204    GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
00205    GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 };
00206     
00207    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
00208    GLfloat local_view[] = { 0.0 };
00209 
00210    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
00211    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
00212    glLightfv(GL_LIGHT0, GL_POSITION, position);
00213     
00214    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00215    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
00216 
00217    glFrontFace (GL_CW);
00218    glEnable(GL_LIGHTING);
00219    glEnable(GL_LIGHT0);
00220    glEnable(GL_AUTO_NORMAL);
00221    glEnable(GL_NORMALIZE);
00222    glEnable(GL_DEPTH_TEST);
00223 
00224    glClearColor(0.0, 0.0, 0.0, 0.0);
00225    glClearAccum(0.0, 0.0, 0.0, 0.0); 
00226 /*  make teapot display list */
00227    teapotList = glGenLists(1);
00228    glNewList (teapotList, GL_COMPILE);
00229    glutSolidTeapot (0.5);
00230    glEndList ();
00231 }
00232 
00233 void renderTeapot (GLfloat x, GLfloat y, GLfloat z, 
00234    GLfloat ambr, GLfloat ambg, GLfloat ambb, 
00235    GLfloat difr, GLfloat difg, GLfloat difb, 
00236    GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
00237 {
00238    GLfloat mat[4];
00239 
00240    glPushMatrix();
00241    glTranslatef (x, y, z);
00242    mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;   
00243    glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
00244    mat[0] = difr; mat[1] = difg; mat[2] = difb; 
00245    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
00246    mat[0] = specr; mat[1] = specg; mat[2] = specb;
00247    glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
00248    glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0);
00249    glCallList(teapotList);
00250    glPopMatrix();
00251 }
00252 
00253 /*  display() draws 5 teapots into the accumulation buffer 
00254  *  several times; each time with a jittered perspective.
00255  *  The focal point is at z = 5.0, so the gold teapot will 
00256  *  stay in focus.  The amount of jitter is adjusted by the
00257  *  magnitude of the accPerspective() jitter; in this example, 0.33.
00258  *  In this example, the teapots are drawn 8 times.  See jitter.h
00259  */
00260 void display(void)
00261 {
00262    int jitter;
00263    GLint viewport[4];
00264 
00265 //    glColor3f( 1.0f, 1.0f, 1.0f );
00266 
00267    glClearColor(0.0, 0.0, 0.0, 0.0);
00268    glClearAccum(0.0, 0.0, 0.0, 0.0); 
00269 
00270    glGetIntegerv (GL_VIEWPORT, viewport);
00271   // glClear(GL_ACCUM_BUFFER_BIT);
00272 //glClear(GL_COLOR_BUFFER_BIT);
00273       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
00274 
00275 if (changed) 
00276         {
00277         changed = false;
00278       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00279       accPerspective (45.0, 
00280          (GLdouble) viewport[2]/(GLdouble) viewport[3], 
00281          1.0, 15.0, 0.0, 0.0,
00282          0, 0, z);
00283       renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175, 
00284                     0.01175, 0.61424, 0.04136, 0.04136, 
00285                     0.727811, 0.626959, 0.626959, 0.6);
00286       renderTeapot (-0.5, -0.5, -5.0, 0.24725, 0.1995, 
00287                     0.0745, 0.75164, 0.60648, 0.22648, 
00288                     0.628281, 0.555802, 0.366065, 0.4);
00289       renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225, 
00290                     0.19225, 0.50754, 0.50754, 0.50754, 
00291                     0.508273, 0.508273, 0.508273, 0.4);
00292       renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215, 
00293                     0.07568, 0.61424, 0.07568, 0.633, 
00294                     0.727811, 0.633, 0.6);
00295       renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0, 
00296                     0.50980392, 0.50980392, 0.50196078, 
00297                     0.50196078, 0.50196078, .25);
00298        glAccum (GL_ACCUM, 1.0);
00299        glAccum (GL_RETURN, 1.0);
00300        
00301        
00302        //and now making depth of field
00303         }
00304         else
00305         {//if there are no changes in camera position,
00306         // then accumulate to the buffer
00307 
00308    jitter_point *tmp;
00309    for (jitter = 0; jitter < njitters[current_jitter]; jitter++) {
00310       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00311       tmp = (jitters[current_jitter] + jitter);
00312       accPerspective (45.0, 
00313          (GLdouble) viewport[2]/(GLdouble) viewport[3], 
00314          1.0, 15.0, 0.0, 0.0,
00315          .33 * tmp->x, .33 * tmp -> y, z);
00316 //        glMatrixMode(GL_PROJECTION);
00317         //  glTranslated(CameraX, CameraY, CameraZ);
00318 //      glRotated( AngleY, 0, 1, 0);
00319           glMatrixMode(GL_MODELVIEW);
00320 //        glTranslated(-CameraX, -CameraY, -CameraZ);
00321                 glPushMatrix();
00322 /*      ruby, gold, silver, emerald, and cyan teapots   */
00323       renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175, 
00324                     0.01175, 0.61424, 0.04136, 0.04136, 
00325                     0.727811, 0.626959, 0.626959, 0.6);
00326       renderTeapot (-0.5, -0.5, -5.0, 0.24725, 0.1995, 
00327                     0.0745, 0.75164, 0.60648, 0.22648, 
00328                     0.628281, 0.555802, 0.366065, 0.4);
00329       renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225, 
00330                     0.19225, 0.50754, 0.50754, 0.50754, 
00331                     0.508273, 0.508273, 0.508273, 0.4);
00332       renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215, 
00333                     0.07568, 0.61424, 0.07568, 0.633, 
00334                     0.727811, 0.633, 0.6);
00335       renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0, 
00336                     0.50980392, 0.50980392, 0.50196078, 
00337                     0.50196078, 0.50196078, .25);
00338                 glPopMatrix();
00339       glAccum (GL_ACCUM, (1.0f/njitters[current_jitter]) ); //0.125
00340    }//end for
00341    glAccum (GL_RETURN, 1.0);
00342    }//end if 
00343    
00344     
00345 /*       // Display framerate
00346 glPushMatrix();
00347     char buf[100];
00348     sprintf( buf, "READY %0.2f fps,  X=%f, Y=%f, Z=%f, alpha=%f, beta=%f ", FPS, CameraX, CameraY, CameraZ, 
00349         AngleX, AngleY );
00350     glMatrixMode( GL_PROJECTION );
00351     glLoadIdentity();
00352     glMatrixMode( GL_MODELVIEW );
00353     glLoadIdentity();
00354     glDisable( GL_DEPTH_TEST );
00355     glDisable( GL_LIGHTING );
00356     glColor3f( 1.0f, 1.0f, 1.0f );
00357     glRasterPos2f( -1,-1 );
00358     glutString( buf );
00359     glEnable( GL_DEPTH_TEST );
00360     glEnable(GL_LIGHTING);
00361 glPopMatrix();
00362   */ 
00363    glutSwapBuffers();
00364 }
00365 
00366 void print_jitter_points (int n)
00367 {
00368 jitter_point * tmp;
00369    for (int jitter = 0; jitter < njitters[n]; jitter++) 
00370       {
00371       tmp = (jitters[n] + jitter);
00372       printf(" coordinates of %d-jitter point: x = %f, y = %f \n", jitter + 1, tmp->x, tmp->y );
00373       }
00374 
00375 }
00376 
00377 void reshape(int w, int h)
00378 {
00379 changed = true;
00380    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00381    glutPostRedisplay();
00382 }
00383 
00384 void keyboard(unsigned char key, int x, int y)
00385 {
00386    switch (key) {
00387       case 27:
00388       case 'q':
00389          exit(0);
00390          break;
00391           case ' ':
00392                  glutPostRedisplay();
00393                  break;
00394           case 'a':
00395                 RotateLeft = true;
00396                 RotateRight = false;
00397                 break;
00398           case 'd':
00399                 RotateRight = true;
00400                 RotateLeft = false;
00401                 break;
00402           case 'n': 
00403                 //increase focus
00404                 z+= 0.1;
00405                 changed = true;
00406                 break;
00407           case 'm': z-=0.1;
00408                 changed = true;
00409                 break;
00410          case '1': 
00411                 changed = true; 
00412                 current_jitter = JITTER_2; 
00413                 printf(" From now will use %d jitter points. \n", 2);
00414                 print_jitter_points(JITTER_2);
00415                 break;
00416          case '2': 
00417                 changed = true; 
00418                 current_jitter = JITTER_3; 
00419                 printf(" From now will use %d jitter points. \n", 3);
00420                 print_jitter_points(JITTER_3);
00421                 break;
00422          case '3': 
00423                 changed = true; 
00424                 current_jitter = JITTER_4; 
00425                 printf(" From now will use %d jitter points. \n", 4);
00426                 print_jitter_points(JITTER_4);
00427                 break;
00428          case '4': 
00429                 changed = true; 
00430                 current_jitter = JITTER_8; 
00431                 printf(" From now will use %d jitter points. \n", 8);
00432                 print_jitter_points(JITTER_8);
00433                 break;
00434          case '5': 
00435                 changed = true; 
00436                 current_jitter = JITTER_15; 
00437                 printf(" From now will use %d jitter points. \n", 15);
00438                 print_jitter_points(JITTER_15);
00439                 break;
00440          case '6': 
00441                 changed = true; 
00442                 current_jitter = JITTER_24; 
00443                 printf(" From now will use %d jitter points. \n", 24);
00444                 print_jitter_points(JITTER_24);
00445                 break;
00446          case '7': 
00447                 changed = true; 
00448                 current_jitter = JITTER_66; 
00449                 printf(" From now will use %d jitter points. \n", 66);
00450                 print_jitter_points(JITTER_66);
00451                 break;
00452    }
00453 }
00454 
00455 static void timerCallback(int)
00456 {
00457 
00458 int nc = glutGet(GLUT_ELAPSED_TIME);
00459 float fSec = float(nc-LastTime) / 1000.0f;
00460   // Compute average frame rate from the last twenty frames
00461   FPS = (19.0f*FPS + 1.0f / fSec) / 20.0f;
00462   LastTime = nc;
00463   
00464   float fCamArc = fSec * 180.0f;
00465   if (RotateLeft) AngleY -= fCamArc/4;
00466   if (RotateRight) AngleY += fCamArc/4;
00467   
00468   glutPostRedisplay();
00469   glutTimerFunc(TimerDelay, timerCallback, 0);
00470 
00471 }
00472 
00473 
00474 
00475 /*  Main Loop
00476  *  Be certain you request an accumulation buffer.
00477  */
00478 
00479 void keyboardUp(unsigned char key, int, int)
00480 {
00481 switch (key)
00482         {
00483         case 'a':
00484                 RotateLeft = false;
00485                 break;
00486         case 'd': RotateRight = false; break;
00487         }
00488 
00489 }
00490  
00491 int main(int argc, char** argv)
00492 {
00493 
00494 printf(" Keys: \n");
00495 printf("\tn/m  -- increase/decrease focus distance \n");
00496 printf("\t1..7 -- change number of jitter points   \n");
00497 printf("\tq    -- to Quit.\n");
00498 
00499    glutInit(&argc, argv);
00500    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB
00501                         | GLUT_ACCUM | GLUT_DEPTH); 
00502    glutInitWindowSize (400, 400);
00503    glutInitWindowPosition (100, 100);
00504    glutCreateWindow (argv[0]);
00505    init();
00506    glutReshapeFunc(reshape);
00507    glutDisplayFunc(display);
00508    glutKeyboardFunc(keyboard);
00509    glutKeyboardUpFunc(keyboardUp);
00510    LastTime = glutGet (GLUT_ELAPSED_TIME );
00511    glutTimerFunc ( TimerDelay, timerCallback, 0);
00512    glutMainLoop();
00513    return 0;
00514 }
00515 

Generated on Thu Jan 20 02:47:04 2005 for Depth_of_Field_Effect_Demo by doxygen 1.3.6