rayfract
changeset 0:09bb67c000bc
ray-fract repository
author | John Tsiombikas <nuclear@siggraph.org> |
---|---|
date | Thu, 21 Oct 2010 23:39:26 +0300 |
parents | |
children | 03022062c464 |
files | Makefile sdr/julia.p.glsl sdr/sdr.v.glsl src/rayfract.cc src/sdr.c src/sdr.h |
diffstat | 6 files changed, 981 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Thu Oct 21 23:39:26 2010 +0300 1.3 @@ -0,0 +1,23 @@ 1.4 +csrc = $(wildcard src/*.c) 1.5 +ccsrc = $(wildcard src/*.cc) 1.6 +obj = $(ccsrc:.cc=.o) $(csrc:.c=.o) 1.7 +bin = rayfract 1.8 + 1.9 +ifeq ($(shell uname -s), Darwin) 1.10 + libgl = -framework OpenGL -framework GLUT -lGLEW 1.11 +else 1.12 + libgl = -lGL -lglut -lGLEW 1.13 +endif 1.14 + 1.15 +CC = gcc 1.16 +CXX = g++ 1.17 +CFLAGS = -pedantic -Wall -g `pkg-config --cflags vmath` 1.18 +CXXFLAGS = -pedantic -Wall -g `pkg-config --cflags vmath` 1.19 +LDFLAGS = $(libgl) `pkg-config --libs vmath` 1.20 + 1.21 +$(bin): $(obj) 1.22 + $(CXX) -o $@ $(obj) $(LDFLAGS) 1.23 + 1.24 +.PHONY: clean 1.25 +clean: 1.26 + rm -f $(obj) $(bin)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/sdr/julia.p.glsl Thu Oct 21 23:39:26 2010 +0300 2.3 @@ -0,0 +1,289 @@ 2.4 +/* vim: set ft=glsl:ts=4:sw=4 */ 2.5 +uniform vec4 seed; 2.6 +uniform sampler2D ray_tex; 2.7 +uniform float err_thres; 2.8 +uniform int iter; 2.9 + 2.10 +#define quat(s, x, y, z) vec4(x, y, z, s) 2.11 +#define quat_identity() vec4(0.0, 0.0, 0.0, 1.0) 2.12 + 2.13 +#define vec2quat(v) (v).wxyz 2.14 + 2.15 +struct Ray { 2.16 + vec3 origin; 2.17 + vec3 dir; 2.18 +}; 2.19 + 2.20 +struct Julia { 2.21 + bool inside; 2.22 + vec4 q; 2.23 + vec4 qprime; 2.24 +}; 2.25 + 2.26 +struct ISect { 2.27 + bool hit; 2.28 + float t; 2.29 + vec3 pos; 2.30 + vec3 normal; 2.31 + vec3 color; 2.32 + float kr; 2.33 +}; 2.34 + 2.35 +ISect find_intersection(Ray ray); 2.36 +vec3 shade(Ray ray, ISect isect); 2.37 +float amboc(ISect isect); 2.38 +vec3 sky(Ray ray); 2.39 +Julia julia(vec4 q, vec4 c); 2.40 +float julia_dist(vec4 z); 2.41 +vec3 julia_grad(vec4 z); 2.42 +vec4 quat_mul(vec4 q1, vec4 q2); 2.43 +vec4 quat_sq(vec4 q); 2.44 +float quat_length_sq(vec4 q); 2.45 +ISect ray_julia(Ray ray); 2.46 +ISect ray_sphere(Ray ray, float rad); 2.47 +ISect ray_floor(Ray ray); 2.48 +Ray get_primary_ray(); 2.49 + 2.50 + 2.51 +void main() 2.52 +{ 2.53 + Ray ray = get_primary_ray(); 2.54 + 2.55 + float energy = 1.0; 2.56 + vec3 color = vec3(0.0, 0.0, 0.0); 2.57 + 2.58 + while(energy > 0.001) { 2.59 + ISect res = find_intersection(ray); 2.60 + 2.61 + if(res.hit) { 2.62 + color += shade(ray, res) * energy; 2.63 + energy *= res.kr; 2.64 + 2.65 + ray.origin = res.pos; 2.66 + ray.dir = reflect(ray.dir, res.normal); 2.67 + } else { 2.68 + color += sky(ray) * energy; 2.69 + break; 2.70 + } 2.71 + } 2.72 + 2.73 + gl_FragColor = vec4(color, 1.0); 2.74 +} 2.75 + 2.76 + 2.77 +ISect find_intersection(Ray ray) 2.78 +{ 2.79 + ISect res; 2.80 + res.hit = false; 2.81 + 2.82 + ISect bhit = ray_sphere(ray, 2.0); 2.83 + if(bhit.hit) { 2.84 + ray.origin = bhit.pos; 2.85 + res = ray_julia(ray); 2.86 + } 2.87 + 2.88 + if(!res.hit) { 2.89 + res = ray_floor(ray); 2.90 + } 2.91 + return res; 2.92 +} 2.93 + 2.94 +vec3 shade(Ray ray, ISect isect) 2.95 +{ 2.96 + vec3 ldir = normalize(vec3(10.0, 10.0, -10.0) - isect.pos); 2.97 + vec3 vdir = -ray.dir; 2.98 + vec3 hdir = normalize(ldir + vdir); 2.99 + 2.100 + float ndotl = dot(ldir, isect.normal); 2.101 + float ndoth = dot(hdir, isect.normal); 2.102 + 2.103 + vec3 dcol = /*isect.color * max(ndotl, 0.0) */ amboc(isect); 2.104 + vec3 scol = vec3(1.0, 1.0, 1.0) * pow(max(ndoth, 0.0), 40.0); 2.105 + 2.106 + return /*vec3(0.05, 0.05, 0.05) + */dcol;// + scol; 2.107 +} 2.108 + 2.109 +#define AO_STEP 0.04 2.110 +#define AO_MAGIC 8.0 2.111 +float amboc(ISect isect) 2.112 +{ 2.113 + float sum = 0.0; 2.114 + 2.115 + for(float fi=0.0; fi<5.0; fi+=1.0) { 2.116 + float sample_dist = fi * AO_STEP; 2.117 + vec3 pt = isect.pos + isect.normal * sample_dist; 2.118 + float jdist = julia_dist(quat(pt.x, pt.y, pt.z, 0.0)); 2.119 + 2.120 + sum += 1.0 / pow(2.0, fi) * (sample_dist - jdist); 2.121 + } 2.122 + 2.123 + return 1.0 - AO_MAGIC * sum; 2.124 +} 2.125 + 2.126 +vec3 sky(Ray ray) 2.127 +{ 2.128 + vec3 col1 = vec3(0.75, 0.78, 0.8); 2.129 + vec3 col2 = vec3(0.56, 0.7, 1.0); 2.130 + 2.131 + float t = max(ray.dir.y, -0.5); 2.132 + return mix(col1, col2, t); 2.133 +} 2.134 + 2.135 +Julia julia(vec4 q, vec4 c) 2.136 +{ 2.137 + Julia res; 2.138 + res.inside = true; 2.139 + 2.140 + res.q = q; 2.141 + res.qprime = quat_identity(); 2.142 + 2.143 + for(int i=0; i<iter; i++) { 2.144 + res.qprime = 2.0 * quat_mul(res.q, res.qprime); 2.145 + res.q = quat_sq(res.q) + c; 2.146 + 2.147 + if(dot(res.q, res.q) > 8.0) { 2.148 + res.inside = false; 2.149 + break; 2.150 + } 2.151 + } 2.152 + return res; 2.153 +} 2.154 + 2.155 +float julia_dist(vec4 z) 2.156 +{ 2.157 + Julia jres = julia(z, seed); 2.158 + 2.159 + float lenq = length(jres.q); 2.160 + float lenqprime = length(jres.qprime); 2.161 + 2.162 + return 0.5 * lenq * log(lenq) / lenqprime; 2.163 +} 2.164 + 2.165 +#define OFFS 1e-4 2.166 +vec3 julia_grad(vec4 z) 2.167 +{ 2.168 + vec3 grad; 2.169 + grad.x = julia_dist(z + quat(OFFS, 0.0, 0.0, 0.0)) - julia_dist(z - quat(OFFS, 0.0, 0.0, 0.0)); 2.170 + grad.y = julia_dist(z + quat(0.0, OFFS, 0.0, 0.0)) - julia_dist(z - quat(0.0, OFFS, 0.0, 0.0)); 2.171 + grad.z = julia_dist(z + quat(0.0, 0.0, OFFS, 0.0)) - julia_dist(z - quat(0.0, 0.0, OFFS, 0.0)); 2.172 + return grad; 2.173 +} 2.174 + 2.175 +vec4 quat_mul(vec4 q1, vec4 q2) 2.176 +{ 2.177 + vec4 res; 2.178 + res.w = q1.w * q2.w - dot(q1.xyz, q2.xyz); 2.179 + res.xyz = q1.w * q2.xyz + q2.w * q1.xyz + cross(q1.xyz, q2.xyz); 2.180 + return res; 2.181 +} 2.182 + 2.183 +vec4 quat_sq(vec4 q) 2.184 +{ 2.185 + vec4 res; 2.186 + res.w = q.w * q.w - dot(q.xyz, q.xyz); 2.187 + res.xyz = 2.0 * q.w * q.xyz; 2.188 + return res; 2.189 +} 2.190 + 2.191 +ISect ray_julia(Ray inray) 2.192 +{ 2.193 + float dist_acc = 0.0; 2.194 + Ray ray = inray; 2.195 + ISect res; 2.196 + 2.197 + for(float fi=0.0; ; fi+=0.1) { 2.198 + vec4 q = quat(ray.origin.x, ray.origin.y, ray.origin.z, 0.0); 2.199 + 2.200 + float dist = julia_dist(q); 2.201 + 2.202 + ray.origin += ray.dir * dist; 2.203 + dist_acc += dist; 2.204 + 2.205 + if(dist < err_thres) { 2.206 + res.hit = true; 2.207 + res.t = dist_acc; 2.208 + res.pos = ray.origin; 2.209 + res.normal = normalize(julia_grad(quat(res.pos.x, res.pos.y, res.pos.z, 0.0))); 2.210 + res.color = vec3(0.75, 0.8, 0.9);//abs(res.normal) * 0.2; 2.211 + //res.kr = 0.6; 2.212 + res.kr = 0.0; 2.213 + break; 2.214 + } 2.215 + 2.216 + if(dot(ray.origin, ray.origin) > 100.0) { 2.217 + res.hit = false; 2.218 + break; 2.219 + } 2.220 + } 2.221 + 2.222 + return res; 2.223 +} 2.224 + 2.225 +ISect ray_sphere(Ray ray, float rad) 2.226 +{ 2.227 + ISect res; 2.228 + res.hit = false; 2.229 + 2.230 + float a = dot(ray.dir, ray.dir); 2.231 + float b = 2.0 * dot(ray.dir, ray.origin); 2.232 + float c = dot(ray.origin, ray.origin) - rad * rad; 2.233 + 2.234 + float d = b * b - 4.0 * a * c; 2.235 + if(d < 0.0) return res; 2.236 + 2.237 + float sqrt_d = sqrt(d); 2.238 + float t1 = (-b + sqrt_d) / (2.0 * a); 2.239 + float t2 = (-b - sqrt_d) / (2.0 * a); 2.240 + 2.241 + if((t1 >= 0.0 || t2 >= 0.0)) { 2.242 + if(t1 < 0.0) t1 = t2; 2.243 + if(t2 < 0.0) t2 = t1; 2.244 + 2.245 + res.hit = true; 2.246 + res.t = min(t1, t2); 2.247 + res.pos = ray.origin + ray.dir * res.t; 2.248 + res.color = vec3(1.0, 0.3, 0.2); 2.249 + res.normal = res.pos / rad; 2.250 + } 2.251 + 2.252 + return res; 2.253 +} 2.254 + 2.255 +#define FLOOR_HEIGHT (-2.0) 2.256 + 2.257 +ISect ray_floor(Ray ray) 2.258 +{ 2.259 + ISect res; 2.260 + res.hit = false; 2.261 + 2.262 + if(ray.origin.y < FLOOR_HEIGHT || ray.dir.y >= 0.0) { 2.263 + return res; 2.264 + } 2.265 + 2.266 + res.normal = vec3(0.0, 1.0, 0.0); 2.267 + float ndotdir = dot(res.normal, ray.dir); 2.268 + 2.269 + float t = (FLOOR_HEIGHT - ray.origin.y) / ndotdir; 2.270 + res.pos = ray.origin + ray.dir * t; 2.271 + 2.272 + if(abs(res.pos.x) > 8.0 || abs(res.pos.z) > 8.0) { 2.273 + res.hit = false; 2.274 + } else { 2.275 + res.hit = true; 2.276 + 2.277 + float chess = mod(floor(res.pos.x) + floor(res.pos.z), 2.0); 2.278 + res.color = mix(vec3(0.498, 0.165, 0.149), vec3(0.776, 0.851, 0.847), chess); 2.279 + res.kr = 0.0; 2.280 + } 2.281 + return res; 2.282 +} 2.283 + 2.284 +Ray get_primary_ray() 2.285 +{ 2.286 + Ray ray; 2.287 + vec2 tc = gl_TexCoord[0].xy; 2.288 + ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz); 2.289 + ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; 2.290 + return ray; 2.291 +} 2.292 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr/sdr.v.glsl Thu Oct 21 23:39:26 2010 +0300 3.3 @@ -0,0 +1,5 @@ 3.4 +void main() 3.5 +{ 3.6 + gl_Position = gl_Vertex; 3.7 + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; 3.8 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/rayfract.cc Thu Oct 21 23:39:26 2010 +0300 4.3 @@ -0,0 +1,293 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <assert.h> 4.7 +#include <GL/glew.h> 4.8 +#include <GL/glut.h> 4.9 +#include <vmath.h> 4.10 +#include "sdr.h" 4.11 + 4.12 +void disp(); 4.13 +void reshape(int x, int y); 4.14 +void keyb(unsigned char key, int x, int y); 4.15 +void mouse(int bn, int state, int x, int y); 4.16 +void motion(int x, int y); 4.17 + 4.18 +int load_shader(); 4.19 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale = 0); 4.20 +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); 4.21 +static int round_pow2(int x); 4.22 + 4.23 +float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; 4.24 +float cam_y = 0; 4.25 + 4.26 +unsigned int sdr; 4.27 +unsigned int ray_tex; 4.28 +Vector2 tex_scale; 4.29 +Vector4 seed; 4.30 +float err_thres = 0.0075; 4.31 +int iter = 10; 4.32 + 4.33 +int main(int argc, char **argv) 4.34 +{ 4.35 + int xsz, ysz; 4.36 + 4.37 + seed = Vector4(0.4, 0.0, 0.0, -0.8); 4.38 + 4.39 + glutInitWindowSize(640, 480); 4.40 + glutInit(&argc, argv); 4.41 + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 4.42 + glutCreateWindow("Raytraced Fractals"); 4.43 + xsz = glutGet(GLUT_WINDOW_WIDTH); 4.44 + ysz = glutGet(GLUT_WINDOW_HEIGHT); 4.45 + 4.46 + glutDisplayFunc(disp); 4.47 + glutReshapeFunc(reshape); 4.48 + glutKeyboardFunc(keyb); 4.49 + glutMouseFunc(mouse); 4.50 + glutMotionFunc(motion); 4.51 + 4.52 + glEnable(GL_DEPTH_TEST); 4.53 + glEnable(GL_LIGHTING); 4.54 + glEnable(GL_LIGHT0); 4.55 + glEnable(GL_CULL_FACE); 4.56 + 4.57 + glewInit(); 4.58 + 4.59 + if(load_shader() == -1) { 4.60 + return 1; 4.61 + } 4.62 + 4.63 + glutMainLoop(); 4.64 + return 0; 4.65 +} 4.66 + 4.67 +int load_shader() 4.68 +{ 4.69 + if(sdr) { 4.70 + free_program(sdr); 4.71 + } 4.72 + 4.73 + if(!(sdr = create_program_load("sdr/sdr.v.glsl", "sdr/julia.p.glsl"))) { 4.74 + return -1; 4.75 + } 4.76 + set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w); 4.77 + set_uniform_float(sdr, "err_thres", err_thres); 4.78 + set_uniform_int(sdr, "iter", iter); 4.79 + return 0; 4.80 +} 4.81 + 4.82 +void disp() 4.83 +{ 4.84 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4.85 + 4.86 + glMatrixMode(GL_MODELVIEW); 4.87 + glLoadIdentity(); 4.88 + glRotatef(cam_theta, 0, 1, 0); 4.89 + glRotatef(cam_phi, 1, 0, 0); 4.90 + glTranslatef(0, 0, -cam_dist); 4.91 + 4.92 + float lpos[] = {-1, 1, 3, 0}; 4.93 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 4.94 + 4.95 + 4.96 + glMatrixMode(GL_TEXTURE); 4.97 + glPushMatrix(); 4.98 + glScalef(tex_scale.x, tex_scale.y, 1.0); 4.99 + 4.100 + glBindTexture(GL_TEXTURE_2D, ray_tex); 4.101 + glEnable(GL_TEXTURE_2D); 4.102 + bind_program(sdr); 4.103 + 4.104 + glBegin(GL_QUADS); 4.105 + glColor3f(1, 1, 1); 4.106 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 4.107 + glTexCoord2f(1, 1); glVertex2f(1, -1); 4.108 + glTexCoord2f(1, 0); glVertex2f(1, 1); 4.109 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 4.110 + glEnd(); 4.111 + 4.112 + bind_program(0); 4.113 + glDisable(GL_TEXTURE_2D); 4.114 + 4.115 + glMatrixMode(GL_TEXTURE); 4.116 + glPopMatrix(); 4.117 + 4.118 + glutSwapBuffers(); 4.119 + assert(glGetError() == GL_NO_ERROR); 4.120 +} 4.121 + 4.122 +void reshape(int x, int y) 4.123 +{ 4.124 + glViewport(0, 0, x, y); 4.125 + glMatrixMode(GL_PROJECTION); 4.126 + glLoadIdentity(); 4.127 + gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0); 4.128 + 4.129 + if(ray_tex) { 4.130 + glDeleteTextures(1, &ray_tex); 4.131 + } 4.132 + ray_tex = create_ray_texture(x, y, 50.0, &tex_scale); 4.133 +} 4.134 + 4.135 + 4.136 +void keyb(unsigned char key, int x, int y) 4.137 +{ 4.138 + switch(key) { 4.139 + case 27: 4.140 + exit(0); 4.141 + 4.142 + case '-': 4.143 + if(iter > 1) { 4.144 + iter--; 4.145 + set_uniform_int(sdr, "iter", iter); 4.146 + printf("iter: %d\n", iter); 4.147 + glutPostRedisplay(); 4.148 + } 4.149 + break; 4.150 + 4.151 + case '=': 4.152 + iter++; 4.153 + set_uniform_int(sdr, "iter", iter); 4.154 + printf("iter: %d\n", iter); 4.155 + glutPostRedisplay(); 4.156 + break; 4.157 + 4.158 + case ',': 4.159 + err_thres -= 0.001; 4.160 + set_uniform_float(sdr, "err_thres", err_thres); 4.161 + printf("maximum error: %f\n", err_thres); 4.162 + glutPostRedisplay(); 4.163 + break; 4.164 + 4.165 + case '.': 4.166 + err_thres += 0.001; 4.167 + set_uniform_float(sdr, "err_thres", err_thres); 4.168 + printf("maximum error: %f\n", err_thres); 4.169 + glutPostRedisplay(); 4.170 + break; 4.171 + 4.172 + case 's': 4.173 + load_shader(); 4.174 + glutPostRedisplay(); 4.175 + break; 4.176 + } 4.177 +} 4.178 + 4.179 +int bnstate[16]; 4.180 + 4.181 +int prev_x = -1, prev_y; 4.182 +void mouse(int bn, int state, int x, int y) 4.183 +{ 4.184 + bnstate[bn] = state == GLUT_DOWN ? 1 : 0; 4.185 + if(state == GLUT_DOWN) { 4.186 + if(bn == 3) { 4.187 + cam_dist -= 0.1; 4.188 + glutPostRedisplay(); 4.189 + if(cam_dist < 0) cam_dist = 0; 4.190 + } else if(bn == 4) { 4.191 + cam_dist += 0.1; 4.192 + glutPostRedisplay(); 4.193 + } else { 4.194 + prev_x = x; 4.195 + prev_y = y; 4.196 + } 4.197 + } else { 4.198 + prev_x = -1; 4.199 + } 4.200 +} 4.201 + 4.202 +void motion(int x, int y) 4.203 +{ 4.204 + if(bnstate[0]) { 4.205 + cam_theta += (x - prev_x) * 0.5; 4.206 + cam_phi += (y - prev_y) * 0.5; 4.207 + 4.208 + if(cam_phi < -90) cam_phi = -90; 4.209 + if(cam_phi > 90) cam_phi = 90; 4.210 + 4.211 + glutPostRedisplay(); 4.212 + } 4.213 + 4.214 + if(bnstate[1]) { 4.215 + cam_y += (y - prev_y) * 0.1; 4.216 + glutPostRedisplay(); 4.217 + } 4.218 + 4.219 + if(bnstate[2]) { 4.220 + cam_dist += (y - prev_y) * 0.1; 4.221 + glutPostRedisplay(); 4.222 + } 4.223 + 4.224 + prev_x = x; 4.225 + prev_y = y; 4.226 +} 4.227 + 4.228 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale) 4.229 +{ 4.230 + unsigned int tex; 4.231 + int tex_xsz = round_pow2(xsz); 4.232 + int tex_ysz = round_pow2(ysz); 4.233 + float *teximg, *dir; 4.234 + 4.235 + teximg = new float[3 * tex_xsz * tex_ysz]; 4.236 + dir = teximg; 4.237 + 4.238 + for(int i=0; i<tex_ysz; i++) { 4.239 + for(int j=0; j<tex_xsz; j++) { 4.240 + if(j < xsz && i < ysz) { 4.241 + Vector3 rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov); 4.242 + dir[0] = rdir.x; 4.243 + dir[1] = rdir.y; 4.244 + dir[2] = rdir.z; 4.245 + } else { 4.246 + dir[0] = dir[1] = 0.0f; 4.247 + dir[2] = 1.0f; 4.248 + } 4.249 + 4.250 + dir += 3; 4.251 + } 4.252 + } 4.253 + 4.254 + glGenTextures(1, &tex); 4.255 + glBindTexture(GL_TEXTURE_2D, tex); 4.256 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4.257 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4.258 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 4.259 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 4.260 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, teximg); 4.261 + delete [] teximg; 4.262 + 4.263 + if(tex_scale) { 4.264 + tex_scale->x = (float)xsz / (float)tex_xsz; 4.265 + tex_scale->y = (float)ysz / (float)tex_ysz; 4.266 + } 4.267 + return tex; 4.268 +} 4.269 + 4.270 +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) 4.271 +{ 4.272 + float vfov = M_PI * vfov_deg / 180.0; 4.273 + float aspect = (float)w / (float)h; 4.274 + 4.275 + float ysz = 2.0; 4.276 + float xsz = aspect * ysz; 4.277 + 4.278 + float px = ((float)x / (float)w) * xsz - xsz / 2.0; 4.279 + float py = 1.0 - ((float)y / (float)h) * ysz; 4.280 + float pz = 1.0 / tan(0.5 * vfov); 4.281 + 4.282 + float mag = sqrt(px * px + py * py + pz * pz); 4.283 + 4.284 + return Vector3(px / mag, py / mag, pz / mag); 4.285 +} 4.286 + 4.287 +static int round_pow2(int x) 4.288 +{ 4.289 + x--; 4.290 + x = (x >> 1) | x; 4.291 + x = (x >> 2) | x; 4.292 + x = (x >> 4) | x; 4.293 + x = (x >> 8) | x; 4.294 + x = (x >> 16) | x; 4.295 + return x + 1; 4.296 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/sdr.c Thu Oct 21 23:39:26 2010 +0300 5.3 @@ -0,0 +1,324 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <string.h> 5.7 +#include <errno.h> 5.8 +#include <assert.h> 5.9 +#include <GL/glew.h> 5.10 + 5.11 +#if defined(unix) || defined(__unix__) 5.12 +#include <unistd.h> 5.13 +#include <sys/stat.h> 5.14 +#endif /* unix */ 5.15 + 5.16 +#include "sdr.h" 5.17 + 5.18 +unsigned int create_vertex_shader(const char *src) 5.19 +{ 5.20 + return create_shader(src, GL_VERTEX_SHADER); 5.21 +} 5.22 + 5.23 +unsigned int create_pixel_shader(const char *src) 5.24 +{ 5.25 + return create_shader(src, GL_FRAGMENT_SHADER); 5.26 +} 5.27 + 5.28 +unsigned int create_shader(const char *src, unsigned int sdr_type) 5.29 +{ 5.30 + unsigned int sdr; 5.31 + int success, info_len; 5.32 + char *info_str = 0; 5.33 + GLenum err; 5.34 + 5.35 + sdr = glCreateShader(sdr_type); 5.36 + assert(glGetError() == GL_NO_ERROR); 5.37 + glShaderSource(sdr, 1, &src, 0); 5.38 + err = glGetError(); 5.39 + assert(err == GL_NO_ERROR); 5.40 + glCompileShader(sdr); 5.41 + assert(glGetError() == GL_NO_ERROR); 5.42 + 5.43 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 5.44 + assert(glGetError() == GL_NO_ERROR); 5.45 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 5.46 + assert(glGetError() == GL_NO_ERROR); 5.47 + 5.48 + if(info_len) { 5.49 + if((info_str = malloc(info_len + 1))) { 5.50 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 5.51 + assert(glGetError() == GL_NO_ERROR); 5.52 + } 5.53 + } 5.54 + 5.55 + if(success) { 5.56 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 5.57 + } else { 5.58 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 5.59 + glDeleteShader(sdr); 5.60 + sdr = 0; 5.61 + } 5.62 + 5.63 + free(info_str); 5.64 + return sdr; 5.65 +} 5.66 + 5.67 +void free_shader(unsigned int sdr) 5.68 +{ 5.69 + glDeleteShader(sdr); 5.70 +} 5.71 + 5.72 +unsigned int load_vertex_shader(const char *fname) 5.73 +{ 5.74 + return load_shader(fname, GL_VERTEX_SHADER); 5.75 +} 5.76 + 5.77 +unsigned int load_pixel_shader(const char *fname) 5.78 +{ 5.79 + return load_shader(fname, GL_FRAGMENT_SHADER); 5.80 +} 5.81 + 5.82 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 5.83 +{ 5.84 +#if defined(unix) || defined(__unix__) 5.85 + struct stat st; 5.86 +#endif 5.87 + unsigned int sdr; 5.88 + size_t filesize; 5.89 + FILE *fp; 5.90 + char *src; 5.91 + 5.92 + if(!(fp = fopen(fname, "r"))) { 5.93 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 5.94 + return 0; 5.95 + } 5.96 + 5.97 +#if defined(unix) || defined(__unix__) 5.98 + fstat(fileno(fp), &st); 5.99 + filesize = st.st_size; 5.100 +#else 5.101 + fseek(fp, 0, SEEK_END); 5.102 + filesize = ftell(fp); 5.103 + fseek(fp, 0, SEEK_SET); 5.104 +#endif /* unix */ 5.105 + 5.106 + if(!(src = malloc(filesize + 1))) { 5.107 + fclose(fp); 5.108 + return 0; 5.109 + } 5.110 + fread(src, 1, filesize, fp); 5.111 + src[filesize] = 0; 5.112 + fclose(fp); 5.113 + 5.114 + fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname); 5.115 + sdr = create_shader(src, sdr_type); 5.116 + 5.117 + free(src); 5.118 + return sdr; 5.119 +} 5.120 + 5.121 + 5.122 +unsigned int get_vertex_shader(const char *fname) 5.123 +{ 5.124 + return get_shader(fname, GL_VERTEX_SHADER); 5.125 +} 5.126 + 5.127 +unsigned int get_pixel_shader(const char *fname) 5.128 +{ 5.129 + return get_shader(fname, GL_FRAGMENT_SHADER); 5.130 +} 5.131 + 5.132 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 5.133 +{ 5.134 + unsigned int sdr; 5.135 +#if 0 5.136 + if((res = get_resource(sdrman, fname))) { 5.137 + /* TODO: validate that the shader matches sdr_type? */ 5.138 + return (uintptr_t)res; 5.139 + } 5.140 +#endif 5.141 + 5.142 + if(!(sdr = load_shader(fname, sdr_type))) { 5.143 + return 0; 5.144 + } 5.145 + add_shader(fname, sdr); 5.146 + return sdr; 5.147 +} 5.148 + 5.149 +int add_shader(const char *fname, unsigned int sdr) 5.150 +{ 5.151 + return 0;/*add_resource(sdrman, fname, (void*)(uintptr_t)sdr);*/ 5.152 +} 5.153 + 5.154 +int remove_shader(const char *fname) 5.155 +{ 5.156 + return 0;/*remove_resource(sdrman, fname);*/ 5.157 +} 5.158 + 5.159 + 5.160 +/* ---- gpu programs ---- */ 5.161 + 5.162 +unsigned int create_program(void) 5.163 +{ 5.164 + unsigned int prog = glCreateProgram(); 5.165 + assert(glGetError() == GL_NO_ERROR); 5.166 + return prog; 5.167 +} 5.168 + 5.169 +unsigned int create_program_link(unsigned int vs, unsigned int ps) 5.170 +{ 5.171 + unsigned int prog; 5.172 + 5.173 + if(!(prog = create_program())) { 5.174 + return 0; 5.175 + } 5.176 + 5.177 + attach_shader(prog, vs); 5.178 + assert(glGetError() == GL_NO_ERROR); 5.179 + attach_shader(prog, ps); 5.180 + assert(glGetError() == GL_NO_ERROR); 5.181 + 5.182 + if(link_program(prog) == -1) { 5.183 + free_program(prog); 5.184 + return 0; 5.185 + } 5.186 + return prog; 5.187 +} 5.188 + 5.189 +unsigned int create_program_load(const char *vfile, const char *pfile) 5.190 +{ 5.191 + unsigned int vs, ps; 5.192 + 5.193 + if(!(vs = get_vertex_shader(vfile)) || !(ps = get_pixel_shader(pfile))) { 5.194 + return 0; 5.195 + } 5.196 + return create_program_link(vs, ps); 5.197 +} 5.198 + 5.199 +void free_program(unsigned int sdr) 5.200 +{ 5.201 + glDeleteProgram(sdr); 5.202 +} 5.203 + 5.204 +void attach_shader(unsigned int prog, unsigned int sdr) 5.205 +{ 5.206 + glAttachShader(prog, sdr); 5.207 + assert(glGetError() == GL_NO_ERROR); 5.208 +} 5.209 + 5.210 +int link_program(unsigned int prog) 5.211 +{ 5.212 + int linked, info_len, retval = 0; 5.213 + char *info_str = 0; 5.214 + 5.215 + glLinkProgram(prog); 5.216 + assert(glGetError() == GL_NO_ERROR); 5.217 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 5.218 + assert(glGetError() == GL_NO_ERROR); 5.219 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 5.220 + assert(glGetError() == GL_NO_ERROR); 5.221 + 5.222 + if(info_len) { 5.223 + if((info_str = malloc(info_len + 1))) { 5.224 + glGetProgramInfoLog(prog, info_len, 0, info_str); 5.225 + assert(glGetError() == GL_NO_ERROR); 5.226 + } 5.227 + } 5.228 + 5.229 + if(linked) { 5.230 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 5.231 + } else { 5.232 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 5.233 + retval = -1; 5.234 + } 5.235 + 5.236 + free(info_str); 5.237 + return retval; 5.238 +} 5.239 + 5.240 +int bind_program(unsigned int prog) 5.241 +{ 5.242 + GLenum err; 5.243 + 5.244 + glUseProgram(prog); 5.245 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 5.246 + /* maybe the program is not linked, try to link first */ 5.247 + if(err == GL_INVALID_OPERATION) { 5.248 + if(link_program(prog) == -1) { 5.249 + return -1; 5.250 + } 5.251 + glUseProgram(prog); 5.252 + return glGetError() == GL_NO_ERROR ? 0 : -1; 5.253 + } 5.254 + return -1; 5.255 + } 5.256 + return 0; 5.257 +} 5.258 + 5.259 +/* ugly but I'm not going to write the same bloody code over and over */ 5.260 +#define BEGIN_UNIFORM_CODE \ 5.261 + int loc, curr_prog; \ 5.262 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 5.263 + if(curr_prog != prog && bind_program(prog) == -1) { \ 5.264 + return -1; \ 5.265 + } \ 5.266 + if((loc = glGetUniformLocation(prog, name)) != -1) 5.267 + 5.268 +#define END_UNIFORM_CODE \ 5.269 + if(curr_prog != prog) { \ 5.270 + bind_program(curr_prog); \ 5.271 + } \ 5.272 + return loc == -1 ? -1 : 0 5.273 + 5.274 +int set_uniform_int(unsigned int prog, const char *name, int val) 5.275 +{ 5.276 + BEGIN_UNIFORM_CODE { 5.277 + glUniform1i(loc, val); 5.278 + } 5.279 + END_UNIFORM_CODE; 5.280 +} 5.281 + 5.282 +int set_uniform_float(unsigned int prog, const char *name, float val) 5.283 +{ 5.284 + BEGIN_UNIFORM_CODE { 5.285 + glUniform1f(loc, val); 5.286 + } 5.287 + END_UNIFORM_CODE; 5.288 +} 5.289 + 5.290 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 5.291 +{ 5.292 + BEGIN_UNIFORM_CODE { 5.293 + glUniform3f(loc, x, y, z); 5.294 + } 5.295 + END_UNIFORM_CODE; 5.296 +} 5.297 + 5.298 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 5.299 +{ 5.300 + BEGIN_UNIFORM_CODE { 5.301 + glUniform4f(loc, x, y, z, w); 5.302 + } 5.303 + END_UNIFORM_CODE; 5.304 +} 5.305 + 5.306 + 5.307 +int get_attrib_loc(unsigned int prog, const char *name) 5.308 +{ 5.309 + int loc, curr_prog; 5.310 + 5.311 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 5.312 + if(curr_prog != prog && bind_program(prog) == -1) { 5.313 + return -1; 5.314 + } 5.315 + 5.316 + loc = glGetAttribLocation(prog, (char*)name); 5.317 + 5.318 + if(curr_prog != prog) { 5.319 + bind_program(curr_prog); 5.320 + } 5.321 + return loc; 5.322 +} 5.323 + 5.324 +void set_attrib_float3(int attr_loc, float x, float y, float z) 5.325 +{ 5.326 + glVertexAttrib3f(attr_loc, x, y, z); 5.327 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/sdr.h Thu Oct 21 23:39:26 2010 +0300 6.3 @@ -0,0 +1,47 @@ 6.4 +#ifndef _SDR_H_ 6.5 +#define _SDR_H_ 6.6 + 6.7 +#ifdef __cplusplus 6.8 +extern "C" { 6.9 +#endif /* __cplusplus */ 6.10 + 6.11 +/* ---- shaders ---- */ 6.12 +unsigned int create_vertex_shader(const char *src); 6.13 +unsigned int create_pixel_shader(const char *src); 6.14 +unsigned int create_shader(const char *src, unsigned int sdr_type); 6.15 +void free_shader(unsigned int sdr); 6.16 + 6.17 +unsigned int load_vertex_shader(const char *fname); 6.18 +unsigned int load_pixel_shader(const char *fname); 6.19 +unsigned int load_shader(const char *src, unsigned int sdr_type); 6.20 + 6.21 +unsigned int get_vertex_shader(const char *fname); 6.22 +unsigned int get_pixel_shader(const char *fname); 6.23 +unsigned int get_shader(const char *fname, unsigned int sdr_type); 6.24 + 6.25 +int add_shader(const char *fname, unsigned int sdr); 6.26 +int remove_shader(const char *fname); 6.27 + 6.28 +/* ---- gpu programs ---- */ 6.29 +unsigned int create_program(void); 6.30 +unsigned int create_program_link(unsigned int vs, unsigned int ps); 6.31 +unsigned int create_program_load(const char *vfile, const char *pfile); 6.32 +void free_program(unsigned int sdr); 6.33 + 6.34 +void attach_shader(unsigned int prog, unsigned int sdr); 6.35 +int link_program(unsigned int prog); 6.36 +int bind_program(unsigned int prog); 6.37 + 6.38 +int set_uniform_int(unsigned int prog, const char *name, int val); 6.39 +int set_uniform_float(unsigned int prog, const char *name, float val); 6.40 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 6.41 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 6.42 + 6.43 +int get_attrib_loc(unsigned int prog, const char *name); 6.44 +void set_attrib_float3(int attr_loc, float x, float y, float z); 6.45 + 6.46 +#ifdef __cplusplus 6.47 +} 6.48 +#endif /* __cplusplus */ 6.49 + 6.50 +#endif /* _SDR_H_ */