132001f49Smrg/**
232001f49Smrg * Procedural Bump Mapping demo.  Uses the example shaders from
332001f49Smrg * chapter 11 of the OpenGL Shading Language "orange" book.
432001f49Smrg * 16 Jan 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#include "readtex.h"
1632001f49Smrg
1732001f49Smrg
1832001f49Smrgstatic char *FragProgFile = "CH11-bumpmap.frag";
1932001f49Smrgstatic char *FragTexProgFile = "CH11-bumpmaptex.frag";
2032001f49Smrgstatic char *VertProgFile = "CH11-bumpmap.vert";
2132001f49Smrgstatic char *TextureFile = DEMOS_DATA_DIR "tile.rgb";
2232001f49Smrg
2332001f49Smrg/* program/shader objects */
2432001f49Smrgstatic GLuint fragShader;
2532001f49Smrgstatic GLuint fragTexShader;
2632001f49Smrgstatic GLuint vertShader;
2732001f49Smrgstatic GLuint program;
2832001f49Smrgstatic GLuint texProgram;
2932001f49Smrg
3032001f49Smrg
3132001f49Smrgstatic struct uniform_info Uniforms[] = {
3232001f49Smrg   { "LightPosition",  1, GL_FLOAT_VEC3, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
3332001f49Smrg   { "SurfaceColor",   1, GL_FLOAT_VEC3, { 0.8, 0.8, 0.2, 0 }, -1 },
3432001f49Smrg   { "BumpDensity",    1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 },
3532001f49Smrg   { "BumpSize",       1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
3632001f49Smrg   { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
3732001f49Smrg   END_OF_UNIFORMS
3832001f49Smrg};
3932001f49Smrg
4032001f49Smrgstatic struct uniform_info TexUniforms[] = {
4132001f49Smrg   { "LightPosition",  1, GL_FLOAT_VEC3, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
4232001f49Smrg   { "Tex",            1, GL_INT,   { 0, 0, 0, 0 }, -1 },
4332001f49Smrg   { "BumpDensity",    1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 },
4432001f49Smrg   { "BumpSize",       1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
4532001f49Smrg   { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
4632001f49Smrg   END_OF_UNIFORMS
4732001f49Smrg};
4832001f49Smrg
4932001f49Smrgstatic GLint win = 0;
5032001f49Smrg
5132001f49Smrgstatic GLfloat xRot = 20.0f, yRot = 0.0f, zRot = 0.0f;
5232001f49Smrg
5332001f49Smrgstatic GLint tangentAttrib;
5432001f49Smrg
5532001f49Smrgstatic GLuint Texture;
5632001f49Smrg
5732001f49Smrgstatic GLboolean Anim = GL_FALSE;
5832001f49Smrgstatic GLboolean Textured = GL_FALSE;
5932001f49Smrg
6032001f49Smrg
6132001f49Smrgstatic void
6232001f49SmrgCheckError(int line)
6332001f49Smrg{
6432001f49Smrg   GLenum err = glGetError();
6532001f49Smrg   if (err) {
6632001f49Smrg      printf("GL Error %s (0x%x) at line %d\n",
6732001f49Smrg             gluErrorString(err), (int) err, line);
6832001f49Smrg   }
6932001f49Smrg}
7032001f49Smrg
7132001f49Smrg/*
7232001f49Smrg * Draw a square, specifying normal and tangent vectors.
7332001f49Smrg */
7432001f49Smrgstatic void
7532001f49SmrgSquare(GLfloat size)
7632001f49Smrg{
7732001f49Smrg   glNormal3f(0, 0, 1);
7832001f49Smrg   glVertexAttrib3f(tangentAttrib, 1, 0, 0);
7932001f49Smrg   glBegin(GL_POLYGON);
8032001f49Smrg   glTexCoord2f(0, 0);  glVertex2f(-size, -size);
8132001f49Smrg   glTexCoord2f(1, 0);  glVertex2f( size, -size);
8232001f49Smrg   glTexCoord2f(1, 1);  glVertex2f( size,  size);
8332001f49Smrg   glTexCoord2f(0, 1);  glVertex2f(-size,  size);
8432001f49Smrg   glEnd();
8532001f49Smrg}
8632001f49Smrg
8732001f49Smrg
8832001f49Smrgstatic void
8932001f49SmrgCube(GLfloat size)
9032001f49Smrg{
9132001f49Smrg   /* +X */
9232001f49Smrg   glPushMatrix();
9332001f49Smrg   glRotatef(90, 0, 1, 0);
9432001f49Smrg   glTranslatef(0, 0, size);
9532001f49Smrg   Square(size);
9632001f49Smrg   glPopMatrix();
9732001f49Smrg
9832001f49Smrg   /* -X */
9932001f49Smrg   glPushMatrix();
10032001f49Smrg   glRotatef(-90, 0, 1, 0);
10132001f49Smrg   glTranslatef(0, 0, size);
10232001f49Smrg   Square(size);
10332001f49Smrg   glPopMatrix();
10432001f49Smrg
10532001f49Smrg   /* +Y */
10632001f49Smrg   glPushMatrix();
10732001f49Smrg   glRotatef(90, 1, 0, 0);
10832001f49Smrg   glTranslatef(0, 0, size);
10932001f49Smrg   Square(size);
11032001f49Smrg   glPopMatrix();
11132001f49Smrg
11232001f49Smrg   /* -Y */
11332001f49Smrg   glPushMatrix();
11432001f49Smrg   glRotatef(-90, 1, 0, 0);
11532001f49Smrg   glTranslatef(0, 0, size);
11632001f49Smrg   Square(size);
11732001f49Smrg   glPopMatrix();
11832001f49Smrg
11932001f49Smrg
12032001f49Smrg   /* +Z */
12132001f49Smrg   glPushMatrix();
12232001f49Smrg   glTranslatef(0, 0, size);
12332001f49Smrg   Square(size);
12432001f49Smrg   glPopMatrix();
12532001f49Smrg
12632001f49Smrg   /* -Z */
12732001f49Smrg   glPushMatrix();
12832001f49Smrg   glRotatef(180, 0, 1, 0);
12932001f49Smrg   glTranslatef(0, 0, size);
13032001f49Smrg   Square(size);
13132001f49Smrg   glPopMatrix();
13232001f49Smrg
13332001f49Smrg}
13432001f49Smrg
13532001f49Smrg
13632001f49Smrgstatic void
13732001f49SmrgIdle(void)
13832001f49Smrg{
13932001f49Smrg   GLint t = glutGet(GLUT_ELAPSED_TIME);
14032001f49Smrg   yRot  = t * 0.05;
14132001f49Smrg   glutPostRedisplay();
14232001f49Smrg}
14332001f49Smrg
14432001f49Smrg
14532001f49Smrgstatic void
14632001f49SmrgRedisplay(void)
14732001f49Smrg{
14832001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14932001f49Smrg
15032001f49Smrg   glPushMatrix();
15132001f49Smrg   glRotatef(xRot, 1.0f, 0.0f, 0.0f);
15232001f49Smrg   glRotatef(yRot, 0.0f, 1.0f, 0.0f);
15332001f49Smrg   glRotatef(zRot, 0.0f, 0.0f, 1.0f);
15432001f49Smrg
15532001f49Smrg   if (Textured)
15632001f49Smrg      glUseProgram(texProgram);
15732001f49Smrg   else
15832001f49Smrg      glUseProgram(program);
15932001f49Smrg
16032001f49Smrg   Cube(1.5);
16132001f49Smrg
16232001f49Smrg   glPopMatrix();
16332001f49Smrg
16432001f49Smrg   CheckError(__LINE__);
16532001f49Smrg
16632001f49Smrg   glutSwapBuffers();
16732001f49Smrg}
16832001f49Smrg
16932001f49Smrg
17032001f49Smrgstatic void
17132001f49SmrgReshape(int width, int height)
17232001f49Smrg{
17332001f49Smrg   float ar = (float) width / (float) height;
17432001f49Smrg   glViewport(0, 0, width, height);
17532001f49Smrg   glMatrixMode(GL_PROJECTION);
17632001f49Smrg   glLoadIdentity();
17732001f49Smrg   glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
17832001f49Smrg   glMatrixMode(GL_MODELVIEW);
17932001f49Smrg   glLoadIdentity();
18032001f49Smrg   glTranslatef(0.0f, 0.0f, -15.0f);
18132001f49Smrg}
18232001f49Smrg
18332001f49Smrg
18432001f49Smrgstatic void
18532001f49SmrgCleanUp(void)
18632001f49Smrg{
18732001f49Smrg   glDeleteShader(fragShader);
18832001f49Smrg   glDeleteShader(fragTexShader);
18932001f49Smrg   glDeleteShader(vertShader);
19032001f49Smrg   glDeleteProgram(program);
19132001f49Smrg   glDeleteProgram(texProgram);
19232001f49Smrg   glutDestroyWindow(win);
19332001f49Smrg}
19432001f49Smrg
19532001f49Smrg
19632001f49Smrgstatic void
19732001f49SmrgKey(unsigned char key, int x, int y)
19832001f49Smrg{
19932001f49Smrg   const GLfloat step = 2.0;
20032001f49Smrg  (void) x;
20132001f49Smrg  (void) y;
20232001f49Smrg
20332001f49Smrg   switch(key) {
20432001f49Smrg   case 'a':
20532001f49Smrg      Anim = !Anim;
20632001f49Smrg      glutIdleFunc(Anim ? Idle : NULL);
20732001f49Smrg      break;
20832001f49Smrg   case 't':
20932001f49Smrg      Textured = !Textured;
21032001f49Smrg      break;
21132001f49Smrg   case 'z':
21232001f49Smrg      zRot += step;
21332001f49Smrg      break;
21432001f49Smrg   case 'Z':
21532001f49Smrg      zRot -= step;
21632001f49Smrg      break;
21732001f49Smrg   case 27:
21832001f49Smrg      CleanUp();
21932001f49Smrg      exit(0);
22032001f49Smrg      break;
22132001f49Smrg   }
22232001f49Smrg   glutPostRedisplay();
22332001f49Smrg}
22432001f49Smrg
22532001f49Smrg
22632001f49Smrgstatic void
22732001f49SmrgSpecialKey(int key, int x, int y)
22832001f49Smrg{
22932001f49Smrg   const GLfloat step = 2.0;
23032001f49Smrg
23132001f49Smrg  (void) x;
23232001f49Smrg  (void) y;
23332001f49Smrg
23432001f49Smrg   switch(key) {
23532001f49Smrg   case GLUT_KEY_UP:
23632001f49Smrg      xRot += step;
23732001f49Smrg      break;
23832001f49Smrg   case GLUT_KEY_DOWN:
23932001f49Smrg      xRot -= step;
24032001f49Smrg      break;
24132001f49Smrg   case GLUT_KEY_LEFT:
24232001f49Smrg      yRot -= step;
24332001f49Smrg      break;
24432001f49Smrg   case GLUT_KEY_RIGHT:
24532001f49Smrg      yRot += step;
24632001f49Smrg      break;
24732001f49Smrg   }
24832001f49Smrg   glutPostRedisplay();
24932001f49Smrg}
25032001f49Smrg
25132001f49Smrg
25232001f49Smrgstatic void
25332001f49SmrgInit(void)
25432001f49Smrg{
25532001f49Smrg   if (!ShadersSupported())
25632001f49Smrg      exit(1);
25732001f49Smrg
25832001f49Smrg   vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
25932001f49Smrg   fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
26032001f49Smrg   program = LinkShaders(vertShader, fragShader);
26132001f49Smrg
26232001f49Smrg   glUseProgram(program);
26332001f49Smrg
26432001f49Smrg   assert(glIsProgram(program));
26532001f49Smrg   assert(glIsShader(fragShader));
26632001f49Smrg   assert(glIsShader(vertShader));
26732001f49Smrg
26832001f49Smrg   assert(glGetError() == 0);
26932001f49Smrg
27032001f49Smrg   CheckError(__LINE__);
27132001f49Smrg
27232001f49Smrg   SetUniformValues(program, Uniforms);
27332001f49Smrg   PrintUniforms(Uniforms);
27432001f49Smrg
27532001f49Smrg   CheckError(__LINE__);
27632001f49Smrg
27732001f49Smrg   tangentAttrib = glGetAttribLocation(program, "Tangent");
27832001f49Smrg   printf("Tangent Attrib: %d\n", tangentAttrib);
27932001f49Smrg
28032001f49Smrg   assert(tangentAttrib >= 0);
28132001f49Smrg
28232001f49Smrg   CheckError(__LINE__);
28332001f49Smrg
28432001f49Smrg
28532001f49Smrg   /*
28632001f49Smrg    * As above, but fragment shader also uses a texture map.
28732001f49Smrg    */
28832001f49Smrg   fragTexShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragTexProgFile);
28932001f49Smrg   texProgram = LinkShaders(vertShader, fragTexShader);
29032001f49Smrg   glUseProgram(texProgram);
29132001f49Smrg   assert(glIsProgram(texProgram));
29232001f49Smrg   assert(glIsShader(fragTexShader));
29332001f49Smrg   SetUniformValues(texProgram, TexUniforms);
29432001f49Smrg   PrintUniforms(TexUniforms);
29532001f49Smrg
29632001f49Smrg   /*
29732001f49Smrg    * Load tex image.
29832001f49Smrg    */
29932001f49Smrg   glGenTextures(1, &Texture);
30032001f49Smrg   glBindTexture(GL_TEXTURE_2D, Texture);
30132001f49Smrg   LoadRGBMipmaps(TextureFile, GL_RGB);
30232001f49Smrg
30332001f49Smrg
30432001f49Smrg   glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
30532001f49Smrg
30632001f49Smrg   glEnable(GL_DEPTH_TEST);
30732001f49Smrg
30832001f49Smrg   glColor3f(1, 0, 0);
30932001f49Smrg}
31032001f49Smrg
31132001f49Smrg
31232001f49Smrgstatic void
31332001f49SmrgParseOptions(int argc, char *argv[])
31432001f49Smrg{
31532001f49Smrg   int i;
31632001f49Smrg   for (i = 1; i < argc; i++) {
31732001f49Smrg      if (strcmp(argv[i], "-fs") == 0) {
31832001f49Smrg         FragProgFile = argv[++i];
31932001f49Smrg      }
32032001f49Smrg      else if (strcmp(argv[i], "-vs") == 0) {
32132001f49Smrg         VertProgFile = argv[++i];
32232001f49Smrg      }
32332001f49Smrg      else if (strcmp(argv[i], "-t") == 0) {
32432001f49Smrg         TextureFile = argv[++i];
32532001f49Smrg      }
32632001f49Smrg   }
32732001f49Smrg}
32832001f49Smrg
32932001f49Smrg
33032001f49Smrgint
33132001f49Smrgmain(int argc, char *argv[])
33232001f49Smrg{
33332001f49Smrg   glutInit(&argc, argv);
33432001f49Smrg   glutInitWindowSize(400, 400);
33532001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
33632001f49Smrg   win = glutCreateWindow(argv[0]);
33732001f49Smrg   glewInit();
33832001f49Smrg   glutReshapeFunc(Reshape);
33932001f49Smrg   glutKeyboardFunc(Key);
34032001f49Smrg   glutSpecialFunc(SpecialKey);
34132001f49Smrg   glutDisplayFunc(Redisplay);
34232001f49Smrg   ParseOptions(argc, argv);
34332001f49Smrg   Init();
34432001f49Smrg   glutMainLoop();
34532001f49Smrg   return 0;
34632001f49Smrg}
34732001f49Smrg
348