blob: e31afab9392e4f78388446cc42306764661aa112 [file] [log] [blame]
Brianf44ba112007-01-16 14:55:43 -07001/**
2 * Procedural Bump Mapping demo. Uses the example shaders from
3 * chapter 11 of the OpenGL Shading Language "orange" book.
4 * 16 Jan 2007
5 */
6
7#include <assert.h>
8#include <string.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <math.h>
Brian Paulee0b1bc2009-07-17 13:23:11 -060012#include <GL/glew.h>
Brianf44ba112007-01-16 14:55:43 -070013#include <GL/glut.h>
Brian2dca3372008-04-09 22:28:23 -060014#include "shaderutil.h"
Brian Paul8796dbf2009-12-03 09:49:27 -070015#include "readtex.h"
Brianf44ba112007-01-16 14:55:43 -070016
17
Brian Paulc0dd9122008-08-16 09:36:46 -060018static char *FragProgFile = "CH11-bumpmap.frag";
Brian Paul8796dbf2009-12-03 09:49:27 -070019static char *FragTexProgFile = "CH11-bumpmaptex.frag";
Brian Paulc0dd9122008-08-16 09:36:46 -060020static char *VertProgFile = "CH11-bumpmap.vert";
Brian Paul8796dbf2009-12-03 09:49:27 -070021static char *TextureFile = "../images/tile.rgb";
Brianf44ba112007-01-16 14:55:43 -070022
23/* program/shader objects */
24static GLuint fragShader;
Brian Paul8796dbf2009-12-03 09:49:27 -070025static GLuint fragTexShader;
Brianf44ba112007-01-16 14:55:43 -070026static GLuint vertShader;
27static GLuint program;
Brian Paul8796dbf2009-12-03 09:49:27 -070028static GLuint texProgram;
Brianf44ba112007-01-16 14:55:43 -070029
30
Brianf44ba112007-01-16 14:55:43 -070031static struct uniform_info Uniforms[] = {
Brian Paulfdfb0d42009-08-12 17:25:49 -060032 { "LightPosition", 1, GL_FLOAT_VEC3, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
33 { "SurfaceColor", 1, GL_FLOAT_VEC3, { 0.8, 0.8, 0.2, 0 }, -1 },
34 { "BumpDensity", 1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 },
35 { "BumpSize", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
36 { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
Brian2dca3372008-04-09 22:28:23 -060037 END_OF_UNIFORMS
Brianf44ba112007-01-16 14:55:43 -070038};
39
Brian Paul8796dbf2009-12-03 09:49:27 -070040static struct uniform_info TexUniforms[] = {
41 { "LightPosition", 1, GL_FLOAT_VEC3, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
42 { "Tex", 1, GL_INT, { 0, 0, 0, 0 }, -1 },
43 { "BumpDensity", 1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 },
44 { "BumpSize", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
45 { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
46 END_OF_UNIFORMS
47};
48
Brianf44ba112007-01-16 14:55:43 -070049static GLint win = 0;
50
Brian271d5042007-01-16 15:27:11 -070051static GLfloat xRot = 20.0f, yRot = 0.0f, zRot = 0.0f;
Brianf44ba112007-01-16 14:55:43 -070052
Vinson Leeb8dcb792009-11-17 11:37:48 -080053static GLint tangentAttrib;
Brian Paul8796dbf2009-12-03 09:49:27 -070054static GLint tangentAttribTex;
55
56static GLuint Texture;
Brianf44ba112007-01-16 14:55:43 -070057
Brian271d5042007-01-16 15:27:11 -070058static GLboolean Anim = GL_FALSE;
Brian Paul8796dbf2009-12-03 09:49:27 -070059static GLboolean Textured = GL_FALSE;
Brian271d5042007-01-16 15:27:11 -070060
Brianf44ba112007-01-16 14:55:43 -070061
62static void
63CheckError(int line)
64{
65 GLenum err = glGetError();
66 if (err) {
67 printf("GL Error %s (0x%x) at line %d\n",
68 gluErrorString(err), (int) err, line);
69 }
70}
71
72/*
73 * Draw a square, specifying normal and tangent vectors.
74 */
75static void
76Square(GLfloat size)
77{
78 glNormal3f(0, 0, 1);
Brian Paulee0b1bc2009-07-17 13:23:11 -060079 glVertexAttrib3f(tangentAttrib, 1, 0, 0);
Brianf44ba112007-01-16 14:55:43 -070080 glBegin(GL_POLYGON);
81 glTexCoord2f(0, 0); glVertex2f(-size, -size);
82 glTexCoord2f(1, 0); glVertex2f( size, -size);
83 glTexCoord2f(1, 1); glVertex2f( size, size);
84 glTexCoord2f(0, 1); glVertex2f(-size, size);
85 glEnd();
86}
87
88
89static void
Brian271d5042007-01-16 15:27:11 -070090Cube(GLfloat size)
91{
92 /* +X */
93 glPushMatrix();
94 glRotatef(90, 0, 1, 0);
95 glTranslatef(0, 0, size);
96 Square(size);
97 glPopMatrix();
98
99 /* -X */
100 glPushMatrix();
101 glRotatef(-90, 0, 1, 0);
102 glTranslatef(0, 0, size);
103 Square(size);
104 glPopMatrix();
105
106 /* +Y */
107 glPushMatrix();
108 glRotatef(90, 1, 0, 0);
109 glTranslatef(0, 0, size);
110 Square(size);
111 glPopMatrix();
112
113 /* -Y */
114 glPushMatrix();
115 glRotatef(-90, 1, 0, 0);
116 glTranslatef(0, 0, size);
117 Square(size);
118 glPopMatrix();
119
120
121 /* +Z */
122 glPushMatrix();
123 glTranslatef(0, 0, size);
124 Square(size);
125 glPopMatrix();
126
127 /* -Z */
128 glPushMatrix();
129 glRotatef(180, 0, 1, 0);
130 glTranslatef(0, 0, size);
131 Square(size);
132 glPopMatrix();
133
134}
135
136
137static void
138Idle(void)
139{
140 GLint t = glutGet(GLUT_ELAPSED_TIME);
141 yRot = t * 0.05;
142 glutPostRedisplay();
143}
144
145
146static void
Brianf44ba112007-01-16 14:55:43 -0700147Redisplay(void)
148{
149 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
150
151 glPushMatrix();
152 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
153 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
154 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
155
Brian Paul8796dbf2009-12-03 09:49:27 -0700156 if (Textured)
157 glUseProgram(texProgram);
158 else
159 glUseProgram(program);
160
Brian271d5042007-01-16 15:27:11 -0700161 Cube(1.5);
Brianf44ba112007-01-16 14:55:43 -0700162
163 glPopMatrix();
164
Brianf44ba112007-01-16 14:55:43 -0700165 CheckError(__LINE__);
166
167 glutSwapBuffers();
168}
169
170
171static void
172Reshape(int width, int height)
173{
Brian Paul08a1e1e2009-04-09 17:04:58 -0600174 float ar = (float) width / (float) height;
Brianf44ba112007-01-16 14:55:43 -0700175 glViewport(0, 0, width, height);
176 glMatrixMode(GL_PROJECTION);
177 glLoadIdentity();
Brian Paul08a1e1e2009-04-09 17:04:58 -0600178 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
Brianf44ba112007-01-16 14:55:43 -0700179 glMatrixMode(GL_MODELVIEW);
180 glLoadIdentity();
181 glTranslatef(0.0f, 0.0f, -15.0f);
182}
183
184
185static void
186CleanUp(void)
187{
Brian Paulee0b1bc2009-07-17 13:23:11 -0600188 glDeleteShader(fragShader);
Brian Paul8796dbf2009-12-03 09:49:27 -0700189 glDeleteShader(fragTexShader);
Brian Paulee0b1bc2009-07-17 13:23:11 -0600190 glDeleteShader(vertShader);
191 glDeleteProgram(program);
Brian Paul8796dbf2009-12-03 09:49:27 -0700192 glDeleteProgram(texProgram);
Brianf44ba112007-01-16 14:55:43 -0700193 glutDestroyWindow(win);
194}
195
196
197static void
198Key(unsigned char key, int x, int y)
199{
200 const GLfloat step = 2.0;
201 (void) x;
202 (void) y;
203
204 switch(key) {
Brian271d5042007-01-16 15:27:11 -0700205 case 'a':
206 Anim = !Anim;
207 glutIdleFunc(Anim ? Idle : NULL);
208 break;
Brian Paul8796dbf2009-12-03 09:49:27 -0700209 case 't':
210 Textured = !Textured;
211 break;
Brianf44ba112007-01-16 14:55:43 -0700212 case 'z':
213 zRot += step;
214 break;
215 case 'Z':
216 zRot -= step;
217 break;
218 case 27:
219 CleanUp();
220 exit(0);
221 break;
222 }
223 glutPostRedisplay();
224}
225
226
227static void
228SpecialKey(int key, int x, int y)
229{
230 const GLfloat step = 2.0;
231
232 (void) x;
233 (void) y;
234
235 switch(key) {
236 case GLUT_KEY_UP:
237 xRot += step;
238 break;
239 case GLUT_KEY_DOWN:
240 xRot -= step;
241 break;
242 case GLUT_KEY_LEFT:
243 yRot -= step;
244 break;
245 case GLUT_KEY_RIGHT:
246 yRot += step;
247 break;
248 }
249 glutPostRedisplay();
250}
251
252
Brianf44ba112007-01-16 14:55:43 -0700253static void
254Init(void)
255{
Brian2dca3372008-04-09 22:28:23 -0600256 if (!ShadersSupported())
257 exit(1);
Brianf44ba112007-01-16 14:55:43 -0700258
Brian2dca3372008-04-09 22:28:23 -0600259 vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
260 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
261 program = LinkShaders(vertShader, fragShader);
Brianf44ba112007-01-16 14:55:43 -0700262
Brian Paulee0b1bc2009-07-17 13:23:11 -0600263 glUseProgram(program);
Brianf44ba112007-01-16 14:55:43 -0700264
Brian Paulee0b1bc2009-07-17 13:23:11 -0600265 assert(glIsProgram(program));
266 assert(glIsShader(fragShader));
267 assert(glIsShader(vertShader));
Brianf44ba112007-01-16 14:55:43 -0700268
269 assert(glGetError() == 0);
270
271 CheckError(__LINE__);
272
Brian Paul684049d2009-08-12 13:53:56 -0600273 SetUniformValues(program, Uniforms);
274 PrintUniforms(Uniforms);
Brianf44ba112007-01-16 14:55:43 -0700275
276 CheckError(__LINE__);
277
Brian Paulee0b1bc2009-07-17 13:23:11 -0600278 tangentAttrib = glGetAttribLocation(program, "Tangent");
Brianf44ba112007-01-16 14:55:43 -0700279 printf("Tangent Attrib: %d\n", tangentAttrib);
280
281 assert(tangentAttrib >= 0);
282
283 CheckError(__LINE__);
284
Brian Paul8796dbf2009-12-03 09:49:27 -0700285
286 /*
287 * As above, but fragment shader also uses a texture map.
288 */
289 fragTexShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragTexProgFile);
290 texProgram = LinkShaders(vertShader, fragTexShader);
291 glUseProgram(texProgram);
292 assert(glIsProgram(texProgram));
293 assert(glIsShader(fragTexShader));
294 SetUniformValues(texProgram, TexUniforms);
295 PrintUniforms(TexUniforms);
296
297 /*
298 * Load tex image.
299 */
300 glGenTextures(1, &Texture);
301 glBindTexture(GL_TEXTURE_2D, Texture);
302 LoadRGBMipmaps(TextureFile, GL_RGB);
303
304
Brianf44ba112007-01-16 14:55:43 -0700305 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
306
307 glEnable(GL_DEPTH_TEST);
308
309 glColor3f(1, 0, 0);
310}
311
312
313static void
314ParseOptions(int argc, char *argv[])
315{
316 int i;
317 for (i = 1; i < argc; i++) {
318 if (strcmp(argv[i], "-fs") == 0) {
Brian Paul8796dbf2009-12-03 09:49:27 -0700319 FragProgFile = argv[++i];
Brianf44ba112007-01-16 14:55:43 -0700320 }
321 else if (strcmp(argv[i], "-vs") == 0) {
Brian Paul8796dbf2009-12-03 09:49:27 -0700322 VertProgFile = argv[++i];
323 }
324 else if (strcmp(argv[i], "-t") == 0) {
325 TextureFile = argv[++i];
Brianf44ba112007-01-16 14:55:43 -0700326 }
327 }
328}
329
330
331int
332main(int argc, char *argv[])
333{
334 glutInit(&argc, argv);
Brianf44ba112007-01-16 14:55:43 -0700335 glutInitWindowSize(400, 400);
336 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
337 win = glutCreateWindow(argv[0]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100338 glewInit();
Brianf44ba112007-01-16 14:55:43 -0700339 glutReshapeFunc(Reshape);
340 glutKeyboardFunc(Key);
341 glutSpecialFunc(SpecialKey);
342 glutDisplayFunc(Redisplay);
343 ParseOptions(argc, argv);
344 Init();
345 glutMainLoop();
346 return 0;
347}
348