rayfract
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/rayfract.cc Thu Oct 21 23:39:26 2010 +0300 1.3 @@ -0,0 +1,293 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <assert.h> 1.7 +#include <GL/glew.h> 1.8 +#include <GL/glut.h> 1.9 +#include <vmath.h> 1.10 +#include "sdr.h" 1.11 + 1.12 +void disp(); 1.13 +void reshape(int x, int y); 1.14 +void keyb(unsigned char key, int x, int y); 1.15 +void mouse(int bn, int state, int x, int y); 1.16 +void motion(int x, int y); 1.17 + 1.18 +int load_shader(); 1.19 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale = 0); 1.20 +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); 1.21 +static int round_pow2(int x); 1.22 + 1.23 +float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; 1.24 +float cam_y = 0; 1.25 + 1.26 +unsigned int sdr; 1.27 +unsigned int ray_tex; 1.28 +Vector2 tex_scale; 1.29 +Vector4 seed; 1.30 +float err_thres = 0.0075; 1.31 +int iter = 10; 1.32 + 1.33 +int main(int argc, char **argv) 1.34 +{ 1.35 + int xsz, ysz; 1.36 + 1.37 + seed = Vector4(0.4, 0.0, 0.0, -0.8); 1.38 + 1.39 + glutInitWindowSize(640, 480); 1.40 + glutInit(&argc, argv); 1.41 + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 1.42 + glutCreateWindow("Raytraced Fractals"); 1.43 + xsz = glutGet(GLUT_WINDOW_WIDTH); 1.44 + ysz = glutGet(GLUT_WINDOW_HEIGHT); 1.45 + 1.46 + glutDisplayFunc(disp); 1.47 + glutReshapeFunc(reshape); 1.48 + glutKeyboardFunc(keyb); 1.49 + glutMouseFunc(mouse); 1.50 + glutMotionFunc(motion); 1.51 + 1.52 + glEnable(GL_DEPTH_TEST); 1.53 + glEnable(GL_LIGHTING); 1.54 + glEnable(GL_LIGHT0); 1.55 + glEnable(GL_CULL_FACE); 1.56 + 1.57 + glewInit(); 1.58 + 1.59 + if(load_shader() == -1) { 1.60 + return 1; 1.61 + } 1.62 + 1.63 + glutMainLoop(); 1.64 + return 0; 1.65 +} 1.66 + 1.67 +int load_shader() 1.68 +{ 1.69 + if(sdr) { 1.70 + free_program(sdr); 1.71 + } 1.72 + 1.73 + if(!(sdr = create_program_load("sdr/sdr.v.glsl", "sdr/julia.p.glsl"))) { 1.74 + return -1; 1.75 + } 1.76 + set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w); 1.77 + set_uniform_float(sdr, "err_thres", err_thres); 1.78 + set_uniform_int(sdr, "iter", iter); 1.79 + return 0; 1.80 +} 1.81 + 1.82 +void disp() 1.83 +{ 1.84 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.85 + 1.86 + glMatrixMode(GL_MODELVIEW); 1.87 + glLoadIdentity(); 1.88 + glRotatef(cam_theta, 0, 1, 0); 1.89 + glRotatef(cam_phi, 1, 0, 0); 1.90 + glTranslatef(0, 0, -cam_dist); 1.91 + 1.92 + float lpos[] = {-1, 1, 3, 0}; 1.93 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 1.94 + 1.95 + 1.96 + glMatrixMode(GL_TEXTURE); 1.97 + glPushMatrix(); 1.98 + glScalef(tex_scale.x, tex_scale.y, 1.0); 1.99 + 1.100 + glBindTexture(GL_TEXTURE_2D, ray_tex); 1.101 + glEnable(GL_TEXTURE_2D); 1.102 + bind_program(sdr); 1.103 + 1.104 + glBegin(GL_QUADS); 1.105 + glColor3f(1, 1, 1); 1.106 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.107 + glTexCoord2f(1, 1); glVertex2f(1, -1); 1.108 + glTexCoord2f(1, 0); glVertex2f(1, 1); 1.109 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.110 + glEnd(); 1.111 + 1.112 + bind_program(0); 1.113 + glDisable(GL_TEXTURE_2D); 1.114 + 1.115 + glMatrixMode(GL_TEXTURE); 1.116 + glPopMatrix(); 1.117 + 1.118 + glutSwapBuffers(); 1.119 + assert(glGetError() == GL_NO_ERROR); 1.120 +} 1.121 + 1.122 +void reshape(int x, int y) 1.123 +{ 1.124 + glViewport(0, 0, x, y); 1.125 + glMatrixMode(GL_PROJECTION); 1.126 + glLoadIdentity(); 1.127 + gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0); 1.128 + 1.129 + if(ray_tex) { 1.130 + glDeleteTextures(1, &ray_tex); 1.131 + } 1.132 + ray_tex = create_ray_texture(x, y, 50.0, &tex_scale); 1.133 +} 1.134 + 1.135 + 1.136 +void keyb(unsigned char key, int x, int y) 1.137 +{ 1.138 + switch(key) { 1.139 + case 27: 1.140 + exit(0); 1.141 + 1.142 + case '-': 1.143 + if(iter > 1) { 1.144 + iter--; 1.145 + set_uniform_int(sdr, "iter", iter); 1.146 + printf("iter: %d\n", iter); 1.147 + glutPostRedisplay(); 1.148 + } 1.149 + break; 1.150 + 1.151 + case '=': 1.152 + iter++; 1.153 + set_uniform_int(sdr, "iter", iter); 1.154 + printf("iter: %d\n", iter); 1.155 + glutPostRedisplay(); 1.156 + break; 1.157 + 1.158 + case ',': 1.159 + err_thres -= 0.001; 1.160 + set_uniform_float(sdr, "err_thres", err_thres); 1.161 + printf("maximum error: %f\n", err_thres); 1.162 + glutPostRedisplay(); 1.163 + break; 1.164 + 1.165 + case '.': 1.166 + err_thres += 0.001; 1.167 + set_uniform_float(sdr, "err_thres", err_thres); 1.168 + printf("maximum error: %f\n", err_thres); 1.169 + glutPostRedisplay(); 1.170 + break; 1.171 + 1.172 + case 's': 1.173 + load_shader(); 1.174 + glutPostRedisplay(); 1.175 + break; 1.176 + } 1.177 +} 1.178 + 1.179 +int bnstate[16]; 1.180 + 1.181 +int prev_x = -1, prev_y; 1.182 +void mouse(int bn, int state, int x, int y) 1.183 +{ 1.184 + bnstate[bn] = state == GLUT_DOWN ? 1 : 0; 1.185 + if(state == GLUT_DOWN) { 1.186 + if(bn == 3) { 1.187 + cam_dist -= 0.1; 1.188 + glutPostRedisplay(); 1.189 + if(cam_dist < 0) cam_dist = 0; 1.190 + } else if(bn == 4) { 1.191 + cam_dist += 0.1; 1.192 + glutPostRedisplay(); 1.193 + } else { 1.194 + prev_x = x; 1.195 + prev_y = y; 1.196 + } 1.197 + } else { 1.198 + prev_x = -1; 1.199 + } 1.200 +} 1.201 + 1.202 +void motion(int x, int y) 1.203 +{ 1.204 + if(bnstate[0]) { 1.205 + cam_theta += (x - prev_x) * 0.5; 1.206 + cam_phi += (y - prev_y) * 0.5; 1.207 + 1.208 + if(cam_phi < -90) cam_phi = -90; 1.209 + if(cam_phi > 90) cam_phi = 90; 1.210 + 1.211 + glutPostRedisplay(); 1.212 + } 1.213 + 1.214 + if(bnstate[1]) { 1.215 + cam_y += (y - prev_y) * 0.1; 1.216 + glutPostRedisplay(); 1.217 + } 1.218 + 1.219 + if(bnstate[2]) { 1.220 + cam_dist += (y - prev_y) * 0.1; 1.221 + glutPostRedisplay(); 1.222 + } 1.223 + 1.224 + prev_x = x; 1.225 + prev_y = y; 1.226 +} 1.227 + 1.228 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale) 1.229 +{ 1.230 + unsigned int tex; 1.231 + int tex_xsz = round_pow2(xsz); 1.232 + int tex_ysz = round_pow2(ysz); 1.233 + float *teximg, *dir; 1.234 + 1.235 + teximg = new float[3 * tex_xsz * tex_ysz]; 1.236 + dir = teximg; 1.237 + 1.238 + for(int i=0; i<tex_ysz; i++) { 1.239 + for(int j=0; j<tex_xsz; j++) { 1.240 + if(j < xsz && i < ysz) { 1.241 + Vector3 rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov); 1.242 + dir[0] = rdir.x; 1.243 + dir[1] = rdir.y; 1.244 + dir[2] = rdir.z; 1.245 + } else { 1.246 + dir[0] = dir[1] = 0.0f; 1.247 + dir[2] = 1.0f; 1.248 + } 1.249 + 1.250 + dir += 3; 1.251 + } 1.252 + } 1.253 + 1.254 + glGenTextures(1, &tex); 1.255 + glBindTexture(GL_TEXTURE_2D, tex); 1.256 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1.257 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1.258 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 1.259 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 1.260 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, teximg); 1.261 + delete [] teximg; 1.262 + 1.263 + if(tex_scale) { 1.264 + tex_scale->x = (float)xsz / (float)tex_xsz; 1.265 + tex_scale->y = (float)ysz / (float)tex_ysz; 1.266 + } 1.267 + return tex; 1.268 +} 1.269 + 1.270 +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) 1.271 +{ 1.272 + float vfov = M_PI * vfov_deg / 180.0; 1.273 + float aspect = (float)w / (float)h; 1.274 + 1.275 + float ysz = 2.0; 1.276 + float xsz = aspect * ysz; 1.277 + 1.278 + float px = ((float)x / (float)w) * xsz - xsz / 2.0; 1.279 + float py = 1.0 - ((float)y / (float)h) * ysz; 1.280 + float pz = 1.0 / tan(0.5 * vfov); 1.281 + 1.282 + float mag = sqrt(px * px + py * py + pz * pz); 1.283 + 1.284 + return Vector3(px / mag, py / mag, pz / mag); 1.285 +} 1.286 + 1.287 +static int round_pow2(int x) 1.288 +{ 1.289 + x--; 1.290 + x = (x >> 1) | x; 1.291 + x = (x >> 2) | x; 1.292 + x = (x >> 4) | x; 1.293 + x = (x >> 8) | x; 1.294 + x = (x >> 16) | x; 1.295 + return x + 1; 1.296 +}