4b62686cbff2afb0992174713c797b6fceb07490
[mesa.git] / progs / glsl / bitmap.c
1 /**
2 * Implement glRasterPos + glBitmap with textures + shaders.
3 * Brian Paul
4 * 14 May 2007
5 */
6
7 #include <assert.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <GL/gl.h>
13 #include <GL/glut.h>
14 #include <GL/glext.h>
15 #include "extfuncs.h"
16
17
18 static GLuint FragShader;
19 static GLuint VertShader;
20 static GLuint Program;
21
22 static GLint Win = 0;
23 static GLint WinWidth = 500, WinHeight = 500;
24 static GLboolean Anim = GL_TRUE;
25 static GLboolean Bitmap = GL_FALSE;
26 static GLfloat Xrot = 20.0f, Yrot = 70.0f;
27 static GLint uTex, uScale;
28 static GLuint Textures[2];
29
30 #define TEX_WIDTH 16
31 #define TEX_HEIGHT 8
32
33
34 static void
35 BitmapText(const char *s)
36 {
37 while (*s) {
38 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
39 s++;
40 }
41 }
42
43
44 static void
45 Redisplay(void)
46 {
47 static const GLfloat px[3] = { 1.2, 0, 0};
48 static const GLfloat nx[3] = {-1.2, 0, 0};
49
50 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
51
52 glPushMatrix();
53 glRotatef(Xrot, 1.0f, 0.0f, 0.0f);
54 glRotatef(Yrot, 0.0f, 1.0f, 0.0f);
55
56 glEnable(GL_LIGHTING);
57
58 glPushMatrix();
59 glScalef(0.5, 0.5, 0.5);
60 glutSolidDodecahedron();
61 glPopMatrix();
62
63 glDisable(GL_LIGHTING);
64
65 glColor3f(0, 1, 0);
66 glBegin(GL_LINES);
67 glVertex3f(-1, 0, 0);
68 glVertex3f( 1, 0, 0);
69 glEnd();
70
71 glColor3f(1, 1, 0);
72
73 if (Bitmap) {
74 glRasterPos3fv(px);
75 BitmapText("+X");
76 glRasterPos3fv(nx);
77 BitmapText("-X");
78 }
79 else {
80 glUseProgram_func(Program);
81
82 /* vertex positions (deltas) depend on texture size and window size */
83 if (uScale != -1) {
84 glUniform2f_func(uScale,
85 2.0 * TEX_WIDTH / WinWidth,
86 2.0 * TEX_HEIGHT / WinHeight);
87 }
88
89 /* draw +X */
90 glBindTexture(GL_TEXTURE_2D, Textures[0]);
91 glBegin(GL_QUADS);
92 glTexCoord2f(0, 0); glVertex3fv(px);
93 glTexCoord2f(1, 0); glVertex3fv(px);
94 glTexCoord2f(1, 1); glVertex3fv(px);
95 glTexCoord2f(0, 1); glVertex3fv(px);
96 glEnd();
97
98 /* draw -X */
99 glBindTexture(GL_TEXTURE_2D, Textures[1]);
100 glBegin(GL_QUADS);
101 glTexCoord2f(0, 0); glVertex3fv(nx);
102 glTexCoord2f(1, 0); glVertex3fv(nx);
103 glTexCoord2f(1, 1); glVertex3fv(nx);
104 glTexCoord2f(0, 1); glVertex3fv(nx);
105 glEnd();
106
107 glUseProgram_func(0);
108 }
109
110 glPopMatrix();
111
112 glutSwapBuffers();
113 }
114
115
116 static void
117 Idle(void)
118 {
119 Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.01;
120 glutPostRedisplay();
121 }
122
123
124 static void
125 Reshape(int width, int height)
126 {
127 WinWidth = width;
128 WinHeight = height;
129 glViewport(0, 0, width, height);
130 glMatrixMode(GL_PROJECTION);
131 glLoadIdentity();
132 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
133 glMatrixMode(GL_MODELVIEW);
134 glLoadIdentity();
135 glTranslatef(0.0f, 0.0f, -10.0f);
136 }
137
138
139 static void
140 Key(unsigned char key, int x, int y)
141 {
142 (void) x;
143 (void) y;
144
145 switch(key) {
146 case ' ':
147 case 'a':
148 Anim = !Anim;
149 if (Anim)
150 glutIdleFunc(Idle);
151 else
152 glutIdleFunc(NULL);
153 break;
154 case 'b':
155 Bitmap = !Bitmap;
156 if (Bitmap)
157 printf("Using glBitmap\n");
158 else
159 printf("Using billboard texture\n");
160 break;
161 case 27:
162 glDeleteShader_func(FragShader);
163 glDeleteShader_func(VertShader);
164 glDeleteProgram_func(Program);
165 glutDestroyWindow(Win);
166 exit(0);
167 }
168 glutPostRedisplay();
169 }
170
171
172 static void
173 SpecialKey(int key, int x, int y)
174 {
175 const GLfloat step = 0.125f;
176 switch(key) {
177 case GLUT_KEY_UP:
178 Xrot -= step;
179 break;
180 case GLUT_KEY_DOWN:
181 Xrot += step;
182 break;
183 case GLUT_KEY_LEFT:
184 Yrot -= step;
185 break;
186 case GLUT_KEY_RIGHT:
187 Yrot += step;
188 break;
189 }
190 /*printf("Xrot: %f Yrot: %f\n", Xrot, Yrot);*/
191 glutPostRedisplay();
192 }
193
194
195 static void
196 MakeTexImage(const char *p, GLuint texobj)
197 {
198 GLubyte image[TEX_HEIGHT][TEX_WIDTH];
199 GLuint i, j, k;
200
201 for (i = 0; i < TEX_HEIGHT; i++) {
202 for (j = 0; j < TEX_WIDTH; j++) {
203 k = i * TEX_WIDTH + j;
204 if (p[k] == ' ') {
205 image[i][j] = 0;
206 }
207 else {
208 image[i][j] = 255;
209 }
210 }
211 }
212
213 glBindTexture(GL_TEXTURE_2D, texobj);
214 glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, TEX_WIDTH, TEX_HEIGHT, 0,
215 GL_RED, GL_UNSIGNED_BYTE, image);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
219 }
220
221
222 static void
223 MakeBitmapTextures(void)
224 {
225 const char *px =
226 " X X "
227 " X X X "
228 " X X X "
229 " XXXXX X "
230 " X X X "
231 " X X X "
232 " X X "
233 " X X ";
234 const char *nx =
235 " X X "
236 " X X "
237 " X X "
238 " XXXXX X "
239 " X X "
240 " X X "
241 " X X "
242 " X X ";
243 glGenTextures(2, Textures);
244 MakeTexImage(px, Textures[0]);
245 MakeTexImage(nx, Textures[1]);
246 }
247
248
249 static void
250 LoadAndCompileShader(GLuint shader, const char *text)
251 {
252 GLint stat;
253
254 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
255
256 glCompileShader_func(shader);
257
258 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
259 if (!stat) {
260 GLchar log[1000];
261 GLsizei len;
262 glGetShaderInfoLog_func(shader, 1000, &len, log);
263 fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
264 exit(1);
265 }
266 }
267
268
269 static void
270 CheckLink(GLuint prog)
271 {
272 GLint stat;
273 glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
274 if (!stat) {
275 GLchar log[1000];
276 GLsizei len;
277 glGetProgramInfoLog_func(prog, 1000, &len, log);
278 fprintf(stderr, "Linker error:\n%s\n", log);
279 }
280 }
281
282
283 static void
284 Init(void)
285 {
286 /* Fragment shader: modulate raster color by texture, discard fragments
287 * with alpha < 1.0
288 */
289 static const char *fragShaderText =
290 "uniform sampler2D tex2d; \n"
291 "void main() {\n"
292 " vec4 c = texture2D(tex2d, gl_TexCoord[0].xy); \n"
293 " if (c.w < 1.0) \n"
294 " discard; \n"
295 " gl_FragColor = c * gl_Color; \n"
296 "}\n";
297 /* Vertex shader: compute new vertex position based on incoming vertex pos,
298 * texcoords and special scale factor.
299 */
300 static const char *vertShaderText =
301 "uniform vec2 scale; \n"
302 "void main() {\n"
303 " vec4 p = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
304 " gl_Position.xy = p.xy + gl_MultiTexCoord0.xy * scale * p.w; \n"
305 " gl_Position.zw = p.zw; \n"
306 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
307 " gl_FrontColor = gl_Color; \n"
308 "}\n";
309 const char *version;
310
311 version = (const char *) glGetString(GL_VERSION);
312 if (version[0] != '2' || version[1] != '.') {
313 printf("This program requires OpenGL 2.x, found %s\n", version);
314 exit(1);
315 }
316 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
317
318 GetExtensionFuncs();
319
320 FragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
321 LoadAndCompileShader(FragShader, fragShaderText);
322
323 VertShader = glCreateShader_func(GL_VERTEX_SHADER);
324 LoadAndCompileShader(VertShader, vertShaderText);
325
326 Program = glCreateProgram_func();
327 glAttachShader_func(Program, FragShader);
328 glAttachShader_func(Program, VertShader);
329 glLinkProgram_func(Program);
330 CheckLink(Program);
331 glUseProgram_func(Program);
332
333 uScale = glGetUniformLocation_func(Program, "scale");
334 uTex = glGetUniformLocation_func(Program, "tex2d");
335 if (uTex != -1) {
336 glUniform1i_func(uTex, 0); /* tex unit 0 */
337 }
338
339 glUseProgram_func(0);
340
341 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
342 glEnable(GL_DEPTH_TEST);
343 glEnable(GL_NORMALIZE);
344 glEnable(GL_LIGHT0);
345
346 MakeBitmapTextures();
347 }
348
349
350 int
351 main(int argc, char *argv[])
352 {
353 glutInit(&argc, argv);
354 glutInitWindowSize(WinWidth, WinHeight);
355 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
356 Win = glutCreateWindow(argv[0]);
357 glutReshapeFunc(Reshape);
358 glutKeyboardFunc(Key);
359 glutSpecialFunc(SpecialKey);
360 glutDisplayFunc(Redisplay);
361 if (Anim)
362 glutIdleFunc(Idle);
363 Init();
364 glutMainLoop();
365 return 0;
366 }
367
368