Merge branch '7.8'
[mesa.git] / progs / demos / dissolve.c
1 /**
2 * Dissolve between two images using randomized/patterned stencil buffer
3 * and varying stencil ref.
4 *
5 * Brian Paul
6 * 29 Jan 2010
7 */
8
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <math.h>
14 #include <GL/glut.h>
15 #include "readtex.h"
16
17 #define FILE1 "../images/bw.rgb"
18 #define FILE2 "../images/arch.rgb"
19
20
21 static int Win;
22 static int WinWidth = 400, WinHeight = 400;
23 static GLboolean Anim = GL_TRUE;
24
25 static int ImgWidth[2], ImgHeight[2];
26 static GLenum ImgFormat[2];
27 static GLubyte *Image[2];
28 static GLfloat ScaleX[2], ScaleY[2];
29
30 static GLubyte StencilRef = 0;
31
32 static int Mode = 0;
33
34
35 static void
36 Idle(void)
37 {
38 StencilRef = (GLint) (glutGet(GLUT_ELAPSED_TIME) / 10);
39 glutPostRedisplay();
40 }
41
42
43 static void
44 FillRandomPixels(GLubyte *b)
45 {
46 int i;
47 for (i = 0; i < WinWidth * WinHeight; i++) {
48 b[i] = rand() & 0xff;
49 }
50 }
51
52
53 static void
54 FillRandomRects(GLubyte *b)
55 {
56 int i;
57
58 memset(b, 0, WinWidth * WinHeight);
59
60 for (i = 0; i < 256; i++) {
61 int x = rand() % WinWidth;
62 int y = rand() % WinHeight;
63 int w = rand() % 60;
64 int h = rand() % 60;
65 int ix, iy;
66
67 if (x + w > WinWidth)
68 w = WinWidth - x;
69 if (y + h > WinHeight)
70 h = WinHeight - y;
71
72 for (iy = 0; iy < h; iy++) {
73 for (ix = 0; ix < w; ix++) {
74 int p = (y + iy) * WinWidth + x + ix;
75 b[p] = i;
76 }
77 }
78 }
79 }
80
81
82 static void
83 FillWipe(GLubyte *b)
84 {
85 int iy, ix;
86
87 memset(b, 0, WinWidth * WinHeight);
88
89 for (iy = 0; iy < WinHeight; iy++) {
90 for (ix = 0; ix < WinWidth; ix++) {
91 int p = iy * WinWidth + ix;
92 b[p] = 2 * ix + iy / 2;
93 }
94 }
95 }
96
97
98 static void
99 FillMoire(GLubyte *b)
100 {
101 int iy, ix;
102
103 memset(b, 0, WinWidth * WinHeight);
104
105 for (iy = 0; iy < WinHeight; iy++) {
106 for (ix = 0; ix < WinWidth; ix++) {
107 int p = iy * WinWidth + ix;
108 b[p] = (ix / 2) * (ix / 2) - (iy / 2) * (iy / 2);
109 }
110 }
111 }
112
113
114 static void
115 FillWaves(GLubyte *b)
116 {
117 int iy, ix;
118
119 memset(b, 0, WinWidth * WinHeight);
120
121 for (iy = 0; iy < WinHeight; iy++) {
122 for (ix = 0; ix < WinWidth; ix++) {
123 int p = iy * WinWidth + ix;
124 float x = 8.0 * 3.1415 * ix / (float) WinWidth;
125 b[p] = (int) (25.0 * sin(x) ) - iy*2;
126 }
127 }
128 }
129
130
131 typedef void (*FillFunc)(GLubyte *b);
132
133
134 static FillFunc Funcs[] = {
135 FillRandomPixels,
136 FillRandomRects,
137 FillWipe,
138 FillMoire,
139 FillWaves
140 };
141
142 #define NUM_MODES (sizeof(Funcs) / sizeof(Funcs[0]))
143
144
145
146 static void
147 InitStencilBuffer(void)
148 {
149 GLubyte *b = malloc(WinWidth * WinHeight);
150
151 Funcs[Mode](b);
152
153 glStencilFunc(GL_ALWAYS, 0, ~0);
154 glPixelZoom(1.0, 1.0);
155 glDrawPixels(WinWidth, WinHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, b);
156
157 free(b);
158 }
159
160
161 static void
162 Draw(void)
163 {
164 glClear(GL_COLOR_BUFFER_BIT);
165
166 glPixelZoom(ScaleX[0], ScaleY[0]);
167 glStencilFunc(GL_LESS, StencilRef, ~0);
168 glDrawPixels(ImgWidth[0], ImgHeight[0], ImgFormat[0], GL_UNSIGNED_BYTE, Image[0]);
169
170 glPixelZoom(ScaleX[1], ScaleY[1]);
171 glStencilFunc(GL_GEQUAL, StencilRef, ~0);
172 glDrawPixels(ImgWidth[1], ImgHeight[1], ImgFormat[1], GL_UNSIGNED_BYTE, Image[1]);
173
174 glutSwapBuffers();
175 }
176
177
178 static void
179 Reshape(int width, int height)
180 {
181 WinWidth = width;
182 WinHeight = height;
183 glViewport(0, 0, width, height);
184 glMatrixMode(GL_PROJECTION);
185 glLoadIdentity();
186 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
187 glMatrixMode(GL_MODELVIEW);
188 glLoadIdentity();
189 glTranslatef(0.0, 0.0, -15.0);
190
191 InitStencilBuffer();
192
193 ScaleX[0] = (float) width / ImgWidth[0];
194 ScaleY[0] = (float) height / ImgHeight[0];
195
196 ScaleX[1] = (float) width / ImgWidth[1];
197 ScaleY[1] = (float) height / ImgHeight[1];
198 }
199
200
201 static void
202 Key(unsigned char key, int x, int y)
203 {
204 (void) x;
205 (void) y;
206 switch (key) {
207 case 'a':
208 case ' ':
209 Anim = !Anim;
210 if (Anim)
211 glutIdleFunc(Idle);
212 else
213 glutIdleFunc(NULL);
214 break;
215 case 'i':
216 InitStencilBuffer();
217 break;
218 case '-':
219 StencilRef--;
220 break;
221 case '+':
222 StencilRef++;
223 break;
224 case 'm':
225 Mode = (Mode + 1) % NUM_MODES;
226 InitStencilBuffer();
227 break;
228 case 27:
229 glutDestroyWindow(Win);
230 exit(0);
231 break;
232 }
233 glutPostRedisplay();
234 }
235
236
237
238 static void
239 Init(void)
240 {
241 Image[0] = LoadRGBImage(FILE1, &ImgWidth[0], &ImgHeight[0], &ImgFormat[0]);
242 if (!Image[0]) {
243 printf("Couldn't read %s\n", FILE1);
244 exit(0);
245 }
246
247 Image[1] = LoadRGBImage(FILE2, &ImgWidth[1], &ImgHeight[1], &ImgFormat[1]);
248 if (!Image[1]) {
249 printf("Couldn't read %s\n", FILE2);
250 exit(0);
251 }
252
253 glEnable(GL_STENCIL_TEST);
254 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
255
256 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
257 }
258
259
260 int
261 main(int argc, char *argv[])
262 {
263 glutInitWindowSize(WinWidth, WinHeight);
264 glutInit(&argc, argv);
265 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
266 Win = glutCreateWindow(argv[0]);
267 glutReshapeFunc(Reshape);
268 glutKeyboardFunc(Key);
269 glutDisplayFunc(Draw);
270 if (Anim)
271 glutIdleFunc(Idle);
272 Init();
273
274 printf("Keys:\n");
275 printf(" a/SPACE toggle animation\n");
276 printf(" +/- single step\n");
277 printf(" i re-init pattern\n");
278 printf(" m change pattern/dissolve mode\n");
279 printf(" ESC exit\n");
280
281 glutMainLoop();
282 return 0;
283 }