blob: b71c3af970b46d1865a32f93139adadadc9bdf9c [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>
12#include <GL/glut.h>
13#include <GL/glu.h>
14#include <GL/glext.h>
15#include "extfuncs.h"
16
17
18static char *FragProgFile = "CH11-bumpmap.frag.txt";
19static char *VertProgFile = "CH11-bumpmap.vert.txt";
20
21/* program/shader objects */
22static GLuint fragShader;
23static GLuint vertShader;
24static GLuint program;
25
26
27struct uniform_info {
28 const char *name;
29 GLuint size;
30 GLint location;
31 GLfloat value[4];
32};
33
34static struct uniform_info Uniforms[] = {
35 { "LightPosition", 3, -1, { 0.57737, 0.57735, 0.57735, 0.0 } },
36 { "SurfaceColor", 3, -1, { 0.8, 0.8, 0.2, 0 } },
37 { "BumpDensity", 1, -1, { 16.0, 0, 0, 0 } },
38 { "BumpSize", 1, -1, { 0.15, 0, 0, 0 } },
39 { "SpecularFactor", 1, -1, { 0.5, 0, 0, 0 } },
40 { NULL, 0, 0, { 0, 0, 0, 0 } }
41};
42
43static GLint win = 0;
44
45static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
46
47static GLuint tangentAttrib;
48
49
50static void
51CheckError(int line)
52{
53 GLenum err = glGetError();
54 if (err) {
55 printf("GL Error %s (0x%x) at line %d\n",
56 gluErrorString(err), (int) err, line);
57 }
58}
59
60/*
61 * Draw a square, specifying normal and tangent vectors.
62 */
63static void
64Square(GLfloat size)
65{
66 glNormal3f(0, 0, 1);
67 glVertexAttrib3f_func(tangentAttrib, 1, 0, 0);
68 glBegin(GL_POLYGON);
69 glTexCoord2f(0, 0); glVertex2f(-size, -size);
70 glTexCoord2f(1, 0); glVertex2f( size, -size);
71 glTexCoord2f(1, 1); glVertex2f( size, size);
72 glTexCoord2f(0, 1); glVertex2f(-size, size);
73 glEnd();
74}
75
76
77static void
78Redisplay(void)
79{
80 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
81
82 glPushMatrix();
83 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
84 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
85 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
86
87 Square(2.0);
88
89 glPopMatrix();
90
91 glFinish();
92 glFlush();
93
94 CheckError(__LINE__);
95
96 glutSwapBuffers();
97}
98
99
100static void
101Reshape(int width, int height)
102{
103 glViewport(0, 0, width, height);
104 glMatrixMode(GL_PROJECTION);
105 glLoadIdentity();
106 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
107 glMatrixMode(GL_MODELVIEW);
108 glLoadIdentity();
109 glTranslatef(0.0f, 0.0f, -15.0f);
110}
111
112
113static void
114CleanUp(void)
115{
116 glDeleteShader_func(fragShader);
117 glDeleteShader_func(vertShader);
118 glDeleteProgram_func(program);
119 glutDestroyWindow(win);
120}
121
122
123static void
124Key(unsigned char key, int x, int y)
125{
126 const GLfloat step = 2.0;
127 (void) x;
128 (void) y;
129
130 switch(key) {
131 case 'z':
132 zRot += step;
133 break;
134 case 'Z':
135 zRot -= step;
136 break;
137 case 27:
138 CleanUp();
139 exit(0);
140 break;
141 }
142 glutPostRedisplay();
143}
144
145
146static void
147SpecialKey(int key, int x, int y)
148{
149 const GLfloat step = 2.0;
150
151 (void) x;
152 (void) y;
153
154 switch(key) {
155 case GLUT_KEY_UP:
156 xRot += step;
157 break;
158 case GLUT_KEY_DOWN:
159 xRot -= step;
160 break;
161 case GLUT_KEY_LEFT:
162 yRot -= step;
163 break;
164 case GLUT_KEY_RIGHT:
165 yRot += step;
166 break;
167 }
168 glutPostRedisplay();
169}
170
171
172
173static void
174LoadAndCompileShader(GLuint shader, const char *text)
175{
176 GLint stat;
177
178 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
179
180 glCompileShader_func(shader);
181
182 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
183 if (!stat) {
184 GLchar log[1000];
185 GLsizei len;
186 glGetShaderInfoLog_func(shader, 1000, &len, log);
187 fprintf(stderr, "brick: problem compiling shader: %s\n", log);
188 exit(1);
189 }
190 else {
191 printf("Shader compiled OK\n");
192 }
193}
194
195
196/**
197 * Read a shader from a file.
198 */
199static void
200ReadShader(GLuint shader, const char *filename)
201{
202 const int max = 100*1000;
203 int n;
204 char *buffer = (char*) malloc(max);
205 FILE *f = fopen(filename, "r");
206 if (!f) {
207 fprintf(stderr, "brick: Unable to open shader file %s\n", filename);
208 exit(1);
209 }
210
211 n = fread(buffer, 1, max, f);
212 printf("brick: read %d bytes from shader file %s\n", n, filename);
213 if (n > 0) {
214 buffer[n] = 0;
215 LoadAndCompileShader(shader, buffer);
216 }
217
218 fclose(f);
219 free(buffer);
220}
221
222
223static void
224CheckLink(GLuint prog)
225{
226 GLint stat;
227 glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
228 if (!stat) {
229 GLchar log[1000];
230 GLsizei len;
231 glGetProgramInfoLog_func(prog, 1000, &len, log);
232 fprintf(stderr, "Linker error:\n%s\n", log);
233 }
234 else {
235 fprintf(stderr, "Link success!\n");
236 }
237}
238
239
240static void
241Init(void)
242{
243 const char *version;
244 GLint i;
245
246 version = (const char *) glGetString(GL_VERSION);
247 if (version[0] != '2' || version[1] != '.') {
248 printf("Warning: this program expects OpenGL 2.0\n");
249 /*exit(1);*/
250 }
251 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
252
253 GetExtensionFuncs();
254
255 vertShader = glCreateShader_func(GL_VERTEX_SHADER);
256 ReadShader(vertShader, VertProgFile);
257
258 fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
259 ReadShader(fragShader, FragProgFile);
260
261 program = glCreateProgram_func();
262 glAttachShader_func(program, fragShader);
263 glAttachShader_func(program, vertShader);
264 glLinkProgram_func(program);
265 CheckLink(program);
266 glUseProgram_func(program);
267
268 assert(glIsProgram_func(program));
269 assert(glIsShader_func(fragShader));
270 assert(glIsShader_func(vertShader));
271
272 assert(glGetError() == 0);
273
274 CheckError(__LINE__);
275
276 for (i = 0; Uniforms[i].name; i++) {
277 Uniforms[i].location
278 = glGetUniformLocation_func(program, Uniforms[i].name);
279 printf("Uniform %s location: %d\n", Uniforms[i].name,
280 Uniforms[i].location);
281 switch (Uniforms[i].size) {
282 case 1:
283 glUniform1fv_func(Uniforms[i].location, 1, Uniforms[i].value);
284 break;
285 case 2:
286 glUniform2fv_func(Uniforms[i].location, 1, Uniforms[i].value);
287 break;
288 case 3:
289 glUniform3fv_func(Uniforms[i].location, 1, Uniforms[i].value);
290 break;
291 case 4:
292 glUniform4fv_func(Uniforms[i].location, 1, Uniforms[i].value);
293 break;
294 default:
295 abort();
296 }
297 }
298
299 CheckError(__LINE__);
300
301 tangentAttrib = glGetAttribLocation_func(program, "Tangent");
302 printf("Tangent Attrib: %d\n", tangentAttrib);
303
304 assert(tangentAttrib >= 0);
305
306 CheckError(__LINE__);
307
308 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
309
310 glEnable(GL_DEPTH_TEST);
311
312 glColor3f(1, 0, 0);
313}
314
315
316static void
317ParseOptions(int argc, char *argv[])
318{
319 int i;
320 for (i = 1; i < argc; i++) {
321 if (strcmp(argv[i], "-fs") == 0) {
322 FragProgFile = argv[i+1];
323 }
324 else if (strcmp(argv[i], "-vs") == 0) {
325 VertProgFile = argv[i+1];
326 }
327 }
328}
329
330
331int
332main(int argc, char *argv[])
333{
334 glutInit(&argc, argv);
335 glutInitWindowPosition( 0, 0);
336 glutInitWindowSize(400, 400);
337 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
338 win = glutCreateWindow(argv[0]);
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