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/glew.h> 13#include "glut_wrap.h" 14#include "shaderutil.h" 15 16 17static GLuint FragShader; 18static GLuint VertShader; 19static GLuint Program; 20 21static GLint Win = 0; 22static GLint WinWidth = 500, WinHeight = 500; 23static GLboolean Anim = GL_TRUE; 24static GLboolean Bitmap = GL_FALSE; 25static GLfloat Xrot = 20.0f, Yrot = 70.0f; 26static GLint uTex, uScale; 27static GLuint Textures[2]; 28 29#define TEX_WIDTH 16 30#define TEX_HEIGHT 8 31 32 33static void 34BitmapText(const char *s) 35{ 36 while (*s) { 37 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 38 s++; 39 } 40} 41 42 43static void 44Redisplay(void) 45{ 46 static const GLfloat px[3] = { 1.2, 0, 0}; 47 static const GLfloat nx[3] = {-1.2, 0, 0}; 48 49 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 50 51 glPushMatrix(); 52 glRotatef(Xrot, 1.0f, 0.0f, 0.0f); 53 glRotatef(Yrot, 0.0f, 1.0f, 0.0f); 54 55 glEnable(GL_LIGHTING); 56 57 glPushMatrix(); 58 glScalef(0.5, 0.5, 0.5); 59 glutSolidDodecahedron(); 60 glPopMatrix(); 61 62 glDisable(GL_LIGHTING); 63 64 glColor3f(0, 1, 0); 65 glBegin(GL_LINES); 66 glVertex3f(-1, 0, 0); 67 glVertex3f( 1, 0, 0); 68 glEnd(); 69 70 glColor3f(1, 1, 0); 71 72 if (Bitmap) { 73 glRasterPos3fv(px); 74 BitmapText("+X"); 75 glRasterPos3fv(nx); 76 BitmapText("-X"); 77 } 78 else { 79 glUseProgram(Program); 80 81 /* vertex positions (deltas) depend on texture size and window size */ 82 if (uScale != -1) { 83 glUniform2f(uScale, 84 2.0 * TEX_WIDTH / WinWidth, 85 2.0 * TEX_HEIGHT / WinHeight); 86 } 87 88 /* draw +X */ 89 glBindTexture(GL_TEXTURE_2D, Textures[0]); 90 glBegin(GL_QUADS); 91 glTexCoord2f(0, 0); glVertex3fv(px); 92 glTexCoord2f(1, 0); glVertex3fv(px); 93 glTexCoord2f(1, 1); glVertex3fv(px); 94 glTexCoord2f(0, 1); glVertex3fv(px); 95 glEnd(); 96 97 /* draw -X */ 98 glBindTexture(GL_TEXTURE_2D, Textures[1]); 99 glBegin(GL_QUADS); 100 glTexCoord2f(0, 0); glVertex3fv(nx); 101 glTexCoord2f(1, 0); glVertex3fv(nx); 102 glTexCoord2f(1, 1); glVertex3fv(nx); 103 glTexCoord2f(0, 1); glVertex3fv(nx); 104 glEnd(); 105 106 glUseProgram(0); 107 } 108 109 glPopMatrix(); 110 111 glutSwapBuffers(); 112} 113 114 115static void 116Idle(void) 117{ 118 Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.01; 119 glutPostRedisplay(); 120} 121 122 123static void 124Reshape(int width, int height) 125{ 126 WinWidth = width; 127 WinHeight = height; 128 glViewport(0, 0, width, height); 129 glMatrixMode(GL_PROJECTION); 130 glLoadIdentity(); 131 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 132 glMatrixMode(GL_MODELVIEW); 133 glLoadIdentity(); 134 glTranslatef(0.0f, 0.0f, -10.0f); 135} 136 137 138static void 139Key(unsigned char key, int x, int y) 140{ 141 (void) x; 142 (void) y; 143 144 switch(key) { 145 case ' ': 146 case 'a': 147 Anim = !Anim; 148 if (Anim) 149 glutIdleFunc(Idle); 150 else 151 glutIdleFunc(NULL); 152 break; 153 case 'b': 154 Bitmap = !Bitmap; 155 if (Bitmap) 156 printf("Using glBitmap\n"); 157 else 158 printf("Using billboard texture\n"); 159 break; 160 case 27: 161 glDeleteShader(FragShader); 162 glDeleteShader(VertShader); 163 glDeleteProgram(Program); 164 glutDestroyWindow(Win); 165 exit(0); 166 } 167 glutPostRedisplay(); 168} 169 170 171static void 172SpecialKey(int key, int x, int y) 173{ 174 const GLfloat step = 0.125f; 175 switch(key) { 176 case GLUT_KEY_UP: 177 Xrot -= step; 178 break; 179 case GLUT_KEY_DOWN: 180 Xrot += step; 181 break; 182 case GLUT_KEY_LEFT: 183 Yrot -= step; 184 break; 185 case GLUT_KEY_RIGHT: 186 Yrot += step; 187 break; 188 } 189 /*printf("Xrot: %f Yrot: %f\n", Xrot, Yrot);*/ 190 glutPostRedisplay(); 191} 192 193 194static void 195MakeTexImage(const char *p, GLuint texobj) 196{ 197 GLubyte image[TEX_HEIGHT][TEX_WIDTH]; 198 GLuint i, j, k; 199 200 for (i = 0; i < TEX_HEIGHT; i++) { 201 for (j = 0; j < TEX_WIDTH; j++) { 202 k = i * TEX_WIDTH + j; 203 if (p[k] == ' ') { 204 image[i][j] = 0; 205 } 206 else { 207 image[i][j] = 255; 208 } 209 } 210 } 211 212 glBindTexture(GL_TEXTURE_2D, texobj); 213 glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, TEX_WIDTH, TEX_HEIGHT, 0, 214 GL_RED, GL_UNSIGNED_BYTE, image); 215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); 216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 218} 219 220 221static void 222MakeBitmapTextures(void) 223{ 224 const char *px = 225 " X X " 226 " X X X " 227 " X X X " 228 " XXXXX X " 229 " X X X " 230 " X X X " 231 " X X " 232 " X X "; 233 const char *nx = 234 " X X " 235 " X X " 236 " X X " 237 " XXXXX X " 238 " X X " 239 " X X " 240 " X X " 241 " X X "; 242 glGenTextures(2, Textures); 243 MakeTexImage(px, Textures[0]); 244 MakeTexImage(nx, Textures[1]); 245} 246 247 248static void 249Init(void) 250{ 251 /* Fragment shader: modulate raster color by texture, discard fragments 252 * with alpha < 1.0 253 */ 254 static const char *fragShaderText = 255 "uniform sampler2D tex2d; \n" 256 "void main() {\n" 257 " vec4 c = texture2D(tex2d, gl_TexCoord[0].xy); \n" 258 " if (c.w < 1.0) \n" 259 " discard; \n" 260 " gl_FragColor = c * gl_Color; \n" 261 "}\n"; 262 /* Vertex shader: compute new vertex position based on incoming vertex pos, 263 * texcoords and special scale factor. 264 */ 265 static const char *vertShaderText = 266 "uniform vec2 scale; \n" 267 "void main() {\n" 268 " vec4 p = gl_ModelViewProjectionMatrix * gl_Vertex;\n" 269 " gl_Position.xy = p.xy + gl_MultiTexCoord0.xy * scale * p.w; \n" 270 " gl_Position.zw = p.zw; \n" 271 " gl_TexCoord[0] = gl_MultiTexCoord0; \n" 272 " gl_FrontColor = gl_Color; \n" 273 "}\n"; 274 275 if (!ShadersSupported()) 276 exit(1); 277 278 VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText); 279 FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText); 280 Program = LinkShaders(VertShader, FragShader); 281 282 glUseProgram(Program); 283 284 uScale = glGetUniformLocation(Program, "scale"); 285 uTex = glGetUniformLocation(Program, "tex2d"); 286 if (uTex != -1) { 287 glUniform1i(uTex, 0); /* tex unit 0 */ 288 } 289 290 glUseProgram(0); 291 292 glClearColor(0.3f, 0.3f, 0.3f, 0.0f); 293 glEnable(GL_DEPTH_TEST); 294 glEnable(GL_NORMALIZE); 295 glEnable(GL_LIGHT0); 296 297 MakeBitmapTextures(); 298} 299 300 301int 302main(int argc, char *argv[]) 303{ 304 glutInit(&argc, argv); 305 glutInitWindowSize(WinWidth, WinHeight); 306 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 307 Win = glutCreateWindow(argv[0]); 308 glewInit(); 309 glutReshapeFunc(Reshape); 310 glutKeyboardFunc(Key); 311 glutSpecialFunc(SpecialKey); 312 glutDisplayFunc(Redisplay); 313 if (Anim) 314 glutIdleFunc(Idle); 315 Init(); 316 glutMainLoop(); 317 return 0; 318} 319 320 321