rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <string.h>
|
nuclear@1
|
4 #include <GL/glew.h>
|
nuclear@1
|
5 #ifdef __APPLE__
|
nuclear@1
|
6 #include <GLUT/glut.h>
|
nuclear@1
|
7 #else
|
nuclear@0
|
8 #include <GL/glut.h>
|
nuclear@1
|
9 #endif
|
nuclear@0
|
10 #include "sdr.h"
|
nuclear@0
|
11
|
nuclear@0
|
12 #ifdef FREEGLUT
|
nuclear@0
|
13 #include <GL/freeglut_ext.h>
|
nuclear@0
|
14 #define MOUSEWHEEL
|
nuclear@0
|
15 #endif
|
nuclear@0
|
16
|
nuclear@0
|
17 void redraw(void);
|
nuclear@0
|
18 void set_material_color(float r, float g, float b, float a);
|
nuclear@0
|
19 void setup_lights(void);
|
nuclear@0
|
20 void key_handler(unsigned char key, int x, int y);
|
nuclear@0
|
21 void key_up_handler(unsigned char key, int x, int y);
|
nuclear@0
|
22 void skey_handler(int key, int x, int y);
|
nuclear@0
|
23 void button_handler(int bn, int state, int x, int y);
|
nuclear@0
|
24 void mouse_handler(int x, int y);
|
nuclear@0
|
25 void reshape(int x, int y);
|
nuclear@0
|
26 #ifdef MOUSEWHEEL
|
nuclear@0
|
27 void wheel_handler(int unk, int dir, int x, int y);
|
nuclear@0
|
28 #endif
|
nuclear@0
|
29 void menu_handler(int val);
|
nuclear@0
|
30 void init_sdr(void);
|
nuclear@0
|
31
|
nuclear@0
|
32 int xres, yres;
|
nuclear@0
|
33
|
nuclear@0
|
34 float cam_x, cam_y = 0.6, cam_z = 4;
|
nuclear@0
|
35 float cam_rot, cam_pitch = 35.0;
|
nuclear@0
|
36
|
nuclear@0
|
37 float pan_offs = 0.025;
|
nuclear@0
|
38
|
nuclear@0
|
39 unsigned int prog;
|
nuclear@0
|
40
|
nuclear@0
|
41 float roughness = 0.24;
|
nuclear@0
|
42 float specularity = 0.86;
|
nuclear@0
|
43 float ior = 3.2;
|
nuclear@0
|
44 float spec_pow = 60.0;
|
nuclear@0
|
45
|
nuclear@0
|
46 enum {DSDR_LAMBERT, DSDR_OREN_NAYAR};
|
nuclear@0
|
47 enum {SSDR_PHONG, SSDR_BLINN, SSDR_COOK_TORR};
|
nuclear@0
|
48
|
nuclear@0
|
49 int dif_sdr = DSDR_OREN_NAYAR;
|
nuclear@0
|
50 int spec_sdr = SSDR_COOK_TORR;
|
nuclear@0
|
51
|
nuclear@0
|
52 int main(int argc, char **argv)
|
nuclear@0
|
53 {
|
nuclear@0
|
54 unsigned int vs, ps, pslib;
|
nuclear@0
|
55 int dif_menu, spec_menu, i;
|
nuclear@0
|
56
|
nuclear@0
|
57 for(i=1; i<argc; i++) {
|
nuclear@0
|
58 if(argv[i][0] == '-' && argv[i][2] == 0) {
|
nuclear@0
|
59 switch(argv[i][1]) {
|
nuclear@0
|
60 case 'd':
|
nuclear@0
|
61 if(strcmp(argv[++i], "lambert") == 0) {
|
nuclear@0
|
62 dif_sdr = DSDR_LAMBERT;
|
nuclear@0
|
63 } else if(strcmp(argv[i], "oren-nayar") == 0) {
|
nuclear@0
|
64 dif_sdr = DSDR_OREN_NAYAR;
|
nuclear@0
|
65 } else {
|
nuclear@0
|
66 printf("-d (diffuse model) choices:\n");
|
nuclear@0
|
67 printf(" lambert \"Photometria sive de mensura de gratibus luminis, colorum et umbrae\", 1760\n");
|
nuclear@0
|
68 printf(" oren-nayar \"Generalization of Lambert's Reflectance Model\", SIGGRAPH 1994\n");
|
nuclear@0
|
69 return EXIT_FAILURE;
|
nuclear@0
|
70 }
|
nuclear@0
|
71 break;
|
nuclear@0
|
72
|
nuclear@0
|
73 case 's':
|
nuclear@0
|
74 if(strcmp(argv[++i], "phong") == 0) {
|
nuclear@0
|
75 spec_sdr = SSDR_PHONG;
|
nuclear@0
|
76 } else if(strcmp(argv[i], "cook-torrance") == 0) {
|
nuclear@0
|
77 spec_sdr = SSDR_COOK_TORR;
|
nuclear@0
|
78 } else {
|
nuclear@0
|
79 printf("-s (specular model) choices:\n");
|
nuclear@0
|
80 printf(" phong \"Illumination for Computer Generated Pictures\", CACM 1975\n");
|
nuclear@0
|
81 printf(" blinn \"Models of Light Reflection for Computer Synthesized Pictures\", SIGGRAPH 1977\n");
|
nuclear@0
|
82 printf(" cook-torrance \"A Reflectance Model for Computer Graphics\", SIGGRAPH 1981\n");
|
nuclear@0
|
83 return EXIT_FAILURE;
|
nuclear@0
|
84 }
|
nuclear@0
|
85 break;
|
nuclear@0
|
86
|
nuclear@0
|
87 default:
|
nuclear@0
|
88 fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
|
nuclear@0
|
89 return EXIT_FAILURE;
|
nuclear@0
|
90 }
|
nuclear@0
|
91 }
|
nuclear@0
|
92 }
|
nuclear@0
|
93
|
nuclear@0
|
94 glutInitWindowSize(800, 600);
|
nuclear@0
|
95 glutInit(&argc, argv);
|
nuclear@0
|
96 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
|
nuclear@0
|
97 glutCreateWindow("1.roughness 2.specularity 3.ior 4.phong power");
|
nuclear@0
|
98 xres = glutGet(GLUT_WINDOW_WIDTH);
|
nuclear@0
|
99 yres = glutGet(GLUT_WINDOW_HEIGHT);
|
nuclear@0
|
100
|
nuclear@0
|
101 glutKeyboardFunc(key_handler);
|
nuclear@0
|
102 glutKeyboardUpFunc(key_up_handler);
|
nuclear@0
|
103 glutSpecialFunc(skey_handler);
|
nuclear@0
|
104 glutMotionFunc(mouse_handler);
|
nuclear@0
|
105 glutMouseFunc(button_handler);
|
nuclear@0
|
106 glutReshapeFunc(reshape);
|
nuclear@0
|
107 glutDisplayFunc(redraw);
|
nuclear@0
|
108 #ifdef MOUSEWHEEL
|
nuclear@0
|
109 glutMouseWheelFunc(wheel_handler);
|
nuclear@0
|
110 #endif
|
nuclear@0
|
111
|
nuclear@0
|
112 /* create the menus */
|
nuclear@0
|
113 dif_menu = glutCreateMenu(menu_handler);
|
nuclear@0
|
114 glutAddMenuEntry("lambert", DSDR_LAMBERT);
|
nuclear@0
|
115 glutAddMenuEntry("oren-nayar", DSDR_OREN_NAYAR);
|
nuclear@0
|
116
|
nuclear@0
|
117 spec_menu = glutCreateMenu(menu_handler);
|
nuclear@0
|
118 glutAddMenuEntry("phong", SSDR_PHONG + 10);
|
nuclear@0
|
119 glutAddMenuEntry("blinn", SSDR_BLINN + 10);
|
nuclear@0
|
120 glutAddMenuEntry("cook-torrance", SSDR_COOK_TORR + 10);
|
nuclear@0
|
121
|
nuclear@0
|
122 glutCreateMenu(menu_handler);
|
nuclear@0
|
123 glutAddSubMenu("diffuse models", dif_menu);
|
nuclear@0
|
124 glutAddSubMenu("specular models", spec_menu);
|
nuclear@0
|
125
|
nuclear@0
|
126 glutAttachMenu(GLUT_RIGHT_BUTTON);
|
nuclear@0
|
127
|
nuclear@0
|
128
|
nuclear@0
|
129 glEnable(GL_DEPTH_TEST);
|
nuclear@0
|
130 glEnable(GL_CULL_FACE);
|
nuclear@0
|
131
|
nuclear@0
|
132 glEnable(GL_LIGHTING);
|
nuclear@0
|
133 glEnable(GL_LIGHT0);
|
nuclear@0
|
134
|
nuclear@0
|
135 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
136 gluPerspective(45.0, (float)xres / (float)yres, 1.0, 100.0);
|
nuclear@0
|
137 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
138
|
nuclear@0
|
139 init_sdr();
|
nuclear@0
|
140
|
nuclear@0
|
141 if(!(vs = load_vertex_shader("sdr.vs.glsl"))) {
|
nuclear@0
|
142 fprintf(stderr, "failed to load vertex shader\n");
|
nuclear@0
|
143 return EXIT_FAILURE;
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146 if(!(pslib = load_pixel_shader("sdr_ref_models.glsl"))) {
|
nuclear@0
|
147 fprintf(stderr, "failed to load reflection models shader\n");
|
nuclear@0
|
148 return EXIT_FAILURE;
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 if(!(ps = load_pixel_shader("sdr.ps.glsl"))) {
|
nuclear@0
|
152 fprintf(stderr, "failed to load pixel shader\n");
|
nuclear@0
|
153 return EXIT_FAILURE;
|
nuclear@0
|
154 }
|
nuclear@0
|
155
|
nuclear@0
|
156 if(!(prog = create_program())) {
|
nuclear@0
|
157 fprintf(stderr, "failed to create GPU program\n");
|
nuclear@0
|
158 return EXIT_FAILURE;
|
nuclear@0
|
159 }
|
nuclear@0
|
160 attach_shader(prog, vs);
|
nuclear@0
|
161 attach_shader(prog, pslib);
|
nuclear@0
|
162 attach_shader(prog, ps);
|
nuclear@0
|
163
|
nuclear@0
|
164 if(link_program(prog) == -1) {
|
nuclear@0
|
165 fprintf(stderr, "failed to link GPU program\n");
|
nuclear@0
|
166 return EXIT_FAILURE;
|
nuclear@0
|
167 }
|
nuclear@0
|
168
|
nuclear@0
|
169 glutMainLoop();
|
nuclear@0
|
170 return 0;
|
nuclear@0
|
171 }
|
nuclear@0
|
172
|
nuclear@0
|
173 void setup_lights(void)
|
nuclear@0
|
174 {
|
nuclear@0
|
175 float lpos[] = {-6, 8, 10, 1};
|
nuclear@0
|
176 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
|
nuclear@0
|
177 }
|
nuclear@0
|
178
|
nuclear@0
|
179 void redraw(void)
|
nuclear@0
|
180 {
|
nuclear@0
|
181 glClearColor(0, 0, 0, 0);
|
nuclear@0
|
182 glClearDepth(1.0);
|
nuclear@0
|
183
|
nuclear@0
|
184 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@0
|
185
|
nuclear@0
|
186 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
187 glLoadIdentity();
|
nuclear@0
|
188 glTranslatef(-cam_x, -cam_y, -cam_z);
|
nuclear@0
|
189 glRotatef(cam_pitch, 1, 0, 0);
|
nuclear@0
|
190 glRotatef(cam_rot, 0, 1, 0);
|
nuclear@0
|
191
|
nuclear@0
|
192 setup_lights();
|
nuclear@0
|
193
|
nuclear@0
|
194 glPushMatrix();
|
nuclear@0
|
195 glTranslatef(0, 0.8, 0);
|
nuclear@0
|
196
|
nuclear@0
|
197 bind_program(prog);
|
nuclear@0
|
198 set_uniform_float(prog, "rough", roughness);
|
nuclear@0
|
199 set_uniform_float(prog, "specularity", specularity);
|
nuclear@0
|
200 set_uniform_float(prog, "ior", ior);
|
nuclear@0
|
201 set_uniform_float(prog, "dif_sdr", dif_sdr);
|
nuclear@0
|
202 set_uniform_float(prog, "spec_sdr", spec_sdr);
|
nuclear@0
|
203 glFrontFace(GL_CW);
|
nuclear@0
|
204 set_material_color(0.55, 0.20, 0.10, 1.0);
|
nuclear@0
|
205 /*set_material_color(0.87, 0.72, 0.62, 1.0);*/
|
nuclear@0
|
206 glutSolidTeapot(1.0);
|
nuclear@0
|
207 glFrontFace(GL_CCW);
|
nuclear@0
|
208 bind_program(0);
|
nuclear@0
|
209
|
nuclear@0
|
210 glPopMatrix();
|
nuclear@0
|
211
|
nuclear@0
|
212
|
nuclear@0
|
213 glutSwapBuffers();
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 void set_material_color(float r, float g, float b, float a)
|
nuclear@0
|
217 {
|
nuclear@0
|
218 float col[4];
|
nuclear@0
|
219 col[0] = r;
|
nuclear@0
|
220 col[1] = g;
|
nuclear@0
|
221 col[2] = b;
|
nuclear@0
|
222 col[3] = a;
|
nuclear@0
|
223 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
|
nuclear@0
|
224 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, spec_pow);
|
nuclear@0
|
225 }
|
nuclear@0
|
226
|
nuclear@0
|
227 int mod_rough, mod_spec, mod_ior, mod_spow;
|
nuclear@0
|
228
|
nuclear@0
|
229 void key_handler(unsigned char key, int x, int y)
|
nuclear@0
|
230 {
|
nuclear@0
|
231 switch(key) {
|
nuclear@0
|
232 case 27:
|
nuclear@0
|
233 exit(0);
|
nuclear@0
|
234
|
nuclear@0
|
235 case '1':
|
nuclear@0
|
236 mod_rough = 1;
|
nuclear@0
|
237 break;
|
nuclear@0
|
238
|
nuclear@0
|
239 case '2':
|
nuclear@0
|
240 mod_spec = 1;
|
nuclear@0
|
241 break;
|
nuclear@0
|
242
|
nuclear@0
|
243 case '3':
|
nuclear@0
|
244 mod_ior = 1;
|
nuclear@0
|
245 break;
|
nuclear@0
|
246
|
nuclear@0
|
247 case '4':
|
nuclear@0
|
248 mod_spow = 1;
|
nuclear@0
|
249 break;
|
nuclear@0
|
250
|
nuclear@0
|
251 default:
|
nuclear@0
|
252 break;
|
nuclear@0
|
253 }
|
nuclear@0
|
254 }
|
nuclear@0
|
255
|
nuclear@0
|
256 void key_up_handler(unsigned char key, int x, int y)
|
nuclear@0
|
257 {
|
nuclear@0
|
258 switch(key) {
|
nuclear@0
|
259 case '1':
|
nuclear@0
|
260 mod_rough = 0;
|
nuclear@0
|
261 break;
|
nuclear@0
|
262
|
nuclear@0
|
263 case '2':
|
nuclear@0
|
264 mod_spec = 0;
|
nuclear@0
|
265 break;
|
nuclear@0
|
266
|
nuclear@0
|
267 case '3':
|
nuclear@0
|
268 mod_ior = 0;
|
nuclear@0
|
269 break;
|
nuclear@0
|
270
|
nuclear@0
|
271 case '4':
|
nuclear@0
|
272 mod_spow = 0;
|
nuclear@0
|
273 break;
|
nuclear@0
|
274
|
nuclear@0
|
275 default:
|
nuclear@0
|
276 break;
|
nuclear@0
|
277 }
|
nuclear@0
|
278 }
|
nuclear@0
|
279
|
nuclear@0
|
280 void skey_handler(int key, int x, int y)
|
nuclear@0
|
281 {
|
nuclear@0
|
282 switch(key) {
|
nuclear@0
|
283 default:
|
nuclear@0
|
284 break;
|
nuclear@0
|
285 }
|
nuclear@0
|
286 }
|
nuclear@0
|
287
|
nuclear@0
|
288 static int prev_x = -1;
|
nuclear@0
|
289 static int prev_y = -1;
|
nuclear@0
|
290 static int pbn;
|
nuclear@0
|
291
|
nuclear@0
|
292 void button_handler(int button, int state, int x, int y)
|
nuclear@0
|
293 {
|
nuclear@0
|
294 if(state == GLUT_DOWN) {
|
nuclear@0
|
295 prev_x = x;
|
nuclear@0
|
296 prev_y = y;
|
nuclear@0
|
297 pbn = button;
|
nuclear@0
|
298 } else {
|
nuclear@0
|
299 prev_x = -1;
|
nuclear@0
|
300 prev_y = -1;
|
nuclear@0
|
301 }
|
nuclear@0
|
302 }
|
nuclear@0
|
303
|
nuclear@0
|
304
|
nuclear@0
|
305 #define MIN(a, b) ((a) < (b) ? (a) : (b))
|
nuclear@0
|
306 #define MAX(a, b) ((a) > (b) ? (a) : (b))
|
nuclear@0
|
307
|
nuclear@0
|
308 void mouse_handler(int x, int y)
|
nuclear@0
|
309 {
|
nuclear@0
|
310 if(pbn == GLUT_LEFT_BUTTON) {
|
nuclear@0
|
311 if(mod_rough || mod_spec || mod_ior || mod_spow) {
|
nuclear@0
|
312 float dx = (float)(x - prev_x) / (float)xres;
|
nuclear@0
|
313
|
nuclear@0
|
314 if(mod_rough) {
|
nuclear@0
|
315 roughness = MAX(0.0, MIN(roughness + dx, 1.0));
|
nuclear@0
|
316 printf("roughness: %.3f\n", roughness);
|
nuclear@0
|
317 }
|
nuclear@0
|
318 if(mod_spec) {
|
nuclear@0
|
319 specularity = MAX(0.0, MIN(specularity + dx, 1.0));
|
nuclear@0
|
320 printf("specularity: %.3f\n", specularity);
|
nuclear@0
|
321 }
|
nuclear@0
|
322 if(mod_ior) {
|
nuclear@0
|
323 ior = MAX(ior + dx, 0.0);
|
nuclear@0
|
324 printf("ior: %.3f\n", ior);
|
nuclear@0
|
325 }
|
nuclear@0
|
326 if(mod_spow) {
|
nuclear@0
|
327 spec_pow = MAX(spec_pow + dx * 50.0, 0.01);
|
nuclear@0
|
328 printf("specular power: %.3f\n", spec_pow);
|
nuclear@0
|
329 }
|
nuclear@0
|
330 } else {
|
nuclear@0
|
331 /*
|
nuclear@0
|
332 cam_x += (float)(prev_x - x) * pan_offs;
|
nuclear@0
|
333 cam_y += (float)(y - prev_y) * pan_offs;
|
nuclear@0
|
334 */
|
nuclear@0
|
335 }
|
nuclear@0
|
336
|
nuclear@0
|
337 prev_x = x;
|
nuclear@0
|
338 prev_y = y;
|
nuclear@0
|
339 glutPostRedisplay();
|
nuclear@0
|
340
|
nuclear@0
|
341 } else if(pbn == GLUT_MIDDLE_BUTTON) {
|
nuclear@0
|
342 cam_rot += (float)(x - prev_x) / 2.0f;
|
nuclear@0
|
343 cam_pitch += (float)(y - prev_y) / 2.0f;
|
nuclear@0
|
344 if(cam_pitch > 90.0) cam_pitch = 90.0;
|
nuclear@0
|
345 if(cam_pitch < -90.0) cam_pitch = -90.0;
|
nuclear@0
|
346
|
nuclear@0
|
347 prev_x = x;
|
nuclear@0
|
348 prev_y = y;
|
nuclear@0
|
349 glutPostRedisplay();
|
nuclear@0
|
350
|
nuclear@0
|
351 } else if(pbn == GLUT_RIGHT_BUTTON) {
|
nuclear@0
|
352 /*
|
nuclear@0
|
353 cam_z -= (float)(prev_y - y) / 2.0f;
|
nuclear@0
|
354 prev_y = y;
|
nuclear@0
|
355 glutPostRedisplay();
|
nuclear@0
|
356 */
|
nuclear@0
|
357 }
|
nuclear@0
|
358 }
|
nuclear@0
|
359
|
nuclear@0
|
360 void reshape(int x, int y)
|
nuclear@0
|
361 {
|
nuclear@0
|
362 glViewport(0, 0, x, y);
|
nuclear@0
|
363 xres = x;
|
nuclear@0
|
364 yres = y;
|
nuclear@0
|
365
|
nuclear@0
|
366 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
367 glLoadIdentity();
|
nuclear@0
|
368 gluPerspective(45.0, (float)xres / (float)yres, 1.0, 100.0);
|
nuclear@0
|
369 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
370 }
|
nuclear@0
|
371
|
nuclear@0
|
372 #ifdef MOUSEWHEEL
|
nuclear@0
|
373 void wheel_handler(int unk, int dir, int x, int y)
|
nuclear@0
|
374 {
|
nuclear@0
|
375 if(dir > 0) {
|
nuclear@0
|
376 cam_z -= pan_offs * 5.0;
|
nuclear@0
|
377 } else {
|
nuclear@0
|
378 cam_z += pan_offs * 5.0;
|
nuclear@0
|
379 }
|
nuclear@0
|
380 glutPostRedisplay();
|
nuclear@0
|
381 }
|
nuclear@0
|
382 #endif
|
nuclear@0
|
383
|
nuclear@0
|
384 void menu_handler(int val)
|
nuclear@0
|
385 {
|
nuclear@0
|
386 if(val < 10) {
|
nuclear@0
|
387 dif_sdr = val;
|
nuclear@0
|
388 } else {
|
nuclear@0
|
389 spec_sdr = val - 10;
|
nuclear@0
|
390 }
|
nuclear@0
|
391 glutPostRedisplay();
|
nuclear@0
|
392 }
|