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