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