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