Merge branch 'mesa_7_7_branch'
[mesa.git] / progs / glsl / bump.c
1 /**
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>
12 #include <GL/glew.h>
13 #include <GL/glut.h>
14 #include "shaderutil.h"
15 #include "readtex.h"
16
17
18 static char *FragProgFile = "CH11-bumpmap.frag";
19 static char *FragTexProgFile = "CH11-bumpmaptex.frag";
20 static char *VertProgFile = "CH11-bumpmap.vert";
21 static char *TextureFile = "../images/tile.rgb";
22
23 /* program/shader objects */
24 static GLuint fragShader;
25 static GLuint fragTexShader;
26 static GLuint vertShader;
27 static GLuint program;
28 static GLuint texProgram;
29
30
31 static struct uniform_info Uniforms[] = {
32 { "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 },
37 END_OF_UNIFORMS
38 };
39
40 static 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
49 static GLint win = 0;
50
51 static GLfloat xRot = 20.0f, yRot = 0.0f, zRot = 0.0f;
52
53 static GLint tangentAttrib;
54 static GLint tangentAttribTex;
55
56 static GLuint Texture;
57
58 static GLboolean Anim = GL_FALSE;
59 static GLboolean Textured = GL_FALSE;
60
61
62 static void
63 CheckError(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 */
75 static void
76 Square(GLfloat size)
77 {
78 glNormal3f(0, 0, 1);
79 glVertexAttrib3f(tangentAttrib, 1, 0, 0);
80 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
89 static void
90 Cube(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
137 static void
138 Idle(void)
139 {
140 GLint t = glutGet(GLUT_ELAPSED_TIME);
141 yRot = t * 0.05;
142 glutPostRedisplay();
143 }
144
145
146 static void
147 Redisplay(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
156 if (Textured)
157 glUseProgram(texProgram);
158 else
159 glUseProgram(program);
160
161 Cube(1.5);
162
163 glPopMatrix();
164
165 CheckError(__LINE__);
166
167 glutSwapBuffers();
168 }
169
170
171 static void
172 Reshape(int width, int height)
173 {
174 float ar = (float) width / (float) height;
175 glViewport(0, 0, width, height);
176 glMatrixMode(GL_PROJECTION);
177 glLoadIdentity();
178 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
179 glMatrixMode(GL_MODELVIEW);
180 glLoadIdentity();
181 glTranslatef(0.0f, 0.0f, -15.0f);
182 }
183
184
185 static void
186 CleanUp(void)
187 {
188 glDeleteShader(fragShader);
189 glDeleteShader(fragTexShader);
190 glDeleteShader(vertShader);
191 glDeleteProgram(program);
192 glDeleteProgram(texProgram);
193 glutDestroyWindow(win);
194 }
195
196
197 static void
198 Key(unsigned char key, int x, int y)
199 {
200 const GLfloat step = 2.0;
201 (void) x;
202 (void) y;
203
204 switch(key) {
205 case 'a':
206 Anim = !Anim;
207 glutIdleFunc(Anim ? Idle : NULL);
208 break;
209 case 't':
210 Textured = !Textured;
211 break;
212 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
227 static void
228 SpecialKey(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
253 static void
254 Init(void)
255 {
256 if (!ShadersSupported())
257 exit(1);
258
259 vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
260 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
261 program = LinkShaders(vertShader, fragShader);
262
263 glUseProgram(program);
264
265 assert(glIsProgram(program));
266 assert(glIsShader(fragShader));
267 assert(glIsShader(vertShader));
268
269 assert(glGetError() == 0);
270
271 CheckError(__LINE__);
272
273 SetUniformValues(program, Uniforms);
274 PrintUniforms(Uniforms);
275
276 CheckError(__LINE__);
277
278 tangentAttrib = glGetAttribLocation(program, "Tangent");
279 printf("Tangent Attrib: %d\n", tangentAttrib);
280
281 assert(tangentAttrib >= 0);
282
283 CheckError(__LINE__);
284
285
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
305 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
306
307 glEnable(GL_DEPTH_TEST);
308
309 glColor3f(1, 0, 0);
310 }
311
312
313 static void
314 ParseOptions(int argc, char *argv[])
315 {
316 int i;
317 for (i = 1; i < argc; i++) {
318 if (strcmp(argv[i], "-fs") == 0) {
319 FragProgFile = argv[++i];
320 }
321 else if (strcmp(argv[i], "-vs") == 0) {
322 VertProgFile = argv[++i];
323 }
324 else if (strcmp(argv[i], "-t") == 0) {
325 TextureFile = argv[++i];
326 }
327 }
328 }
329
330
331 int
332 main(int argc, char *argv[])
333 {
334 glutInit(&argc, argv);
335 glutInitWindowSize(400, 400);
336 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
337 win = glutCreateWindow(argv[0]);
338 glewInit();
339 glutReshapeFunc(Reshape);
340 glutKeyboardFunc(Key);
341 glutSpecialFunc(SpecialKey);
342 glutDisplayFunc(Redisplay);
343 ParseOptions(argc, argv);
344 Init();
345 glutMainLoop();
346 return 0;
347 }
348