132001f49Smrg/**
232001f49Smrg * Dissolve between two images using randomized/patterned stencil buffer
332001f49Smrg * and varying stencil ref.
432001f49Smrg *
532001f49Smrg * Brian Paul
632001f49Smrg * 29 Jan 2010
732001f49Smrg */
832001f49Smrg
932001f49Smrg
1032001f49Smrg#include <stdio.h>
1132001f49Smrg#include <stdlib.h>
1232001f49Smrg#include <string.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include "glut_wrap.h"
1532001f49Smrg#include "readtex.h"
1632001f49Smrg
1732001f49Smrg#define FILE1 DEMOS_DATA_DIR "bw.rgb"
1832001f49Smrg#define FILE2 DEMOS_DATA_DIR "arch.rgb"
1932001f49Smrg
2032001f49Smrg
2132001f49Smrgstatic int Win;
2232001f49Smrgstatic int WinWidth = 400, WinHeight = 400;
2332001f49Smrgstatic GLboolean Anim = GL_TRUE;
2432001f49Smrg
2532001f49Smrgstatic int ImgWidth[2], ImgHeight[2];
2632001f49Smrgstatic GLenum ImgFormat[2];
2732001f49Smrgstatic GLubyte *Image[2];
2832001f49Smrgstatic GLfloat ScaleX[2], ScaleY[2];
2932001f49Smrg
3032001f49Smrgstatic GLubyte StencilRef = 0;
3132001f49Smrg
3232001f49Smrgstatic int Mode = 0;
3332001f49Smrg
3432001f49Smrg
3532001f49Smrgstatic void
3632001f49SmrgIdle(void)
3732001f49Smrg{
3832001f49Smrg   StencilRef = (GLint) (glutGet(GLUT_ELAPSED_TIME) / 10);
3932001f49Smrg   glutPostRedisplay();
4032001f49Smrg}
4132001f49Smrg
4232001f49Smrg
4332001f49Smrgstatic void
4432001f49SmrgFillRandomPixels(GLubyte *b)
4532001f49Smrg{
4632001f49Smrg   int i;
4732001f49Smrg   for (i = 0; i < WinWidth * WinHeight; i++) {
4832001f49Smrg      b[i] = rand() & 0xff;
4932001f49Smrg   }
5032001f49Smrg}
5132001f49Smrg
5232001f49Smrg
5332001f49Smrgstatic void
5432001f49SmrgFillRandomRects(GLubyte *b)
5532001f49Smrg{
5632001f49Smrg   int i;
5732001f49Smrg
5832001f49Smrg   memset(b, 0, WinWidth * WinHeight);
5932001f49Smrg
6032001f49Smrg   for (i = 0; i < 256; i++) {
6132001f49Smrg      int x = rand() % WinWidth;
6232001f49Smrg      int y = rand() % WinHeight;
6332001f49Smrg      int w = rand() % 60;
6432001f49Smrg      int h = rand() % 60;
6532001f49Smrg      int ix, iy;
6632001f49Smrg
6732001f49Smrg      if (x + w > WinWidth)
6832001f49Smrg         w = WinWidth - x;
6932001f49Smrg      if (y + h > WinHeight)
7032001f49Smrg         h = WinHeight - y;
7132001f49Smrg
7232001f49Smrg      for (iy = 0; iy < h; iy++) {
7332001f49Smrg         for (ix = 0; ix < w; ix++) {
7432001f49Smrg            int p = (y + iy) * WinWidth + x + ix;
7532001f49Smrg            b[p] = i;
7632001f49Smrg         }
7732001f49Smrg      }
7832001f49Smrg   }
7932001f49Smrg}
8032001f49Smrg
8132001f49Smrg
8232001f49Smrgstatic void
8332001f49SmrgFillWipe(GLubyte *b)
8432001f49Smrg{
8532001f49Smrg   int iy, ix;
8632001f49Smrg
8732001f49Smrg   memset(b, 0, WinWidth * WinHeight);
8832001f49Smrg
8932001f49Smrg   for (iy = 0; iy < WinHeight; iy++) {
9032001f49Smrg      for (ix = 0; ix < WinWidth; ix++) {
9132001f49Smrg         int p = iy * WinWidth + ix;
9232001f49Smrg         b[p] = 2 * ix + iy / 2;
9332001f49Smrg      }
9432001f49Smrg   }
9532001f49Smrg}
9632001f49Smrg
9732001f49Smrg
9832001f49Smrgstatic void
9932001f49SmrgFillMoire(GLubyte *b)
10032001f49Smrg{
10132001f49Smrg   int iy, ix;
10232001f49Smrg
10332001f49Smrg   memset(b, 0, WinWidth * WinHeight);
10432001f49Smrg
10532001f49Smrg   for (iy = 0; iy < WinHeight; iy++) {
10632001f49Smrg      for (ix = 0; ix < WinWidth; ix++) {
10732001f49Smrg         int p = iy * WinWidth + ix;
10832001f49Smrg         b[p] = (ix / 2) * (ix / 2) - (iy / 2) * (iy / 2);
10932001f49Smrg      }
11032001f49Smrg   }
11132001f49Smrg}
11232001f49Smrg
11332001f49Smrg
11432001f49Smrgstatic void
11532001f49SmrgFillWaves(GLubyte *b)
11632001f49Smrg{
11732001f49Smrg   int iy, ix;
11832001f49Smrg
11932001f49Smrg   memset(b, 0, WinWidth * WinHeight);
12032001f49Smrg
12132001f49Smrg   for (iy = 0; iy < WinHeight; iy++) {
12232001f49Smrg      for (ix = 0; ix < WinWidth; ix++) {
12332001f49Smrg         int p = iy * WinWidth + ix;
12432001f49Smrg         float x = 8.0 * 3.1415 * ix / (float) WinWidth;
12532001f49Smrg         b[p] = (int) (25.0 * sin(x) ) - iy*2;
12632001f49Smrg      }
12732001f49Smrg   }
12832001f49Smrg}
12932001f49Smrg
13032001f49Smrg
13132001f49Smrgtypedef void (*FillFunc)(GLubyte *b);
13232001f49Smrg
13332001f49Smrg
13432001f49Smrgstatic FillFunc Funcs[] = {
13532001f49Smrg   FillRandomPixels,
13632001f49Smrg   FillRandomRects,
13732001f49Smrg   FillWipe,
13832001f49Smrg   FillMoire,
13932001f49Smrg   FillWaves
14032001f49Smrg};
14132001f49Smrg
14232001f49Smrg#define NUM_MODES (sizeof(Funcs) / sizeof(Funcs[0]))
14332001f49Smrg
14432001f49Smrg
14532001f49Smrg
14632001f49Smrgstatic void
14732001f49SmrgInitStencilBuffer(void)
14832001f49Smrg{
14932001f49Smrg   GLubyte *b = malloc(WinWidth * WinHeight);
15032001f49Smrg
15132001f49Smrg   Funcs[Mode](b);
15232001f49Smrg
15332001f49Smrg   glStencilFunc(GL_ALWAYS, 0, ~0);
15432001f49Smrg   glPixelZoom(1.0, 1.0);
15532001f49Smrg   glDrawPixels(WinWidth, WinHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, b);
15632001f49Smrg
15732001f49Smrg   free(b);
15832001f49Smrg}
15932001f49Smrg
16032001f49Smrg
16132001f49Smrgstatic void
16232001f49SmrgDraw(void)
16332001f49Smrg{
16432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
16532001f49Smrg
16632001f49Smrg   glPixelZoom(ScaleX[0], ScaleY[0]);
16732001f49Smrg   glStencilFunc(GL_LESS, StencilRef, ~0);
16832001f49Smrg   glDrawPixels(ImgWidth[0], ImgHeight[0], ImgFormat[0], GL_UNSIGNED_BYTE, Image[0]);
16932001f49Smrg
17032001f49Smrg   glPixelZoom(ScaleX[1], ScaleY[1]);
17132001f49Smrg   glStencilFunc(GL_GEQUAL, StencilRef, ~0);
17232001f49Smrg   glDrawPixels(ImgWidth[1], ImgHeight[1], ImgFormat[1], GL_UNSIGNED_BYTE, Image[1]);
17332001f49Smrg
17432001f49Smrg   glutSwapBuffers();
17532001f49Smrg}
17632001f49Smrg
17732001f49Smrg
17832001f49Smrgstatic void
17932001f49SmrgReshape(int width, int height)
18032001f49Smrg{
18132001f49Smrg   WinWidth = width;
18232001f49Smrg   WinHeight = height;
18332001f49Smrg   glViewport(0, 0, width, height);
18432001f49Smrg   glMatrixMode(GL_PROJECTION);
18532001f49Smrg   glLoadIdentity();
18632001f49Smrg   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
18732001f49Smrg   glMatrixMode(GL_MODELVIEW);
18832001f49Smrg   glLoadIdentity();
18932001f49Smrg   glTranslatef(0.0, 0.0, -15.0);
19032001f49Smrg
19132001f49Smrg   InitStencilBuffer();
19232001f49Smrg
19332001f49Smrg   ScaleX[0] = (float) width / ImgWidth[0];
19432001f49Smrg   ScaleY[0] = (float) height / ImgHeight[0];
19532001f49Smrg
19632001f49Smrg   ScaleX[1] = (float) width / ImgWidth[1];
19732001f49Smrg   ScaleY[1] = (float) height / ImgHeight[1];
19832001f49Smrg}
19932001f49Smrg
20032001f49Smrg
20132001f49Smrgstatic void
20232001f49SmrgKey(unsigned char key, int x, int y)
20332001f49Smrg{
20432001f49Smrg   (void) x;
20532001f49Smrg   (void) y;
20632001f49Smrg   switch (key) {
20732001f49Smrg   case 'a':
20832001f49Smrg   case ' ':
20932001f49Smrg      Anim = !Anim;
21032001f49Smrg      if (Anim)
21132001f49Smrg         glutIdleFunc(Idle);
21232001f49Smrg      else
21332001f49Smrg         glutIdleFunc(NULL);
21432001f49Smrg      break;
21532001f49Smrg   case 'i':
21632001f49Smrg      InitStencilBuffer();
21732001f49Smrg      break;
21832001f49Smrg   case '-':
21932001f49Smrg      StencilRef--;
22032001f49Smrg      break;
22132001f49Smrg   case '+':
22232001f49Smrg      StencilRef++;
22332001f49Smrg      break;
22432001f49Smrg   case 'm':
22532001f49Smrg      Mode = (Mode + 1) % NUM_MODES;
22632001f49Smrg      InitStencilBuffer();
22732001f49Smrg      break;
22832001f49Smrg   case 27:
22932001f49Smrg      glutDestroyWindow(Win);
23032001f49Smrg      exit(0);
23132001f49Smrg      break;
23232001f49Smrg   }
23332001f49Smrg   glutPostRedisplay();
23432001f49Smrg}
23532001f49Smrg
23632001f49Smrg
23732001f49Smrg
23832001f49Smrgstatic void
23932001f49SmrgInit(void)
24032001f49Smrg{
24132001f49Smrg   Image[0] = LoadRGBImage(FILE1, &ImgWidth[0], &ImgHeight[0], &ImgFormat[0]);
24232001f49Smrg   if (!Image[0]) {
24332001f49Smrg      printf("Couldn't read %s\n", FILE1);
24432001f49Smrg      exit(0);
24532001f49Smrg   }
24632001f49Smrg
24732001f49Smrg   Image[1] = LoadRGBImage(FILE2, &ImgWidth[1], &ImgHeight[1], &ImgFormat[1]);
24832001f49Smrg   if (!Image[1]) {
24932001f49Smrg      printf("Couldn't read %s\n", FILE2);
25032001f49Smrg      exit(0);
25132001f49Smrg   }
25232001f49Smrg
25332001f49Smrg   glEnable(GL_STENCIL_TEST);
25432001f49Smrg   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
25532001f49Smrg
25632001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
25732001f49Smrg}
25832001f49Smrg
25932001f49Smrg
26032001f49Smrgint
26132001f49Smrgmain(int argc, char *argv[])
26232001f49Smrg{
26332001f49Smrg   glutInitWindowSize(WinWidth, WinHeight);
26432001f49Smrg   glutInit(&argc, argv);
26532001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
26632001f49Smrg   Win = glutCreateWindow(argv[0]);
26732001f49Smrg   glutReshapeFunc(Reshape);
26832001f49Smrg   glutKeyboardFunc(Key);
26932001f49Smrg   glutDisplayFunc(Draw);
27032001f49Smrg   if (Anim)
27132001f49Smrg      glutIdleFunc(Idle);
27232001f49Smrg   Init();
27332001f49Smrg
27432001f49Smrg   printf("Keys:\n");
27532001f49Smrg   printf("  a/SPACE  toggle animation\n");
27632001f49Smrg   printf("  +/-      single step\n");
27732001f49Smrg   printf("  i        re-init pattern\n");
27832001f49Smrg   printf("  m        change pattern/dissolve mode\n");
27932001f49Smrg   printf("  ESC      exit\n");
28032001f49Smrg
28132001f49Smrg   glutMainLoop();
28232001f49Smrg   return 0;
28332001f49Smrg}
284