#include #include #ifdef _WIN32 #include #define sleep(x) Sleep(1000*x) #else #include #endif #include const GLdouble FRUSTDIM = 100.f; int win_width = 256; int win_height = 256; int show_results = GL_TRUE; int object_offset, font_offset; enum {SPHERE, CONE}; /*{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},*/ GLubyte rasters[][13] = { {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, }; GLfloat mults[] = {1., 1./2., 2./3., 3./4., 4./5., 5./6., 6./7., 7./8., 8./9., 9./10.}; /* ** Create a single component texture map */ void make_font(void) { GLuint i; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); font_offset = glGenLists (10); for (i = 0; i < 10; i++) { glNewList(i+font_offset, GL_COMPILE); glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, rasters[i]); glEndList(); } } GLfloat *make_texture(int maxs, int maxt) { int s, t; static GLfloat *texture; texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat)); for(t = 0; t < maxt; t++) { for(s = 0; s < maxs; s++) { texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1); } } return texture; } void print_frame_number(GLuint frame) { GLuint f1, f2; glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho (0.0, win_width, 0.0, win_height, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glColor3f(1.0, 0.0, 0.0); f1 = frame/10; if (f1 > 0) { glRasterPos2i(50, win_height - 50); glCallList(font_offset + f1); } else glRasterPos2i(60, win_height - 50); f2 = frame - f1*10; glCallList(font_offset + f2); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } void render(void) { /* material properties for objects in scene */ static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f}; glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); /* ** Note: wall verticies are ordered so they are all front facing ** this lets me do back face culling to speed things up. */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat); /* floor */ /* make the floor textured */ glEnable(GL_TEXTURE_2D); /* ** Since we want to turn texturing on for floor only, we have to ** make floor a separate glBegin()/glEnd() sequence. You can't ** turn texturing on and off between begin and end calls */ glBegin(GL_QUADS); glNormal3f(0.f, 1.f, 0.f); glTexCoord2i(0, 0); glVertex3f(-100.f, -100.f, -320.f); glTexCoord2i(1, 0); glVertex3f( 100.f, -100.f, -320.f); glTexCoord2i(1, 1); glVertex3f( 100.f, -100.f, -520.f); glTexCoord2i(0, 1); glVertex3f(-100.f, -100.f, -520.f); glEnd(); glDisable(GL_TEXTURE_2D); /* walls */ glBegin(GL_QUADS); /* left wall */ glNormal3f(1.f, 0.f, 0.f); glVertex3f(-100.f, -100.f, -320.f); glVertex3f(-100.f, -100.f, -520.f); glVertex3f(-100.f, 100.f, -520.f); glVertex3f(-100.f, 100.f, -320.f); /* right wall */ glNormal3f(-1.f, 0.f, 0.f); glVertex3f( 100.f, -100.f, -320.f); glVertex3f( 100.f, 100.f, -320.f); glVertex3f( 100.f, 100.f, -520.f); glVertex3f( 100.f, -100.f, -520.f); /* ceiling */ glNormal3f(0.f, -1.f, 0.f); glVertex3f(-100.f, 100.f, -320.f); glVertex3f(-100.f, 100.f, -520.f); glVertex3f( 100.f, 100.f, -520.f); glVertex3f( 100.f, 100.f, -320.f); /* back wall */ glNormal3f(0.f, 0.f, 1.f); glVertex3f(-100.f, -100.f, -520.f); glVertex3f( 100.f, -100.f, -520.f); glVertex3f( 100.f, 100.f, -520.f); glVertex3f(-100.f, 100.f, -520.f); glEnd(); glPushMatrix(); glTranslatef(-80.f, -60.f, -420.f); glCallList(object_offset + SPHERE); glPopMatrix(); glPushMatrix(); glTranslatef(-20.f, -80.f, -500.f); glCallList(object_offset + CONE); glPopMatrix(); if(glGetError()) /* to catch programming errors; should never happen */ printf("Oops! I screwed up my OpenGL calls somewhere\n"); glFlush(); /* high end machines may need this */ } /* compute scale factor for window->object space transform */ /* could use gluUnProject(), but probably too much trouble */ void computescale(GLfloat *sx, GLfloat *sy) { enum {XORG, YORG, WID, HT}; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); *sx = 2 * FRUSTDIM/viewport[WID]; *sy = 2 * FRUSTDIM/viewport[WID]; } enum {NONE, AA, AA_NEW}; int rendermode = NONE; void menu(int selection) { rendermode = selection; glutPostRedisplay(); } /* Called when window needs to be redrawn */ void redraw(void) { GLfloat invx, invy; GLfloat scale, dx, dy; int i, j; int min, max; int count, nframes; switch(rendermode) { case NONE: glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, 320., 640.); glMatrixMode(GL_MODELVIEW); render(); glutSwapBuffers(); break; case AA: min = -1; max = -min + 1; count = -2 * min + 1; count *= count; /* uniform scaling, less than one pixel wide */ scale = -.9f/min; computescale(&invx, &invy); glClear(GL_ACCUM_BUFFER_BIT); for(j = min, nframes = 1; j < max; j++) { for(i = min; i < max; i++, nframes++) { dx = invx * scale * i; dy = invy * scale * j; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-FRUSTDIM + dx, FRUSTDIM + dy, -FRUSTDIM + dx, FRUSTDIM + dy, 320., 640.); glMatrixMode(GL_MODELVIEW); render(); glAccum(GL_ACCUM, 1.f/count); if (show_results) { if (nframes == 1) { glutSwapBuffers(); glDrawBuffer(GL_FRONT); } else if (nframes == 2) { glDrawBuffer(GL_FRONT); glAccum(GL_RETURN, 3.99); } else { glDrawBuffer(GL_FRONT); glAccum(GL_RETURN, (GLfloat)count/(GLfloat)nframes); } print_frame_number(nframes); glFlush(); printf("frame number %d\n",nframes); glDrawBuffer(GL_BACK); sleep(3); } } } if (!show_results) { glAccum(GL_RETURN, 1.f); glutSwapBuffers(); } break; case AA_NEW: min = -2; max = -min + 1; count = -2 * min + 1; count *= count; /* uniform scaling, less than one pixel wide */ scale = -.9f/min; computescale(&invx, &invy); glClear(GL_ACCUM_BUFFER_BIT); for(j = min, nframes = 1; j < max; j++) { for(i = min; i < max; i++, nframes++) { dx = invx * scale * i; dy = invy * scale * j; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-FRUSTDIM + dx, FRUSTDIM + dy, -FRUSTDIM + dx, FRUSTDIM + dy, 320., 640.); glMatrixMode(GL_MODELVIEW); render(); if (nframes == 1) glAccum(GL_ACCUM, 1.); else glAccum(GL_ACCUM, .5); if (show_results) { glDrawBuffer(GL_FRONT); glAccum(GL_RETURN, 1.); print_frame_number(nframes); glFlush(); printf("frame number %d\n",nframes); glDrawBuffer(GL_BACK); sleep(3); } if (nframes < count) { glAccum(GL_RETURN, 1.); glAccum(GL_LOAD, .5); } } } if (!show_results) { glAccum(GL_RETURN, 1.f); glutSwapBuffers(); } break; } } void reshape(int w, int h) { if (w < h) { win_height = win_width = w; } else { win_height = win_width = h; } glViewport(0, 0, win_width, win_height); } /* ARGSUSED1 */ void key(unsigned char key, int x, int y) { if(key == '\033') exit(0); } const int TEXDIM = 256; /* Parse arguments, and set up interface between OpenGL and window system */ main(int argc, char *argv[]) { GLfloat *tex; static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f}; static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f}; static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f}; GLUquadricObj *sphere, *cone, *base; glutInit(&argc, argv); glutInitWindowSize(win_width, win_height); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_ACCUM|GLUT_DOUBLE); (void)glutCreateWindow("Accum antialias"); glutDisplayFunc(redraw); glutKeyboardFunc(key); glutReshapeFunc(reshape); glutCreateMenu(menu); glutAddMenuEntry("Aliased View", NONE); glutAddMenuEntry("AntiAliased View", AA); glutAttachMenu(GLUT_RIGHT_BUTTON); make_font(); /* draw a perspective scene */ glMatrixMode(GL_PROJECTION); glFrustum(-FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, 320., 640.); glMatrixMode(GL_MODELVIEW); /* turn on features */ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); /* place light 0 in the right place */ glLightfv(GL_LIGHT0, GL_POSITION, lightpos); /* remove back faces to speed things up */ glCullFace(GL_BACK); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); object_offset = glGenLists(2); glNewList(object_offset + SPHERE, GL_COMPILE); /* make display lists for sphere and cone; for efficiency */ sphere = gluNewQuadric(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat); gluSphere(sphere, 20.f, 20, 20); gluDeleteQuadric(sphere); glEndList(); glNewList(object_offset + CONE, GL_COMPILE); cone = gluNewQuadric(); base = gluNewQuadric(); glRotatef(-90.f, 1.f, 0.f, 0.f); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat); gluDisk(base, 0., 20., 20, 1); gluCylinder(cone, 20., 0., 60., 20, 20); gluDeleteQuadric(cone); gluDeleteQuadric(base); glEndList(); /* load pattern for current 2d texture */ tex = make_texture(TEXDIM, TEXDIM); glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex); free(tex); glReadBuffer(GL_BACK); /* input to accum buffer */ glutMainLoop(); return 0; }