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