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 "glut_wrap.h"
15 #include "readtex.h"
16 
17 #define FILE1 DEMOS_DATA_DIR "bw.rgb"
18 #define FILE2 DEMOS_DATA_DIR "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
Idle(void)36 Idle(void)
37 {
38    StencilRef = (GLint) (glutGet(GLUT_ELAPSED_TIME) / 10);
39    glutPostRedisplay();
40 }
41 
42 
43 static void
FillRandomPixels(GLubyte * b)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
FillRandomRects(GLubyte * b)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
FillWipe(GLubyte * b)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
FillMoire(GLubyte * b)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
FillWaves(GLubyte * b)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
InitStencilBuffer(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
Draw(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
Reshape(int width,int height)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
Key(unsigned char key,int x,int y)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
Init(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
main(int argc,char * argv[])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 }
284