132001f49Smrg/* 232001f49Smrg * Demo of (nearly) flicker-free drawing with a single color buffer. 332001f49Smrg * 432001f49Smrg * Basically, draw the scene into the Z buffer first, then draw the 532001f49Smrg * scene into the color buffer. Finally, "clear" the background by 632001f49Smrg * setting the fragments we didn't hit earlier. 732001f49Smrg * 832001f49Smrg * This won't work if you need blending. The technique works best 932001f49Smrg * when the scene is relatively simple and can be rendered quickly 1032001f49Smrg * (i.e. with hardware), and when the objects don't move too much from 1132001f49Smrg * one frame to the next. 1232001f49Smrg * 1332001f49Smrg * Brian Paul 1432001f49Smrg * 25 August 2005 1532001f49Smrg * 1632001f49Smrg * See Mesa license for terms. 1732001f49Smrg */ 1832001f49Smrg 1932001f49Smrg 2032001f49Smrg#include <stdio.h> 2132001f49Smrg#include <stdlib.h> 2232001f49Smrg#include "glut_wrap.h" 2332001f49Smrg 2432001f49Smrg 2532001f49Smrg#define FLICKER 0 2632001f49Smrg#define NO_FLICKER 1 2732001f49Smrg 2832001f49Smrgstatic GLint Mode = NO_FLICKER; 2932001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0, Zrot = 0; 3032001f49Smrgstatic GLboolean Anim = GL_TRUE; 3132001f49Smrgstatic GLfloat ClearColor[4] = {0.2, 0.2, 0.9, 0.0}; 3232001f49Smrgstatic GLfloat NearClip = 5.0, FarClip = 25.0, ViewDist = 7.0; 3332001f49Smrgstatic double PrevTime = -1; 3432001f49Smrg 3532001f49Smrgstruct box { 3632001f49Smrg float tx, ty, tz; 3732001f49Smrg float rx, ry, rz, ra; 3832001f49Smrg float sx, sy, sz; 3932001f49Smrg float color[4]; 4032001f49Smrg}; 4132001f49Smrg 4232001f49Smrg#define NUM_BOXES 25 4332001f49Smrg 4432001f49Smrgstruct box Boxes[NUM_BOXES]; 4532001f49Smrg 4632001f49Smrg 4732001f49Smrg/* Return random float in [0,1] */ 4832001f49Smrgstatic float 4932001f49SmrgRandom(void) 5032001f49Smrg{ 5132001f49Smrg int i = rand(); 5232001f49Smrg return (float) (i % 1000) / 1000.0; 5332001f49Smrg} 5432001f49Smrg 5532001f49Smrg 5632001f49Smrgstatic void 5732001f49SmrgMakeBoxes(void) 5832001f49Smrg{ 5932001f49Smrg int i; 6032001f49Smrg for (i = 0; i < NUM_BOXES; i++) { 6132001f49Smrg Boxes[i].tx = -1.0 + 2.0 * Random(); 6232001f49Smrg Boxes[i].ty = -1.0 + 2.0 * Random(); 6332001f49Smrg Boxes[i].tz = -1.0 + 2.0 * Random(); 6432001f49Smrg Boxes[i].sx = 0.1 + Random() * 0.4; 6532001f49Smrg Boxes[i].sy = 0.1 + Random() * 0.4; 6632001f49Smrg Boxes[i].sz = 0.1 + Random() * 0.4; 6732001f49Smrg Boxes[i].rx = Random(); 6832001f49Smrg Boxes[i].ry = Random(); 6932001f49Smrg Boxes[i].rz = Random(); 7032001f49Smrg Boxes[i].ra = Random() * 360.0; 7132001f49Smrg Boxes[i].color[0] = Random(); 7232001f49Smrg Boxes[i].color[1] = Random(); 7332001f49Smrg Boxes[i].color[2] = Random(); 7432001f49Smrg Boxes[i].color[3] = 1.0; 7532001f49Smrg } 7632001f49Smrg} 7732001f49Smrg 7832001f49Smrg 7932001f49Smrgstatic void 8032001f49SmrgDrawBoxes(void) 8132001f49Smrg{ 8232001f49Smrg int i; 8332001f49Smrg for (i = 0; i < NUM_BOXES; i++) { 8432001f49Smrg glPushMatrix(); 8532001f49Smrg glTranslatef(Boxes[i].tx, Boxes[i].ty, Boxes[i].tz); 8632001f49Smrg glRotatef(Boxes[i].ra, Boxes[i].rx, Boxes[i].ry, Boxes[i].rz); 8732001f49Smrg glScalef(Boxes[i].sx, Boxes[i].sy, Boxes[i].sz); 8832001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Boxes[i].color); 8932001f49Smrg glutSolidCube(1.0); 9032001f49Smrg glPopMatrix(); 9132001f49Smrg } 9232001f49Smrg} 9332001f49Smrg 9432001f49Smrg 9532001f49Smrgstatic void 9632001f49SmrgIdle(void) 9732001f49Smrg{ 9832001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) * 0.001; 9932001f49Smrg if (PrevTime < 0.0) 10032001f49Smrg PrevTime = t; 10132001f49Smrg dt = t - PrevTime; 10232001f49Smrg PrevTime = t; 10332001f49Smrg Xrot += 16.0 * dt; 10432001f49Smrg Yrot += 12.0 * dt; 10532001f49Smrg Zrot += 8.0 * dt; 10632001f49Smrg glutPostRedisplay(); 10732001f49Smrg} 10832001f49Smrg 10932001f49Smrg 11032001f49Smrgstatic void 11132001f49SmrgDraw(void) 11232001f49Smrg{ 11332001f49Smrg if (Mode == FLICKER) { 11432001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 11532001f49Smrg } 11632001f49Smrg else { 11732001f49Smrg /* don't clear color buffer */ 11832001f49Smrg glClear(GL_DEPTH_BUFFER_BIT); 11932001f49Smrg /* update Z buffer only */ 12032001f49Smrg glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 12132001f49Smrg } 12232001f49Smrg 12332001f49Smrg glPushMatrix(); 12432001f49Smrg glRotatef(Xrot, 1, 0, 0); 12532001f49Smrg glRotatef(Yrot, 0, 1, 0); 12632001f49Smrg glRotatef(Zrot, 0, 0, 1); 12732001f49Smrg 12832001f49Smrg DrawBoxes(); 12932001f49Smrg 13032001f49Smrg if (Mode == NO_FLICKER) { 13132001f49Smrg /* update color buffer now */ 13232001f49Smrg glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 13332001f49Smrg glDepthFunc(GL_EQUAL); 13432001f49Smrg DrawBoxes(); 13532001f49Smrg glDepthFunc(GL_LESS); 13632001f49Smrg } 13732001f49Smrg 13832001f49Smrg glPopMatrix(); 13932001f49Smrg 14032001f49Smrg if (Mode == NO_FLICKER) { 14132001f49Smrg /* "clear" the untouched pixels now. 14232001f49Smrg * Note: if you comment-out this code you'll see something interesting. 14332001f49Smrg */ 14432001f49Smrg GLfloat x = FarClip / NearClip; 14532001f49Smrg GLfloat z = -(FarClip - ViewDist - 1.0); 14632001f49Smrg glDisable(GL_LIGHTING); 14732001f49Smrg glColor4fv(ClearColor); 14832001f49Smrg glBegin(GL_POLYGON); 14932001f49Smrg glVertex3f(-x, -x, z); 15032001f49Smrg glVertex3f( x, -x, z); 15132001f49Smrg glVertex3f( x, x, z); 15232001f49Smrg glVertex3f(-x, x, z); 15332001f49Smrg glEnd(); 15432001f49Smrg glEnable(GL_LIGHTING); 15532001f49Smrg } 15632001f49Smrg 15732001f49Smrg /* This is where you'd normally do SwapBuffers */ 15832001f49Smrg glFinish(); 15932001f49Smrg} 16032001f49Smrg 16132001f49Smrg 16232001f49Smrgstatic void 16332001f49SmrgReshape(int width, int height) 16432001f49Smrg{ 16532001f49Smrg glViewport(0, 0, width, height); 16632001f49Smrg glMatrixMode(GL_PROJECTION); 16732001f49Smrg glLoadIdentity(); 16832001f49Smrg glFrustum(-1.0, 1.0, -1.0, 1.0, NearClip, FarClip); 16932001f49Smrg glMatrixMode(GL_MODELVIEW); 17032001f49Smrg glLoadIdentity(); 17132001f49Smrg glTranslatef(0.0, 0.0, -ViewDist); 17232001f49Smrg} 17332001f49Smrg 17432001f49Smrg 17532001f49Smrgstatic void 17632001f49SmrgKey(unsigned char key, int x, int y) 17732001f49Smrg{ 17832001f49Smrg (void) x; 17932001f49Smrg (void) y; 18032001f49Smrg switch (key) { 18132001f49Smrg case 'a': 18232001f49Smrg Anim = !Anim; 18332001f49Smrg if (Anim) 18432001f49Smrg glutIdleFunc(Idle); 18532001f49Smrg else 18632001f49Smrg glutIdleFunc(NULL); 18732001f49Smrg PrevTime = -1; 18832001f49Smrg break; 18932001f49Smrg case 'm': 19032001f49Smrg Mode = !Mode; 19132001f49Smrg break; 19232001f49Smrg case 'b': 19332001f49Smrg MakeBoxes(); 19432001f49Smrg break; 19532001f49Smrg case 27: 19632001f49Smrg exit(0); 19732001f49Smrg break; 19832001f49Smrg } 19932001f49Smrg glutPostRedisplay(); 20032001f49Smrg} 20132001f49Smrg 20232001f49Smrg 20332001f49Smrgstatic void 20432001f49SmrgSpecialKey(int key, int x, int y) 20532001f49Smrg{ 20632001f49Smrg const GLfloat step = 3.0; 20732001f49Smrg (void) x; 20832001f49Smrg (void) y; 20932001f49Smrg switch (key) { 21032001f49Smrg case GLUT_KEY_UP: 21132001f49Smrg Xrot -= step; 21232001f49Smrg break; 21332001f49Smrg case GLUT_KEY_DOWN: 21432001f49Smrg Xrot += step; 21532001f49Smrg break; 21632001f49Smrg case GLUT_KEY_LEFT: 21732001f49Smrg Yrot -= step; 21832001f49Smrg break; 21932001f49Smrg case GLUT_KEY_RIGHT: 22032001f49Smrg Yrot += step; 22132001f49Smrg break; 22232001f49Smrg } 22332001f49Smrg glutPostRedisplay(); 22432001f49Smrg} 22532001f49Smrg 22632001f49Smrg 22732001f49Smrgstatic void 22832001f49SmrgInit(void) 22932001f49Smrg{ 23032001f49Smrg glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]); 23132001f49Smrg glEnable(GL_DEPTH_TEST); 23232001f49Smrg glEnable(GL_LIGHTING); 23332001f49Smrg glEnable(GL_LIGHT0); 23432001f49Smrg glEnable(GL_CULL_FACE); 23532001f49Smrg glEnable(GL_NORMALIZE); 23632001f49Smrg MakeBoxes(); 23732001f49Smrg} 23832001f49Smrg 23932001f49Smrg 24032001f49Smrgstatic void 24132001f49SmrgUsage(void) 24232001f49Smrg{ 24332001f49Smrg printf("Keys:\n"); 24432001f49Smrg printf(" m - toggle drawing mode (flicker vs. no flicker)\n"); 24532001f49Smrg printf(" a - toggle animation\n"); 24632001f49Smrg printf(" b - generate new boxes\n"); 24732001f49Smrg printf(" ARROWS - rotate scene\n"); 24832001f49Smrg printf(" ESC - exit\n"); 24932001f49Smrg} 25032001f49Smrg 25132001f49Smrg 25232001f49Smrgint 25332001f49Smrgmain(int argc, char *argv[]) 25432001f49Smrg{ 25532001f49Smrg glutInit(&argc, argv); 25632001f49Smrg glutInitWindowSize(800, 800); 25732001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH); 25832001f49Smrg glutCreateWindow(argv[0]); 25932001f49Smrg glutReshapeFunc(Reshape); 26032001f49Smrg glutKeyboardFunc(Key); 26132001f49Smrg glutSpecialFunc(SpecialKey); 26232001f49Smrg glutDisplayFunc(Draw); 26332001f49Smrg if (Anim) 26432001f49Smrg glutIdleFunc(Idle); 26532001f49Smrg Init(); 26632001f49Smrg Usage(); 26732001f49Smrg glutMainLoop(); 26832001f49Smrg return 0; 26932001f49Smrg} 270