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