rayfract

view src/rayfract.cc @ 1:03022062c464

lalal
author John Tsiombikas <nuclear@siggraph.org>
date Tue, 26 Oct 2010 08:45:37 +0300
parents 09bb67c000bc
children bf1d56975cc9
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <GL/glew.h>
5 #include <GL/glut.h>
6 #include <vmath.h>
7 #include "sdr.h"
8 #include "gui.h"
10 void disp();
11 void reshape(int x, int y);
12 void keyb(unsigned char key, int x, int y);
13 void keyb_up(unsigned char key, int x, int y);
14 void mouse(int bn, int state, int x, int y);
15 void motion(int x, int y);
16 void passive_motion(int x, int y);
18 int load_shader();
19 unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale = 0);
20 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg);
21 static int round_pow2(int x);
23 float cam_theta = 0, cam_phi = 0, cam_dist = 4.0;
24 float cam_y = 0;
26 unsigned int sdr;
27 unsigned int ray_tex;
28 Vector2 tex_scale;
29 Vector4 seed;
30 float err_thres = 0.0075;
31 int iter = 10;
32 float reflectivity = 0.2;
33 Vector3 color(0.9, 0.95, 1.0);
35 int main(int argc, char **argv)
36 {
37 int xsz, ysz;
39 seed = Vector4(0.4, 0.0, 0.0, -0.8);
41 glutInitWindowSize(640, 480);
42 glutInit(&argc, argv);
43 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
44 glutCreateWindow("Raytraced Fractals");
45 xsz = glutGet(GLUT_WINDOW_WIDTH);
46 ysz = glutGet(GLUT_WINDOW_HEIGHT);
48 glutDisplayFunc(disp);
49 glutReshapeFunc(reshape);
50 glutKeyboardFunc(keyb);
51 glutKeyboardUpFunc(keyb_up);
52 glutMouseFunc(mouse);
53 glutMotionFunc(motion);
54 glutPassiveMotionFunc(passive_motion);
56 glEnable(GL_DEPTH_TEST);
57 glEnable(GL_LIGHTING);
58 glEnable(GL_LIGHT0);
59 glEnable(GL_CULL_FACE);
61 glewInit();
63 if(load_shader() == -1) {
64 return 1;
65 }
67 if(gui_init(xsz, ysz) == -1) {
68 return 1;
69 }
71 glutMainLoop();
72 return 0;
73 }
75 int load_shader()
76 {
77 if(sdr) {
78 free_program(sdr);
79 }
81 if(!(sdr = create_program_load("sdr/sdr.v.glsl", "sdr/julia.p.glsl"))) {
82 return -1;
83 }
84 set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w);
85 set_uniform_float(sdr, "err_thres", err_thres);
86 set_uniform_int(sdr, "iter", iter);
87 set_uniform_float(sdr, "reflectivity", reflectivity);
88 set_uniform_float3(sdr, "diffuse_color", color.x, color.y, color.z);
90 return 0;
91 }
93 void disp()
94 {
95 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
97 glMatrixMode(GL_MODELVIEW);
98 glLoadIdentity();
99 glRotatef(cam_theta, 0, 1, 0);
100 glRotatef(cam_phi, 1, 0, 0);
101 glTranslatef(0, 0, -cam_dist);
103 float lpos[] = {-1, 1, 3, 0};
104 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
107 glMatrixMode(GL_TEXTURE);
108 glPushMatrix();
109 glScalef(tex_scale.x, tex_scale.y, 1.0);
111 glBindTexture(GL_TEXTURE_2D, ray_tex);
112 glEnable(GL_TEXTURE_2D);
113 bind_program(sdr);
115 glBegin(GL_QUADS);
116 glColor3f(1, 1, 1);
117 glTexCoord2f(0, 1); glVertex2f(-1, -1);
118 glTexCoord2f(1, 1); glVertex2f(1, -1);
119 glTexCoord2f(1, 0); glVertex2f(1, 1);
120 glTexCoord2f(0, 0); glVertex2f(-1, 1);
121 glEnd();
123 bind_program(0);
124 glDisable(GL_TEXTURE_2D);
126 glMatrixMode(GL_TEXTURE);
127 glPopMatrix();
129 gui_draw();
131 glutSwapBuffers();
132 assert(glGetError() == GL_NO_ERROR);
133 }
135 void reshape(int x, int y)
136 {
137 glViewport(0, 0, x, y);
138 glMatrixMode(GL_PROJECTION);
139 glLoadIdentity();
140 gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0);
142 if(ray_tex) {
143 glDeleteTextures(1, &ray_tex);
144 }
145 ray_tex = create_ray_texture(x, y, 50.0, &tex_scale);
146 }
149 void keyb(unsigned char key, int x, int y)
150 {
151 switch(key) {
152 case 27:
153 exit(0);
155 case '-':
156 if(iter > 1) {
157 iter--;
158 set_uniform_int(sdr, "iter", iter);
159 printf("iter: %d\n", iter);
160 glutPostRedisplay();
161 }
162 break;
164 case '=':
165 iter++;
166 set_uniform_int(sdr, "iter", iter);
167 printf("iter: %d\n", iter);
168 glutPostRedisplay();
169 break;
171 case ',':
172 err_thres -= 0.001;
173 set_uniform_float(sdr, "err_thres", err_thres);
174 printf("maximum error: %f\n", err_thres);
175 glutPostRedisplay();
176 break;
178 case '.':
179 err_thres += 0.001;
180 set_uniform_float(sdr, "err_thres", err_thres);
181 printf("maximum error: %f\n", err_thres);
182 glutPostRedisplay();
183 break;
185 case 's':
186 load_shader();
187 glutPostRedisplay();
188 break;
190 case 'r':
191 reflectivity = reflectivity > 0.0 ? 0.0 : 0.6;
192 set_uniform_float(sdr, "reflectivity", reflectivity);
193 glutPostRedisplay();
194 break;
196 case '`':
197 {
198 static bool vis = true;
199 vis = !vis;
200 gui_set_visible(vis);
201 glutPostRedisplay();
202 }
203 break;
204 }
206 utk::KeyboardEvent ev(key);
207 ev.pressed = true;
208 utk::event(&ev);
209 glutPostRedisplay();
210 }
212 void keyb_up(unsigned char key, int x, int y)
213 {
214 utk::KeyboardEvent ev(key);
215 ev.pressed = false;
216 utk::event(&ev);
217 glutPostRedisplay();
218 }
220 int bnstate[16];
222 int prev_x = -1, prev_y;
223 void mouse(int bn, int state, int x, int y)
224 {
225 utk::Container *utkroot = utk::get_root_widget();
227 if(utkroot->get_child_at(x, y) == utkroot) {
228 bnstate[bn] = state == GLUT_DOWN ? 1 : 0;
229 if(state == GLUT_DOWN) {
230 if(bn == 3) {
231 cam_dist -= 0.1;
232 glutPostRedisplay();
233 if(cam_dist < 0) cam_dist = 0;
234 } else if(bn == 4) {
235 cam_dist += 0.1;
236 glutPostRedisplay();
237 } else {
238 prev_x = x;
239 prev_y = y;
240 }
241 } else {
242 prev_x = -1;
243 }
244 }
246 utk::MButtonEvent ev(bn, x, y);
247 ev.pressed = state == GLUT_DOWN;
248 utk::event(&ev);
249 glutPostRedisplay();
250 }
252 void motion(int x, int y)
253 {
254 if(bnstate[0]) {
255 cam_theta += (x - prev_x) * 0.5;
256 cam_phi += (y - prev_y) * 0.5;
258 if(cam_phi < -90) cam_phi = -90;
259 if(cam_phi > 90) cam_phi = 90;
261 glutPostRedisplay();
262 }
264 if(bnstate[1]) {
265 cam_y += (y - prev_y) * 0.1;
266 glutPostRedisplay();
267 }
269 if(bnstate[2]) {
270 cam_dist += (y - prev_y) * 0.1;
271 glutPostRedisplay();
272 }
274 prev_x = x;
275 prev_y = y;
277 utk::MMotionEvent ev(x, y);
278 utk::event(&ev);
279 glutPostRedisplay();
280 }
282 void passive_motion(int x, int y)
283 {
284 utk::MMotionEvent ev(x, y);
285 utk::event(&ev);
286 //glutPostRedisplay();
287 }
289 unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale)
290 {
291 unsigned int tex;
292 int tex_xsz = round_pow2(xsz);
293 int tex_ysz = round_pow2(ysz);
294 float *teximg, *dir;
296 teximg = new float[3 * tex_xsz * tex_ysz];
297 dir = teximg;
299 for(int i=0; i<tex_ysz; i++) {
300 for(int j=0; j<tex_xsz; j++) {
301 if(j < xsz && i < ysz) {
302 Vector3 rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov);
303 dir[0] = rdir.x;
304 dir[1] = rdir.y;
305 dir[2] = rdir.z;
306 } else {
307 dir[0] = dir[1] = 0.0f;
308 dir[2] = 1.0f;
309 }
311 dir += 3;
312 }
313 }
315 glGenTextures(1, &tex);
316 glBindTexture(GL_TEXTURE_2D, tex);
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
321 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, teximg);
322 delete [] teximg;
324 if(tex_scale) {
325 tex_scale->x = (float)xsz / (float)tex_xsz;
326 tex_scale->y = (float)ysz / (float)tex_ysz;
327 }
328 return tex;
329 }
331 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg)
332 {
333 float vfov = M_PI * vfov_deg / 180.0;
334 float aspect = (float)w / (float)h;
336 float ysz = 2.0;
337 float xsz = aspect * ysz;
339 float px = ((float)x / (float)w) * xsz - xsz / 2.0;
340 float py = 1.0 - ((float)y / (float)h) * ysz;
341 float pz = 1.0 / tan(0.5 * vfov);
343 float mag = sqrt(px * px + py * py + pz * pz);
345 return Vector3(px / mag, py / mag, pz / mag);
346 }
348 static int round_pow2(int x)
349 {
350 x--;
351 x = (x >> 1) | x;
352 x = (x >> 2) | x;
353 x = (x >> 4) | x;
354 x = (x >> 8) | x;
355 x = (x >> 16) | x;
356 return x + 1;
357 }