132001f49Smrg/**
232001f49Smrg * Implement glRasterPos + glBitmap with textures + shaders.
332001f49Smrg * Brian Paul
432001f49Smrg * 14 May 2007
532001f49Smrg */
632001f49Smrg
732001f49Smrg#include <assert.h>
832001f49Smrg#include <string.h>
932001f49Smrg#include <stdio.h>
1032001f49Smrg#include <stdlib.h>
1132001f49Smrg#include <math.h>
1232001f49Smrg#include <GL/glew.h>
1332001f49Smrg#include "glut_wrap.h"
1432001f49Smrg#include "shaderutil.h"
1532001f49Smrg
1632001f49Smrg
1732001f49Smrgstatic GLuint FragShader;
1832001f49Smrgstatic GLuint VertShader;
1932001f49Smrgstatic GLuint Program;
2032001f49Smrg
2132001f49Smrgstatic GLint Win = 0;
2232001f49Smrgstatic GLint WinWidth = 500, WinHeight = 500;
2332001f49Smrgstatic GLboolean Anim = GL_TRUE;
2432001f49Smrgstatic GLboolean Bitmap = GL_FALSE;
2532001f49Smrgstatic GLfloat Xrot = 20.0f, Yrot = 70.0f;
2632001f49Smrgstatic GLint uTex, uScale;
2732001f49Smrgstatic GLuint Textures[2];
2832001f49Smrg
2932001f49Smrg#define TEX_WIDTH 16
3032001f49Smrg#define TEX_HEIGHT 8
3132001f49Smrg
3232001f49Smrg
3332001f49Smrgstatic void
3432001f49SmrgBitmapText(const char *s)
3532001f49Smrg{
3632001f49Smrg   while (*s) {
3732001f49Smrg      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
3832001f49Smrg      s++;
3932001f49Smrg   }
4032001f49Smrg}
4132001f49Smrg
4232001f49Smrg
4332001f49Smrgstatic void
4432001f49SmrgRedisplay(void)
4532001f49Smrg{
4632001f49Smrg   static const GLfloat px[3] = { 1.2, 0, 0};
4732001f49Smrg   static const GLfloat nx[3] = {-1.2, 0, 0};
4832001f49Smrg
4932001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5032001f49Smrg
5132001f49Smrg   glPushMatrix();
5232001f49Smrg   glRotatef(Xrot, 1.0f, 0.0f, 0.0f);
5332001f49Smrg   glRotatef(Yrot, 0.0f, 1.0f, 0.0f);
5432001f49Smrg
5532001f49Smrg   glEnable(GL_LIGHTING);
5632001f49Smrg
5732001f49Smrg   glPushMatrix();
5832001f49Smrg   glScalef(0.5, 0.5, 0.5);
5932001f49Smrg   glutSolidDodecahedron();
6032001f49Smrg   glPopMatrix();
6132001f49Smrg
6232001f49Smrg   glDisable(GL_LIGHTING);
6332001f49Smrg
6432001f49Smrg   glColor3f(0, 1, 0);
6532001f49Smrg   glBegin(GL_LINES);
6632001f49Smrg   glVertex3f(-1, 0, 0);
6732001f49Smrg   glVertex3f( 1, 0, 0);
6832001f49Smrg   glEnd();
6932001f49Smrg
7032001f49Smrg   glColor3f(1, 1, 0);
7132001f49Smrg
7232001f49Smrg   if (Bitmap) {
7332001f49Smrg      glRasterPos3fv(px);
7432001f49Smrg      BitmapText("+X");
7532001f49Smrg      glRasterPos3fv(nx);
7632001f49Smrg      BitmapText("-X");
7732001f49Smrg   }
7832001f49Smrg   else {
7932001f49Smrg      glUseProgram(Program);
8032001f49Smrg
8132001f49Smrg      /* vertex positions (deltas) depend on texture size and window size */
8232001f49Smrg      if (uScale != -1) {
8332001f49Smrg         glUniform2f(uScale,
8432001f49Smrg                          2.0 * TEX_WIDTH / WinWidth,
8532001f49Smrg                          2.0 * TEX_HEIGHT / WinHeight);
8632001f49Smrg      }
8732001f49Smrg
8832001f49Smrg      /* draw +X */
8932001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[0]);
9032001f49Smrg      glBegin(GL_QUADS);
9132001f49Smrg      glTexCoord2f(0, 0);  glVertex3fv(px);
9232001f49Smrg      glTexCoord2f(1, 0);  glVertex3fv(px);
9332001f49Smrg      glTexCoord2f(1, 1);  glVertex3fv(px);
9432001f49Smrg      glTexCoord2f(0, 1);  glVertex3fv(px);
9532001f49Smrg      glEnd();
9632001f49Smrg
9732001f49Smrg      /* draw -X */
9832001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[1]);
9932001f49Smrg      glBegin(GL_QUADS);
10032001f49Smrg      glTexCoord2f(0, 0);  glVertex3fv(nx);
10132001f49Smrg      glTexCoord2f(1, 0);  glVertex3fv(nx);
10232001f49Smrg      glTexCoord2f(1, 1);  glVertex3fv(nx);
10332001f49Smrg      glTexCoord2f(0, 1);  glVertex3fv(nx);
10432001f49Smrg      glEnd();
10532001f49Smrg
10632001f49Smrg      glUseProgram(0);
10732001f49Smrg   }
10832001f49Smrg
10932001f49Smrg   glPopMatrix();
11032001f49Smrg
11132001f49Smrg   glutSwapBuffers();
11232001f49Smrg}
11332001f49Smrg
11432001f49Smrg
11532001f49Smrgstatic void
11632001f49SmrgIdle(void)
11732001f49Smrg{
11832001f49Smrg   Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.01;
11932001f49Smrg   glutPostRedisplay();
12032001f49Smrg}
12132001f49Smrg
12232001f49Smrg
12332001f49Smrgstatic void
12432001f49SmrgReshape(int width, int height)
12532001f49Smrg{
12632001f49Smrg   WinWidth = width;
12732001f49Smrg   WinHeight = height;
12832001f49Smrg   glViewport(0, 0, width, height);
12932001f49Smrg   glMatrixMode(GL_PROJECTION);
13032001f49Smrg   glLoadIdentity();
13132001f49Smrg   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
13232001f49Smrg   glMatrixMode(GL_MODELVIEW);
13332001f49Smrg   glLoadIdentity();
13432001f49Smrg   glTranslatef(0.0f, 0.0f, -10.0f);
13532001f49Smrg}
13632001f49Smrg
13732001f49Smrg
13832001f49Smrgstatic void
13932001f49SmrgKey(unsigned char key, int x, int y)
14032001f49Smrg{
14132001f49Smrg  (void) x;
14232001f49Smrg  (void) y;
14332001f49Smrg
14432001f49Smrg   switch(key) {
14532001f49Smrg   case ' ':
14632001f49Smrg   case 'a':
14732001f49Smrg      Anim = !Anim;
14832001f49Smrg      if (Anim)
14932001f49Smrg         glutIdleFunc(Idle);
15032001f49Smrg      else
15132001f49Smrg         glutIdleFunc(NULL);
15232001f49Smrg      break;
15332001f49Smrg   case 'b':
15432001f49Smrg      Bitmap = !Bitmap;
15532001f49Smrg      if (Bitmap)
15632001f49Smrg         printf("Using glBitmap\n");
15732001f49Smrg      else
15832001f49Smrg         printf("Using billboard texture\n");
15932001f49Smrg      break;
16032001f49Smrg   case 27:
16132001f49Smrg      glDeleteShader(FragShader);
16232001f49Smrg      glDeleteShader(VertShader);
16332001f49Smrg      glDeleteProgram(Program);
16432001f49Smrg      glutDestroyWindow(Win);
16532001f49Smrg      exit(0);
16632001f49Smrg   }
16732001f49Smrg   glutPostRedisplay();
16832001f49Smrg}
16932001f49Smrg
17032001f49Smrg
17132001f49Smrgstatic void
17232001f49SmrgSpecialKey(int key, int x, int y)
17332001f49Smrg{
17432001f49Smrg   const GLfloat step = 0.125f;
17532001f49Smrg   switch(key) {
17632001f49Smrg   case GLUT_KEY_UP:
17732001f49Smrg      Xrot -= step;
17832001f49Smrg      break;
17932001f49Smrg   case GLUT_KEY_DOWN:
18032001f49Smrg      Xrot += step;
18132001f49Smrg      break;
18232001f49Smrg   case GLUT_KEY_LEFT:
18332001f49Smrg      Yrot -= step;
18432001f49Smrg      break;
18532001f49Smrg   case GLUT_KEY_RIGHT:
18632001f49Smrg      Yrot += step;
18732001f49Smrg      break;
18832001f49Smrg   }
18932001f49Smrg   /*printf("Xrot: %f  Yrot: %f\n", Xrot, Yrot);*/
19032001f49Smrg   glutPostRedisplay();
19132001f49Smrg}
19232001f49Smrg
19332001f49Smrg
19432001f49Smrgstatic void
19532001f49SmrgMakeTexImage(const char *p, GLuint texobj)
19632001f49Smrg{
19732001f49Smrg   GLubyte image[TEX_HEIGHT][TEX_WIDTH];
19832001f49Smrg   GLuint i, j, k;
19932001f49Smrg
20032001f49Smrg   for (i = 0; i < TEX_HEIGHT; i++) {
20132001f49Smrg      for (j = 0; j < TEX_WIDTH; j++) {
20232001f49Smrg         k = i * TEX_WIDTH + j;
20332001f49Smrg         if (p[k] == ' ') {
20432001f49Smrg            image[i][j] = 0;
20532001f49Smrg         }
20632001f49Smrg         else {
20732001f49Smrg            image[i][j] = 255;
20832001f49Smrg         }
20932001f49Smrg      }
21032001f49Smrg   }
21132001f49Smrg
21232001f49Smrg   glBindTexture(GL_TEXTURE_2D, texobj);
21332001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, TEX_WIDTH, TEX_HEIGHT, 0,
21432001f49Smrg                GL_RED, GL_UNSIGNED_BYTE, image);
21532001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
21632001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
21732001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
21832001f49Smrg}
21932001f49Smrg
22032001f49Smrg
22132001f49Smrgstatic void
22232001f49SmrgMakeBitmapTextures(void)
22332001f49Smrg{
22432001f49Smrg   const char *px =
22532001f49Smrg      "        X     X "
22632001f49Smrg      "   X     X   X  "
22732001f49Smrg      "   X      X X   "
22832001f49Smrg      " XXXXX     X    "
22932001f49Smrg      "   X      X X   "
23032001f49Smrg      "   X     X   X  "
23132001f49Smrg      "        X     X "
23232001f49Smrg      "        X     X ";
23332001f49Smrg   const char *nx =
23432001f49Smrg      "        X     X "
23532001f49Smrg      "         X   X  "
23632001f49Smrg      "          X X   "
23732001f49Smrg      " XXXXX     X    "
23832001f49Smrg      "          X X   "
23932001f49Smrg      "         X   X  "
24032001f49Smrg      "        X     X "
24132001f49Smrg      "        X     X ";
24232001f49Smrg   glGenTextures(2, Textures);
24332001f49Smrg   MakeTexImage(px, Textures[0]);
24432001f49Smrg   MakeTexImage(nx, Textures[1]);
24532001f49Smrg}
24632001f49Smrg
24732001f49Smrg
24832001f49Smrgstatic void
24932001f49SmrgInit(void)
25032001f49Smrg{
25132001f49Smrg   /* Fragment shader: modulate raster color by texture, discard fragments
25232001f49Smrg    * with alpha < 1.0
25332001f49Smrg    */
25432001f49Smrg   static const char *fragShaderText =
25532001f49Smrg      "uniform sampler2D tex2d; \n"
25632001f49Smrg      "void main() {\n"
25732001f49Smrg      "   vec4 c = texture2D(tex2d, gl_TexCoord[0].xy); \n"
25832001f49Smrg      "   if (c.w < 1.0) \n"
25932001f49Smrg      "      discard; \n"
26032001f49Smrg      "   gl_FragColor = c * gl_Color; \n"
26132001f49Smrg      "}\n";
26232001f49Smrg   /* Vertex shader: compute new vertex position based on incoming vertex pos,
26332001f49Smrg    * texcoords and special scale factor.
26432001f49Smrg    */
26532001f49Smrg   static const char *vertShaderText =
26632001f49Smrg      "uniform vec2 scale; \n"
26732001f49Smrg      "void main() {\n"
26832001f49Smrg      "   vec4 p = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
26932001f49Smrg      "   gl_Position.xy = p.xy + gl_MultiTexCoord0.xy * scale * p.w; \n"
27032001f49Smrg      "   gl_Position.zw = p.zw; \n"
27132001f49Smrg      "   gl_TexCoord[0] = gl_MultiTexCoord0; \n"
27232001f49Smrg      "   gl_FrontColor = gl_Color; \n"
27332001f49Smrg      "}\n";
27432001f49Smrg
27532001f49Smrg   if (!ShadersSupported())
27632001f49Smrg      exit(1);
27732001f49Smrg
27832001f49Smrg   VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
27932001f49Smrg   FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
28032001f49Smrg   Program = LinkShaders(VertShader, FragShader);
28132001f49Smrg
28232001f49Smrg   glUseProgram(Program);
28332001f49Smrg
28432001f49Smrg   uScale = glGetUniformLocation(Program, "scale");
28532001f49Smrg   uTex = glGetUniformLocation(Program, "tex2d");
28632001f49Smrg   if (uTex != -1) {
28732001f49Smrg      glUniform1i(uTex, 0);  /* tex unit 0 */
28832001f49Smrg   }
28932001f49Smrg
29032001f49Smrg   glUseProgram(0);
29132001f49Smrg
29232001f49Smrg   glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
29332001f49Smrg   glEnable(GL_DEPTH_TEST);
29432001f49Smrg   glEnable(GL_NORMALIZE);
29532001f49Smrg   glEnable(GL_LIGHT0);
29632001f49Smrg
29732001f49Smrg   MakeBitmapTextures();
29832001f49Smrg}
29932001f49Smrg
30032001f49Smrg
30132001f49Smrgint
30232001f49Smrgmain(int argc, char *argv[])
30332001f49Smrg{
30432001f49Smrg   glutInit(&argc, argv);
30532001f49Smrg   glutInitWindowSize(WinWidth, WinHeight);
30632001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
30732001f49Smrg   Win = glutCreateWindow(argv[0]);
30832001f49Smrg   glewInit();
30932001f49Smrg   glutReshapeFunc(Reshape);
31032001f49Smrg   glutKeyboardFunc(Key);
31132001f49Smrg   glutSpecialFunc(SpecialKey);
31232001f49Smrg   glutDisplayFunc(Redisplay);
31332001f49Smrg   if (Anim)
31432001f49Smrg      glutIdleFunc(Idle);
31532001f49Smrg   Init();
31632001f49Smrg   glutMainLoop();
31732001f49Smrg   return 0;
31832001f49Smrg}
31932001f49Smrg
32032001f49Smrg
321