1/**
2 * Test Z compositing with glDrawPixels(GL_DEPTH_COMPONENT) and stencil test.
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <math.h>
8#include <GL/glew.h>
9#include "glut_wrap.h"
10
11
12static int Win;
13static GLfloat Xrot = 0, Yrot = 0, Zpos = 6;
14static GLboolean Anim = GL_FALSE;
15
16static int Width = 400, Height = 200;
17static GLfloat *Zimg;
18static GLubyte *Cimg;
19static GLboolean showZ = 0;
20
21
22static void
23Idle(void)
24{
25   Xrot += 3.0;
26   Yrot += 4.0;
27   glutPostRedisplay();
28}
29
30
31/**
32 * Draw first object, save color+Z images
33 */
34static void
35DrawFirst(void)
36{
37   static const GLfloat red[4] = { 1.0, 0.0, 0.0, 0.0 };
38
39   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
40
41   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
42
43   glPushMatrix();
44   glTranslatef(-1, 0, 0);
45   glRotatef(45 + Xrot, 1, 0, 0);
46
47   glutSolidTorus(0.75, 2.0, 10, 20);
48
49   glPopMatrix();
50
51   glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
52   glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
53}
54
55
56/**
57 * Draw second object.
58 */
59static void
60DrawSecond(void)
61{
62   static const GLfloat blue[4] = { 0.0, 0.0, 1.0, 0.0 };
63
64   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
65
66   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
67
68   glPushMatrix();
69   glTranslatef(+1, 0, 0);
70   glRotatef(-45 + Xrot, 1, 0, 0);
71
72   glutSolidTorus(0.75, 2.0, 10, 20);
73
74   glPopMatrix();
75}
76
77
78/**
79 * Composite first/saved image over second rendering.
80 */
81static void
82Composite(void)
83{
84   glWindowPos2i(0, 0);
85
86   /* Draw Z values, set stencil where Z test passes */
87   glEnable(GL_STENCIL_TEST);
88   glStencilFunc(GL_ALWAYS, 1, ~0);
89   glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
90   glColorMask(0,0,0,0);
91   glDrawPixels(Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
92   glColorMask(1,1,1,1);
93
94   /* Draw color where stencil==1 */
95   glStencilFunc(GL_EQUAL, 1, ~0);
96   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
97   glDisable(GL_DEPTH_TEST);
98   glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
99   glEnable(GL_DEPTH_TEST);
100
101   glDisable(GL_STENCIL_TEST);
102}
103
104
105static void
106Draw(void)
107{
108   DrawFirst();
109   DrawSecond();
110   Composite();
111   glutSwapBuffers();
112}
113
114
115static void
116Reshape(int width, int height)
117{
118   GLfloat ar = (float) width / height;
119   glViewport(0, 0, width, height);
120   glMatrixMode(GL_PROJECTION);
121   glLoadIdentity();
122   glFrustum(-ar, ar, -1.0, 1.0, 5.0, 30.0);
123   glMatrixMode(GL_MODELVIEW);
124   glLoadIdentity();
125   glTranslatef(0.0, 0.0, -15.0);
126
127   Width = width;
128   Height = height;
129
130   if (Zimg)
131      free(Zimg);
132   if (Cimg)
133      free(Cimg);
134   Zimg = (float *) malloc(width * height * 4);
135   Cimg = (GLubyte *) malloc(width * height * 4);
136}
137
138
139static void
140Key(unsigned char key, int x, int y)
141{
142   const GLfloat step = 1.0;
143   (void) x;
144   (void) y;
145   switch (key) {
146      case 'a':
147         Anim = !Anim;
148         if (Anim)
149            glutIdleFunc(Idle);
150         else
151            glutIdleFunc(NULL);
152         break;
153      case 'd':
154         showZ = !showZ;
155         break;
156      case 'z':
157         Zpos -= step;
158         break;
159      case 'Z':
160         Zpos += step;
161         break;
162      case 27:
163         glutDestroyWindow(Win);
164         exit(0);
165         break;
166   }
167   glutPostRedisplay();
168}
169
170
171static void
172SpecialKey(int key, int x, int y)
173{
174   const GLfloat step = 3.0;
175   (void) x;
176   (void) y;
177   switch (key) {
178      case GLUT_KEY_UP:
179         Xrot -= step;
180         break;
181      case GLUT_KEY_DOWN:
182         Xrot += step;
183         break;
184      case GLUT_KEY_LEFT:
185         Yrot -= step;
186         break;
187      case GLUT_KEY_RIGHT:
188         Yrot += step;
189         break;
190   }
191   glutPostRedisplay();
192}
193
194
195static void
196Init(void)
197{
198   /* setup lighting, etc */
199   glEnable(GL_DEPTH_TEST);
200   glEnable(GL_LIGHTING);
201   glEnable(GL_LIGHT0);
202}
203
204
205int
206main(int argc, char *argv[])
207{
208   glutInit(&argc, argv);
209   glutInitWindowPosition(0, 0);
210   glutInitWindowSize(Width, Height);
211   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
212   Win = glutCreateWindow(argv[0]);
213   glewInit();
214   glutReshapeFunc(Reshape);
215   glutKeyboardFunc(Key);
216   glutSpecialFunc(SpecialKey);
217   glutDisplayFunc(Draw);
218   if (Anim)
219      glutIdleFunc(Idle);
220   Init();
221   glutMainLoop();
222   return 0;
223}
224