1/**
2 * Draw stencil region
3 */
4
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <math.h>
10#include <GL/glew.h>
11#include "glut_wrap.h"
12
13static int Win;
14static int WinWidth = 600, WinHeight = 200;
15static GLfloat Xrot = 0.0, Yrot = 0.0;
16
17#define WIDTH 256
18#define HEIGHT 150
19
20static GLubyte Image[HEIGHT][WIDTH];
21
22
23static void
24DrawStencilPixels(GLint x, GLint y, GLsizei w, GLsizei h,
25                  const GLubyte *stencil)
26{
27   /* This program is run eight times, once for each stencil bit.
28    * The stencil values to draw are found in an 8-bit alpha texture.
29    * We read the texture/stencil value and test if bit 'b' is set.
30    * If the bit is set, result.A will be non-zero.  Finally, use
31    * alpha test and stencil test to update the stencil buffer.
32    *
33    * The basic algorithm for checking if a bit is set is:
34    *   if (is_odd(value / (1 << bit)))
35    *      result is one (or non-zero).
36    *   else
37    *      result is zero.
38    * The program parameter contains two values:
39    *   parm.x = 255 / (1 << bit)
40    *   parm.y = 0.5
41    */
42   static const char *program =
43      "!!ARBfp1.0\n"
44      "PARAM parm = program.local[0]; \n"
45      "TEMP t; \n"
46      "TEX t, fragment.texcoord[0], texture[0], RECT; \n"
47      "# t = t * 255 / bit \n"
48      "MUL t.x, t.a, parm.x; \n"
49      "# t = (int) t \n"
50      "FRC t.y, t.x; \n"
51      "SUB t.x, t.x, t.y; \n"
52      "# t = 5 * 0.5 \n"
53      "MUL t.x, t.x, parm.y; \n"
54      "# alpha = frac(t) \n"
55      "FRC result.color, t.x; \n"
56      "END \n";
57   GLuint prog;
58   GLint bit;
59
60   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
61   glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, w, h, 0,
62                GL_ALPHA, GL_UNSIGNED_BYTE, stencil);
63   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
64   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
65
66   glGenProgramsARB(1, &prog);
67   glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
68   glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
69                      strlen(program), (const GLubyte *) program);
70   glEnable(GL_FRAGMENT_PROGRAM_ARB);
71
72   glPushMatrix();
73   glTranslatef(x, y, 0);
74
75   glEnable(GL_ALPHA_TEST);
76   glAlphaFunc(GL_GREATER, 0.0);
77
78   glEnable(GL_STENCIL_TEST);
79   glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
80
81   for (bit = 0; bit < 8; bit++) {
82      GLuint mask = 1 << bit;
83      glStencilFunc(GL_ALWAYS, 255/*mask*/, mask);
84      glStencilMask(mask);
85
86      glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
87                                   // 1.0 / bit, 0.5, 0.0, 0.0);
88                                   255.0 / mask, 0.5, 0.0, 0.0);
89
90
91      glBegin(GL_TRIANGLE_FAN);
92      glTexCoord2f(0, 0);  glVertex2f(0, 0);
93      glTexCoord2f(w, 0);  glVertex2f(w, 0);
94      glTexCoord2f(w, h);  glVertex2f(w, h);
95      glTexCoord2f(0, h);  glVertex2f(0, h);
96      glEnd();
97   }
98
99   glPopMatrix();
100
101   glDisable(GL_FRAGMENT_PROGRAM_ARB);
102   glDisable(GL_ALPHA_TEST);
103   glDisable(GL_STENCIL_TEST);
104}
105
106
107
108static void
109Draw(void)
110{
111   GLint x0 = 5, y0= 5, x1 = 10 + WIDTH, y1 = 5;
112   GLubyte tmp[HEIGHT][WIDTH];
113   GLint max, i, j;
114
115   glClearColor(0.2, 0.2, 0.8, 0.0);
116   glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
117
118   if (0) {
119      DrawStencilPixels(x0, y0, WIDTH, HEIGHT, (GLubyte*) Image);
120   } else {
121      glWindowPos2i(x0, y0);
122      glDrawPixels(WIDTH, HEIGHT, GL_STENCIL_INDEX,
123                   GL_UNSIGNED_BYTE, (GLubyte*) Image);
124   }
125
126   glReadPixels(x0, y0, WIDTH, HEIGHT, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, tmp);
127
128   max = 0;
129   for (i = 0; i < HEIGHT; i++) {
130      for (j = 0; j < WIDTH; j++) {
131         if (tmp[i][j] > max)
132            max = tmp[i][j];
133      }
134   }
135   printf("max = %d\n", max);
136
137   glWindowPos2i(x1, y1);
138   glDrawPixels(WIDTH, HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, tmp);
139
140   glutSwapBuffers();
141}
142
143
144static void
145Reshape(int width, int height)
146{
147   WinWidth = width;
148   WinHeight = height;
149   glViewport(0, 0, width, height);
150   glMatrixMode(GL_PROJECTION);
151   glLoadIdentity();
152   glOrtho(0, width, 0, height, -1, 1);
153   glMatrixMode(GL_MODELVIEW);
154   glLoadIdentity();
155}
156
157
158static void
159Key(unsigned char key, int x, int y)
160{
161   (void) x;
162   (void) y;
163   switch (key) {
164   case 27:
165      glutDestroyWindow(Win);
166      exit(0);
167      break;
168   }
169   glutPostRedisplay();
170}
171
172
173static void
174SpecialKey(int key, int x, int y)
175{
176   const GLfloat step = 3.0;
177   (void) x;
178   (void) y;
179   switch (key) {
180   case GLUT_KEY_UP:
181      Xrot -= step;
182      break;
183   case GLUT_KEY_DOWN:
184      Xrot += step;
185      break;
186   case GLUT_KEY_LEFT:
187      Yrot -= step;
188      break;
189   case GLUT_KEY_RIGHT:
190      Yrot += step;
191      break;
192   }
193   glutPostRedisplay();
194}
195
196
197static void
198Init(void)
199{
200   int i, j;
201   for (i = 0; i < HEIGHT; i++) {
202      for (j = 0; j < WIDTH; j++) {
203         Image[i][j] = j;
204      }
205   }
206}
207
208
209int
210main(int argc, char *argv[])
211{
212   glutInit(&argc, argv);
213   glutInitWindowSize(WinWidth, WinHeight);
214   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);
215   Win = glutCreateWindow(argv[0]);
216   glewInit();
217   glutReshapeFunc(Reshape);
218   glutKeyboardFunc(Key);
219   glutSpecialFunc(SpecialKey);
220   glutDisplayFunc(Draw);
221   Init();
222   glutMainLoop();
223   return 0;
224}
225