2 * Demo of (nearly) flicker-free drawing with a single color buffer.
4 * Basically, draw the scene into the Z buffer first, then draw the
5 * scene into the color buffer. Finally, "clear" the background by
6 * setting the fragments we didn't hit earlier.
8 * This won't work if you need blending. The technique works best
9 * when the scene is relatively simple and can be rendered quickly
10 * (i.e. with hardware), and when the objects don't move too much from
11 * one frame to the next.
16 * See Mesa license for terms.
22 #include "glut_wrap.h"
28 static GLint Mode
= NO_FLICKER
;
29 static GLfloat Xrot
= 0, Yrot
= 0, Zrot
= 0;
30 static GLboolean Anim
= GL_TRUE
;
31 static GLfloat ClearColor
[4] = {0.2, 0.2, 0.9, 0.0};
32 static GLfloat NearClip
= 5.0, FarClip
= 25.0, ViewDist
= 7.0;
33 static double PrevTime
= -1;
44 struct box Boxes
[NUM_BOXES
];
47 /* Return random float in [0,1] */
52 return (float) (i
% 1000) / 1000.0;
60 for (i
= 0; i
< NUM_BOXES
; i
++) {
61 Boxes
[i
].tx
= -1.0 + 2.0 * Random();
62 Boxes
[i
].ty
= -1.0 + 2.0 * Random();
63 Boxes
[i
].tz
= -1.0 + 2.0 * Random();
64 Boxes
[i
].sx
= 0.1 + Random() * 0.4;
65 Boxes
[i
].sy
= 0.1 + Random() * 0.4;
66 Boxes
[i
].sz
= 0.1 + Random() * 0.4;
67 Boxes
[i
].rx
= Random();
68 Boxes
[i
].ry
= Random();
69 Boxes
[i
].rz
= Random();
70 Boxes
[i
].ra
= Random() * 360.0;
71 Boxes
[i
].color
[0] = Random();
72 Boxes
[i
].color
[1] = Random();
73 Boxes
[i
].color
[2] = Random();
74 Boxes
[i
].color
[3] = 1.0;
83 for (i
= 0; i
< NUM_BOXES
; i
++) {
85 glTranslatef(Boxes
[i
].tx
, Boxes
[i
].ty
, Boxes
[i
].tz
);
86 glRotatef(Boxes
[i
].ra
, Boxes
[i
].rx
, Boxes
[i
].ry
, Boxes
[i
].rz
);
87 glScalef(Boxes
[i
].sx
, Boxes
[i
].sy
, Boxes
[i
].sz
);
88 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, Boxes
[i
].color
);
98 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) * 0.001;
113 if (Mode
== FLICKER
) {
114 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
117 /* don't clear color buffer */
118 glClear(GL_DEPTH_BUFFER_BIT
);
119 /* update Z buffer only */
120 glColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
124 glRotatef(Xrot
, 1, 0, 0);
125 glRotatef(Yrot
, 0, 1, 0);
126 glRotatef(Zrot
, 0, 0, 1);
130 if (Mode
== NO_FLICKER
) {
131 /* update color buffer now */
132 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
133 glDepthFunc(GL_EQUAL
);
135 glDepthFunc(GL_LESS
);
140 if (Mode
== NO_FLICKER
) {
141 /* "clear" the untouched pixels now.
142 * Note: if you comment-out this code you'll see something interesting.
144 GLfloat x
= FarClip
/ NearClip
;
145 GLfloat z
= -(FarClip
- ViewDist
- 1.0);
146 glDisable(GL_LIGHTING
);
147 glColor4fv(ClearColor
);
149 glVertex3f(-x
, -x
, z
);
150 glVertex3f( x
, -x
, z
);
151 glVertex3f( x
, x
, z
);
152 glVertex3f(-x
, x
, z
);
154 glEnable(GL_LIGHTING
);
157 /* This is where you'd normally do SwapBuffers */
163 Reshape(int width
, int height
)
165 glViewport(0, 0, width
, height
);
166 glMatrixMode(GL_PROJECTION
);
168 glFrustum(-1.0, 1.0, -1.0, 1.0, NearClip
, FarClip
);
169 glMatrixMode(GL_MODELVIEW
);
171 glTranslatef(0.0, 0.0, -ViewDist
);
176 Key(unsigned char key
, int x
, int y
)
204 SpecialKey(int key
, int x
, int y
)
206 const GLfloat step
= 3.0;
230 glClearColor(ClearColor
[0], ClearColor
[1], ClearColor
[2], ClearColor
[3]);
231 glEnable(GL_DEPTH_TEST
);
232 glEnable(GL_LIGHTING
);
234 glEnable(GL_CULL_FACE
);
235 glEnable(GL_NORMALIZE
);
244 printf(" m - toggle drawing mode (flicker vs. no flicker)\n");
245 printf(" a - toggle animation\n");
246 printf(" b - generate new boxes\n");
247 printf(" ARROWS - rotate scene\n");
248 printf(" ESC - exit\n");
253 main(int argc
, char *argv
[])
255 glutInit(&argc
, argv
);
256 glutInitWindowSize(800, 800);
257 glutInitDisplayMode(GLUT_RGB
| GLUT_SINGLE
| GLUT_DEPTH
);
258 glutCreateWindow(argv
[0]);
259 glutReshapeFunc(Reshape
);
260 glutKeyboardFunc(Key
);
261 glutSpecialFunc(SpecialKey
);
262 glutDisplayFunc(Draw
);