Main Page | File List | File Members

motion_blur.cpp

Go to the documentation of this file.
00001 #include <GL/glut.h>
00002 #include <GL/glu.h>
00003 #include <stdlib.h>
00004 #include <math.h>
00005 
00006 #define PI_ 3.14159265358979323846
00007 
00008 
00009 // File a modified to show the motion blur effect on the gold teapot.
00010 // The idea of applied technique is taken both from OpenGL red book
00011 // and "Advanced Graphics Programming Techniques Using OpenGL", section 9.1.
00012 // Then we render the scene with moving object N times (with N distinct
00013 // positions of the object) appending them into accumulation buffer.
00014 // The current position of the teapot is rendered more sharp (value provided to
00015 // glAccum(GL_ACCUM, ...) is greater), and the previous ones more smooth.
00016 // This is defined by the array "parts", which is calculated in init() function.
00017 // With selected constants (0.25 and 0.75) effect looks very good, but 
00018 // works very slow due to the large number of points (by default N = 10).
00019 // Decreasing variable "dangle", which is incrementation of angle, makes
00020 // motion blur more natural. By default it is small enough (1 deg).
00021 // User can change the speed of rotation and  pause the demo. In fact 
00022 // increasing the speed doesn't mean run faster, but rotate to the greater
00023 // angle (more precise, dangle * speed).
00024 
00025 #include <stdio.h>
00026 
00027 
00028 //focus
00029 float z = 5.0;
00030 
00031 
00032 //number of intermediate points in motion blur
00033 #define N  10
00034 
00035 float parts[N];
00036 
00037 //speed of rotation
00038 int speed = 1;
00039 
00040 float dangle = 1.0f;
00041 
00042 //stop the rotation
00043 bool pause = false;
00044 
00045 //rotation variables
00046 float AngleX=90;
00047 float PrevAngleX = 90;
00048 
00049 
00050 int LastTime = 0;
00051 int TimerDelay = 50;
00052 float FPS = 0;
00053 
00054 GLuint teapotList;
00055 
00056 /* accFrustum()
00057  * The first 6 arguments are identical to the glFrustum() call.
00058  *  
00059  * pixdx and pixdy are anti-alias jitter in pixels. 
00060  * Set both equal to 0.0 for no anti-alias jitter.
00061  * eyedx and eyedy are depth-of field jitter in pixels. 
00062  * Set both equal to 0.0 for no depth of field effects.
00063  *
00064  * focus is distance from eye to plane in focus. 
00065  * focus must be greater than, but not equal to 0.0.
00066  *
00067  * Note that accFrustum() calls glTranslatef().  You will 
00068  * probably want to insure that your ModelView matrix has been 
00069  * initialized to identity before calling accFrustum().
00070  */
00071 void accFrustum(GLdouble left, GLdouble right, GLdouble bottom, 
00072    GLdouble top, GLdouble near, GLdouble far, GLdouble pixdx, 
00073    GLdouble pixdy, GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00074 {
00075    GLdouble xwsize, ywsize; 
00076    GLdouble dx, dy;
00077    GLint viewport[4];
00078 
00079    glGetIntegerv (GL_VIEWPORT, viewport);
00080         
00081    xwsize = right - left;
00082    ywsize = top - bottom;
00083         
00084    dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
00085    dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);
00086         
00087    glMatrixMode(GL_PROJECTION);
00088    glLoadIdentity();
00089    glFrustum (left + dx, right + dx, bottom + dy, top + dy, near, far);
00090    glMatrixMode(GL_MODELVIEW);
00091    glLoadIdentity();
00092    glTranslatef (-eyedx, -eyedy, 0.0);
00093 }
00094 
00095 /*  accPerspective()
00096  * 
00097  *  The first 4 arguments are identical to the gluPerspective() call.
00098  *  pixdx and pixdy are anti-alias jitter in pixels. 
00099  *  Set both equal to 0.0 for no anti-alias jitter.
00100  *  eyedx and eyedy are depth-of field jitter in pixels. 
00101  *  Set both equal to 0.0 for no depth of field effects.
00102  *
00103  *  focus is distance from eye to plane in focus. 
00104  *  focus must be greater than, but not equal to 0.0.
00105  *
00106  *  Note that accPerspective() calls accFrustum().
00107  */
00108 void accPerspective(GLdouble fovy, GLdouble aspect, 
00109    GLdouble near, GLdouble far, GLdouble pixdx, GLdouble pixdy, 
00110    GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00111 {
00112    GLdouble fov2,left,right,bottom,top;
00113 
00114    fov2 = ((fovy*M_PI) / 180.0) / 2.0;
00115 
00116    top = near / (cos(fov2) / sin(fov2));
00117    bottom = -top;
00118 
00119    right = top * aspect;
00120    left = -right;
00121 
00122    accFrustum (left, right, bottom, top, near, far,
00123                pixdx, pixdy, eyedx, eyedy, focus);
00124 }
00125 
00126 void init(void)
00127 {
00128 parts[N-1] = 1.0f/N;
00129 float sum;
00130 for (int i = (N-2); i>=0; i--)
00131     {
00132     sum = parts[i+1] + 1.0f/N;
00133     parts[i+1] = .25 * sum;
00134     parts[i]   = .75 * sum;
00135     }
00136 printf(" Accumulation portions are defined as follows: \n");
00137 for (int i= 0; i<N; i++)
00138     {
00139     printf("\tparts[%d] = %f \n", i, parts[i]);
00140     }
00141 
00142 GLenum performance = GL_FASTEST; //GL_NICEST
00143 glHint(GL_POINT_SMOOTH_HINT, performance );
00144 glHint(GL_LINE_SMOOTH_HINT, performance );
00145 glHint(GL_POLYGON_SMOOTH_HINT, performance );
00146 glHint(GL_FOG_HINT, performance );
00147 glHint(GL_PERSPECTIVE_CORRECTION_HINT, performance );
00148 
00149 /*
00150   glEnable(GL_DEPTH_TEST);
00151   glDepthFunc(GL_LESS);
00152   glShadeModel(GL_SMOOTH);
00153   glEnable(GL_LIGHTING);
00154   glDisable( GL_CULL_FACE );
00155   glEnable( GL_NORMALIZE );
00156   */
00157    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
00158    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
00159    GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
00160    GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 };
00161     
00162    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
00163    GLfloat local_view[] = { 0.0 };
00164 
00165    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
00166    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
00167    glLightfv(GL_LIGHT0, GL_POSITION, position);
00168     
00169    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00170    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
00171 
00172    glFrontFace (GL_CW);
00173    glEnable(GL_LIGHTING);
00174    glEnable(GL_LIGHT0);
00175    glEnable(GL_AUTO_NORMAL);
00176    glEnable(GL_NORMALIZE);
00177    glEnable(GL_DEPTH_TEST);
00178 
00179    glClearColor(0.0, 0.0, 0.0, 0.0);
00180    glClearAccum(0.0, 0.0, 0.0, 0.0); 
00181 /*  make teapot display list */
00182    teapotList = glGenLists(1);
00183    glNewList (teapotList, GL_COMPILE);
00184    glutSolidTeapot (0.5);
00185    glEndList ();
00186 }
00187 
00188 void renderTeapot (GLfloat x, GLfloat y, GLfloat z, 
00189    GLfloat ambr, GLfloat ambg, GLfloat ambb, 
00190    GLfloat difr, GLfloat difg, GLfloat difb, 
00191    GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
00192 {
00193    GLfloat mat[4];
00194 
00195    glPushMatrix();
00196    glTranslatef (x, y, z);
00197    mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;   
00198    glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
00199    mat[0] = difr; mat[1] = difg; mat[2] = difb; 
00200    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
00201    mat[0] = specr; mat[1] = specg; mat[2] = specb;
00202    glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
00203    glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0);
00204    glCallList(teapotList);
00205    glPopMatrix();
00206 }
00207 
00208 /*  display() draws 5 teapots into the accumulation buffer 
00209  *  several times; each time with a jittered perspective.
00210  *  The focal point is at z = 5.0, so the gold teapot will 
00211  *  stay in focus.  The amount of jitter is adjusted by the
00212  *  magnitude of the accPerspective() jitter; in this example, 0.33.
00213  *  In this example, the teapots are drawn 8 times.  See jitter.h
00214  */
00215 void display(void)
00216 {
00217    int jitter;
00218    GLint viewport[4];
00219 GLfloat mat[4];
00220 
00221 
00222    glClearColor(0.0, 0.0, 0.0, 0.0);
00223    glClearAccum(0.0, 0.0, 0.0, 0.0); 
00224 
00225    glGetIntegerv (GL_VIEWPORT, viewport);
00226   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
00227 
00228 //then the whole scene with moving teapot at different positions
00229 float angle;
00230 
00231 for (int i=0; i<N; i++)
00232     {
00233 //  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00234 //    angle = AngleX - (AngleX - PrevAngleX)*(i)/(N) ;
00235         angle = PrevAngleX - i*dangle*speed;
00236     
00237     glPushMatrix();
00238       accPerspective (45.0, 
00239          (GLdouble) viewport[2]/(GLdouble) viewport[3], 
00240          1.0, 15.0, 0.0, 0.0,
00241          0, 0, 5.0);
00242 
00243 glPushMatrix();
00244 
00245       renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175, 
00246                     0.01175, 0.61424, 0.04136, 0.04136, 
00247                     0.727811, 0.626959, 0.626959, 0.6);
00248 glPopMatrix();
00249 
00250 
00251 glPushMatrix();
00252       renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225, 
00253                     0.19225, 0.50754, 0.50754, 0.50754, 
00254                     0.508273, 0.508273, 0.508273, 0.4);
00255 glPopMatrix();
00256 glPushMatrix();
00257       renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215, 
00258                     0.07568, 0.61424, 0.07568, 0.633, 
00259                     0.727811, 0.633, 0.6);
00260 glPopMatrix();
00261 
00262 glPushMatrix();
00263       renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0, 
00264                     0.50980392, 0.50980392, 0.50196078, 
00265                     0.50196078, 0.50196078, .25);
00266     glPopMatrix();
00267 
00268     glPushMatrix();
00269     glTranslatef(-0.5, -0.5, -5);
00270     glRotated(angle, 0, 1, 0);
00271        mat[0] = 0.24725; mat[1] = 0.1995; mat[2] = 0.0745; mat[3] = 1.0;        
00272        glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
00273        mat[0] = 0.75164; mat[1] = 0.60648; mat[2] = 0.22648;    
00274        glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
00275        mat[0] = 0.628281; mat[1] = 0.555802; mat[2] = 0.366065;
00276        glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
00277        glMaterialf (GL_FRONT, GL_SHININESS, 0.4*128.0);
00278        glCallList(teapotList);
00279 
00280     glPopMatrix();
00281 glPopMatrix();
00282 
00283        glAccum (GL_ACCUM, parts[i]);
00284       }//endfor
00285 
00286 if (!pause)
00287     PrevAngleX = PrevAngleX + speed*dangle;      
00288 
00289 
00290  glAccum(GL_RETURN, 1.0f);
00291    glutSwapBuffers();
00292 }
00293 
00294 void reshape(int w, int h)
00295 {
00296    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00297    glutPostRedisplay();
00298 }
00299 
00300 void keyboard(unsigned char key, int x, int y)
00301 {
00302    switch (key) {
00303       case 27:
00304       case 'q':
00305          exit(0);
00306          break;
00307           case ' ':
00308                  pause = ! pause;
00309                  break;
00310           case '1':
00311             speed = 1;
00312             break;
00313           case '2':
00314             speed = 2;
00315             break;
00316           case '3':
00317             speed = 3;
00318             break;
00319           case '4':
00320             speed = 4 ;
00321             break;
00322           case '5':
00323             speed = 5;
00324             break;
00325           case '6':
00326             speed = 6;
00327             break;
00328           case '7':
00329             speed = 7;
00330             break;
00331           case '8':
00332             speed = 8;
00333             break;
00334           case '9':
00335             speed = 9;
00336             break;
00337           
00338    }
00339 }
00340 
00341 static void timerCallback(int)
00342 {
00343 
00344 int nc = glutGet(GLUT_ELAPSED_TIME);
00345 float fSec = float(nc-LastTime) / 1000.0f;
00346   // Compute average frame rate from the last twenty frames
00347   FPS = (19.0f*FPS + 1.0f / fSec) / 20.0f;
00348   LastTime = nc;
00349   
00350   float fCamArc = fSec * 180.0f;
00351   
00352 if (!pause)
00353     {
00354 //  AngleX += fCamArc/60.0f*speed;
00355     AngleX += speed * dangle;
00356     }
00357     else
00358     {
00359     AngleX = PrevAngleX;
00360     }
00361   
00362   glutPostRedisplay();
00363   glutTimerFunc(TimerDelay, timerCallback, 0);
00364 
00365 }
00366 
00367 
00368 
00369 /*  Main Loop
00370  *  Be certain you request an accumulation buffer.
00371  */
00372 
00373 int main( int argc, char *argv[])
00374 {
00375 
00376 printf(" Keys: \n");
00377 printf("\tSpace -- stop moving the teapot \n");
00378 printf("\t1..9  -- adjust speed of teapot\n");
00379 printf("\tq     -- Quit.\n");
00380 
00381    glutInit(&argc, argv);
00382    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB
00383                         | GLUT_ACCUM | GLUT_DEPTH); 
00384    glutInitWindowSize (400, 400);
00385    glutInitWindowPosition (100, 100);
00386    glutCreateWindow (argv[0]);
00387    init();
00388    glutReshapeFunc(reshape);
00389    glutDisplayFunc(display);
00390    glutKeyboardFunc(keyboard);
00391    LastTime = glutGet (GLUT_ELAPSED_TIME );
00392    glutTimerFunc ( TimerDelay, timerCallback, 0);
00393    glutMainLoop();
00394    return 0;
00395 }
00396 

Generated on Thu Jan 20 02:47:08 2005 for Motion_Blur_Effect_Demo by doxygen 1.3.6