rayfract

view src/rayfract.cc @ 0:09bb67c000bc

ray-fract repository
author John Tsiombikas <nuclear@siggraph.org>
date Thu, 21 Oct 2010 23:39:26 +0300
parents
children 03022062c464
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"
9 void disp();
10 void reshape(int x, int y);
11 void keyb(unsigned char key, int x, int y);
12 void mouse(int bn, int state, int x, int y);
13 void motion(int x, int y);
15 int load_shader();
16 unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale = 0);
17 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg);
18 static int round_pow2(int x);
20 float cam_theta = 0, cam_phi = 0, cam_dist = 4.0;
21 float cam_y = 0;
23 unsigned int sdr;
24 unsigned int ray_tex;
25 Vector2 tex_scale;
26 Vector4 seed;
27 float err_thres = 0.0075;
28 int iter = 10;
30 int main(int argc, char **argv)
31 {
32 int xsz, ysz;
34 seed = Vector4(0.4, 0.0, 0.0, -0.8);
36 glutInitWindowSize(640, 480);
37 glutInit(&argc, argv);
38 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
39 glutCreateWindow("Raytraced Fractals");
40 xsz = glutGet(GLUT_WINDOW_WIDTH);
41 ysz = glutGet(GLUT_WINDOW_HEIGHT);
43 glutDisplayFunc(disp);
44 glutReshapeFunc(reshape);
45 glutKeyboardFunc(keyb);
46 glutMouseFunc(mouse);
47 glutMotionFunc(motion);
49 glEnable(GL_DEPTH_TEST);
50 glEnable(GL_LIGHTING);
51 glEnable(GL_LIGHT0);
52 glEnable(GL_CULL_FACE);
54 glewInit();
56 if(load_shader() == -1) {
57 return 1;
58 }
60 glutMainLoop();
61 return 0;
62 }
64 int load_shader()
65 {
66 if(sdr) {
67 free_program(sdr);
68 }
70 if(!(sdr = create_program_load("sdr/sdr.v.glsl", "sdr/julia.p.glsl"))) {
71 return -1;
72 }
73 set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w);
74 set_uniform_float(sdr, "err_thres", err_thres);
75 set_uniform_int(sdr, "iter", iter);
76 return 0;
77 }
79 void disp()
80 {
81 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
83 glMatrixMode(GL_MODELVIEW);
84 glLoadIdentity();
85 glRotatef(cam_theta, 0, 1, 0);
86 glRotatef(cam_phi, 1, 0, 0);
87 glTranslatef(0, 0, -cam_dist);
89 float lpos[] = {-1, 1, 3, 0};
90 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
93 glMatrixMode(GL_TEXTURE);
94 glPushMatrix();
95 glScalef(tex_scale.x, tex_scale.y, 1.0);
97 glBindTexture(GL_TEXTURE_2D, ray_tex);
98 glEnable(GL_TEXTURE_2D);
99 bind_program(sdr);
101 glBegin(GL_QUADS);
102 glColor3f(1, 1, 1);
103 glTexCoord2f(0, 1); glVertex2f(-1, -1);
104 glTexCoord2f(1, 1); glVertex2f(1, -1);
105 glTexCoord2f(1, 0); glVertex2f(1, 1);
106 glTexCoord2f(0, 0); glVertex2f(-1, 1);
107 glEnd();
109 bind_program(0);
110 glDisable(GL_TEXTURE_2D);
112 glMatrixMode(GL_TEXTURE);
113 glPopMatrix();
115 glutSwapBuffers();
116 assert(glGetError() == GL_NO_ERROR);
117 }
119 void reshape(int x, int y)
120 {
121 glViewport(0, 0, x, y);
122 glMatrixMode(GL_PROJECTION);
123 glLoadIdentity();
124 gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0);
126 if(ray_tex) {
127 glDeleteTextures(1, &ray_tex);
128 }
129 ray_tex = create_ray_texture(x, y, 50.0, &tex_scale);
130 }
133 void keyb(unsigned char key, int x, int y)
134 {
135 switch(key) {
136 case 27:
137 exit(0);
139 case '-':
140 if(iter > 1) {
141 iter--;
142 set_uniform_int(sdr, "iter", iter);
143 printf("iter: %d\n", iter);
144 glutPostRedisplay();
145 }
146 break;
148 case '=':
149 iter++;
150 set_uniform_int(sdr, "iter", iter);
151 printf("iter: %d\n", iter);
152 glutPostRedisplay();
153 break;
155 case ',':
156 err_thres -= 0.001;
157 set_uniform_float(sdr, "err_thres", err_thres);
158 printf("maximum error: %f\n", err_thres);
159 glutPostRedisplay();
160 break;
162 case '.':
163 err_thres += 0.001;
164 set_uniform_float(sdr, "err_thres", err_thres);
165 printf("maximum error: %f\n", err_thres);
166 glutPostRedisplay();
167 break;
169 case 's':
170 load_shader();
171 glutPostRedisplay();
172 break;
173 }
174 }
176 int bnstate[16];
178 int prev_x = -1, prev_y;
179 void mouse(int bn, int state, int x, int y)
180 {
181 bnstate[bn] = state == GLUT_DOWN ? 1 : 0;
182 if(state == GLUT_DOWN) {
183 if(bn == 3) {
184 cam_dist -= 0.1;
185 glutPostRedisplay();
186 if(cam_dist < 0) cam_dist = 0;
187 } else if(bn == 4) {
188 cam_dist += 0.1;
189 glutPostRedisplay();
190 } else {
191 prev_x = x;
192 prev_y = y;
193 }
194 } else {
195 prev_x = -1;
196 }
197 }
199 void motion(int x, int y)
200 {
201 if(bnstate[0]) {
202 cam_theta += (x - prev_x) * 0.5;
203 cam_phi += (y - prev_y) * 0.5;
205 if(cam_phi < -90) cam_phi = -90;
206 if(cam_phi > 90) cam_phi = 90;
208 glutPostRedisplay();
209 }
211 if(bnstate[1]) {
212 cam_y += (y - prev_y) * 0.1;
213 glutPostRedisplay();
214 }
216 if(bnstate[2]) {
217 cam_dist += (y - prev_y) * 0.1;
218 glutPostRedisplay();
219 }
221 prev_x = x;
222 prev_y = y;
223 }
225 unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale)
226 {
227 unsigned int tex;
228 int tex_xsz = round_pow2(xsz);
229 int tex_ysz = round_pow2(ysz);
230 float *teximg, *dir;
232 teximg = new float[3 * tex_xsz * tex_ysz];
233 dir = teximg;
235 for(int i=0; i<tex_ysz; i++) {
236 for(int j=0; j<tex_xsz; j++) {
237 if(j < xsz && i < ysz) {
238 Vector3 rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov);
239 dir[0] = rdir.x;
240 dir[1] = rdir.y;
241 dir[2] = rdir.z;
242 } else {
243 dir[0] = dir[1] = 0.0f;
244 dir[2] = 1.0f;
245 }
247 dir += 3;
248 }
249 }
251 glGenTextures(1, &tex);
252 glBindTexture(GL_TEXTURE_2D, tex);
253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
255 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
257 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, teximg);
258 delete [] teximg;
260 if(tex_scale) {
261 tex_scale->x = (float)xsz / (float)tex_xsz;
262 tex_scale->y = (float)ysz / (float)tex_ysz;
263 }
264 return tex;
265 }
267 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg)
268 {
269 float vfov = M_PI * vfov_deg / 180.0;
270 float aspect = (float)w / (float)h;
272 float ysz = 2.0;
273 float xsz = aspect * ysz;
275 float px = ((float)x / (float)w) * xsz - xsz / 2.0;
276 float py = 1.0 - ((float)y / (float)h) * ysz;
277 float pz = 1.0 / tan(0.5 * vfov);
279 float mag = sqrt(px * px + py * py + pz * pz);
281 return Vector3(px / mag, py / mag, pz / mag);
282 }
284 static int round_pow2(int x)
285 {
286 x--;
287 x = (x >> 1) | x;
288 x = (x >> 2) | x;
289 x = (x >> 4) | x;
290 x = (x >> 8) | x;
291 x = (x >> 16) | x;
292 return x + 1;
293 }