# HG changeset patch # User John Tsiombikas # Date 1287693566 -10800 # Node ID 09bb67c000bc0de547e1846699177a72b14d5e5a ray-fract repository diff -r 000000000000 -r 09bb67c000bc Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,23 @@ +csrc = $(wildcard src/*.c) +ccsrc = $(wildcard src/*.cc) +obj = $(ccsrc:.cc=.o) $(csrc:.c=.o) +bin = rayfract + +ifeq ($(shell uname -s), Darwin) + libgl = -framework OpenGL -framework GLUT -lGLEW +else + libgl = -lGL -lglut -lGLEW +endif + +CC = gcc +CXX = g++ +CFLAGS = -pedantic -Wall -g `pkg-config --cflags vmath` +CXXFLAGS = -pedantic -Wall -g `pkg-config --cflags vmath` +LDFLAGS = $(libgl) `pkg-config --libs vmath` + +$(bin): $(obj) + $(CXX) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff -r 000000000000 -r 09bb67c000bc sdr/julia.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/julia.p.glsl Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,289 @@ +/* vim: set ft=glsl:ts=4:sw=4 */ +uniform vec4 seed; +uniform sampler2D ray_tex; +uniform float err_thres; +uniform int iter; + +#define quat(s, x, y, z) vec4(x, y, z, s) +#define quat_identity() vec4(0.0, 0.0, 0.0, 1.0) + +#define vec2quat(v) (v).wxyz + +struct Ray { + vec3 origin; + vec3 dir; +}; + +struct Julia { + bool inside; + vec4 q; + vec4 qprime; +}; + +struct ISect { + bool hit; + float t; + vec3 pos; + vec3 normal; + vec3 color; + float kr; +}; + +ISect find_intersection(Ray ray); +vec3 shade(Ray ray, ISect isect); +float amboc(ISect isect); +vec3 sky(Ray ray); +Julia julia(vec4 q, vec4 c); +float julia_dist(vec4 z); +vec3 julia_grad(vec4 z); +vec4 quat_mul(vec4 q1, vec4 q2); +vec4 quat_sq(vec4 q); +float quat_length_sq(vec4 q); +ISect ray_julia(Ray ray); +ISect ray_sphere(Ray ray, float rad); +ISect ray_floor(Ray ray); +Ray get_primary_ray(); + + +void main() +{ + Ray ray = get_primary_ray(); + + float energy = 1.0; + vec3 color = vec3(0.0, 0.0, 0.0); + + while(energy > 0.001) { + ISect res = find_intersection(ray); + + if(res.hit) { + color += shade(ray, res) * energy; + energy *= res.kr; + + ray.origin = res.pos; + ray.dir = reflect(ray.dir, res.normal); + } else { + color += sky(ray) * energy; + break; + } + } + + gl_FragColor = vec4(color, 1.0); +} + + +ISect find_intersection(Ray ray) +{ + ISect res; + res.hit = false; + + ISect bhit = ray_sphere(ray, 2.0); + if(bhit.hit) { + ray.origin = bhit.pos; + res = ray_julia(ray); + } + + if(!res.hit) { + res = ray_floor(ray); + } + return res; +} + +vec3 shade(Ray ray, ISect isect) +{ + vec3 ldir = normalize(vec3(10.0, 10.0, -10.0) - isect.pos); + vec3 vdir = -ray.dir; + vec3 hdir = normalize(ldir + vdir); + + float ndotl = dot(ldir, isect.normal); + float ndoth = dot(hdir, isect.normal); + + vec3 dcol = /*isect.color * max(ndotl, 0.0) */ amboc(isect); + vec3 scol = vec3(1.0, 1.0, 1.0) * pow(max(ndoth, 0.0), 40.0); + + return /*vec3(0.05, 0.05, 0.05) + */dcol;// + scol; +} + +#define AO_STEP 0.04 +#define AO_MAGIC 8.0 +float amboc(ISect isect) +{ + float sum = 0.0; + + for(float fi=0.0; fi<5.0; fi+=1.0) { + float sample_dist = fi * AO_STEP; + vec3 pt = isect.pos + isect.normal * sample_dist; + float jdist = julia_dist(quat(pt.x, pt.y, pt.z, 0.0)); + + sum += 1.0 / pow(2.0, fi) * (sample_dist - jdist); + } + + return 1.0 - AO_MAGIC * sum; +} + +vec3 sky(Ray ray) +{ + vec3 col1 = vec3(0.75, 0.78, 0.8); + vec3 col2 = vec3(0.56, 0.7, 1.0); + + float t = max(ray.dir.y, -0.5); + return mix(col1, col2, t); +} + +Julia julia(vec4 q, vec4 c) +{ + Julia res; + res.inside = true; + + res.q = q; + res.qprime = quat_identity(); + + for(int i=0; i 8.0) { + res.inside = false; + break; + } + } + return res; +} + +float julia_dist(vec4 z) +{ + Julia jres = julia(z, seed); + + float lenq = length(jres.q); + float lenqprime = length(jres.qprime); + + return 0.5 * lenq * log(lenq) / lenqprime; +} + +#define OFFS 1e-4 +vec3 julia_grad(vec4 z) +{ + vec3 grad; + grad.x = julia_dist(z + quat(OFFS, 0.0, 0.0, 0.0)) - julia_dist(z - quat(OFFS, 0.0, 0.0, 0.0)); + grad.y = julia_dist(z + quat(0.0, OFFS, 0.0, 0.0)) - julia_dist(z - quat(0.0, OFFS, 0.0, 0.0)); + grad.z = julia_dist(z + quat(0.0, 0.0, OFFS, 0.0)) - julia_dist(z - quat(0.0, 0.0, OFFS, 0.0)); + return grad; +} + +vec4 quat_mul(vec4 q1, vec4 q2) +{ + vec4 res; + res.w = q1.w * q2.w - dot(q1.xyz, q2.xyz); + res.xyz = q1.w * q2.xyz + q2.w * q1.xyz + cross(q1.xyz, q2.xyz); + return res; +} + +vec4 quat_sq(vec4 q) +{ + vec4 res; + res.w = q.w * q.w - dot(q.xyz, q.xyz); + res.xyz = 2.0 * q.w * q.xyz; + return res; +} + +ISect ray_julia(Ray inray) +{ + float dist_acc = 0.0; + Ray ray = inray; + ISect res; + + for(float fi=0.0; ; fi+=0.1) { + vec4 q = quat(ray.origin.x, ray.origin.y, ray.origin.z, 0.0); + + float dist = julia_dist(q); + + ray.origin += ray.dir * dist; + dist_acc += dist; + + if(dist < err_thres) { + res.hit = true; + res.t = dist_acc; + res.pos = ray.origin; + res.normal = normalize(julia_grad(quat(res.pos.x, res.pos.y, res.pos.z, 0.0))); + res.color = vec3(0.75, 0.8, 0.9);//abs(res.normal) * 0.2; + //res.kr = 0.6; + res.kr = 0.0; + break; + } + + if(dot(ray.origin, ray.origin) > 100.0) { + res.hit = false; + break; + } + } + + return res; +} + +ISect ray_sphere(Ray ray, float rad) +{ + ISect res; + res.hit = false; + + float a = dot(ray.dir, ray.dir); + float b = 2.0 * dot(ray.dir, ray.origin); + float c = dot(ray.origin, ray.origin) - rad * rad; + + float d = b * b - 4.0 * a * c; + if(d < 0.0) return res; + + float sqrt_d = sqrt(d); + float t1 = (-b + sqrt_d) / (2.0 * a); + float t2 = (-b - sqrt_d) / (2.0 * a); + + if((t1 >= 0.0 || t2 >= 0.0)) { + if(t1 < 0.0) t1 = t2; + if(t2 < 0.0) t2 = t1; + + res.hit = true; + res.t = min(t1, t2); + res.pos = ray.origin + ray.dir * res.t; + res.color = vec3(1.0, 0.3, 0.2); + res.normal = res.pos / rad; + } + + return res; +} + +#define FLOOR_HEIGHT (-2.0) + +ISect ray_floor(Ray ray) +{ + ISect res; + res.hit = false; + + if(ray.origin.y < FLOOR_HEIGHT || ray.dir.y >= 0.0) { + return res; + } + + res.normal = vec3(0.0, 1.0, 0.0); + float ndotdir = dot(res.normal, ray.dir); + + float t = (FLOOR_HEIGHT - ray.origin.y) / ndotdir; + res.pos = ray.origin + ray.dir * t; + + if(abs(res.pos.x) > 8.0 || abs(res.pos.z) > 8.0) { + res.hit = false; + } else { + res.hit = true; + + float chess = mod(floor(res.pos.x) + floor(res.pos.z), 2.0); + res.color = mix(vec3(0.498, 0.165, 0.149), vec3(0.776, 0.851, 0.847), chess); + res.kr = 0.0; + } + return res; +} + +Ray get_primary_ray() +{ + Ray ray; + vec2 tc = gl_TexCoord[0].xy; + ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz); + ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; + return ray; +} + diff -r 000000000000 -r 09bb67c000bc sdr/sdr.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/sdr.v.glsl Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = gl_Vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; +} diff -r 000000000000 -r 09bb67c000bc src/rayfract.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rayfract.cc Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,293 @@ +#include +#include +#include +#include +#include +#include +#include "sdr.h" + +void disp(); +void reshape(int x, int y); +void keyb(unsigned char key, int x, int y); +void mouse(int bn, int state, int x, int y); +void motion(int x, int y); + +int load_shader(); +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale = 0); +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); +static int round_pow2(int x); + +float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; +float cam_y = 0; + +unsigned int sdr; +unsigned int ray_tex; +Vector2 tex_scale; +Vector4 seed; +float err_thres = 0.0075; +int iter = 10; + +int main(int argc, char **argv) +{ + int xsz, ysz; + + seed = Vector4(0.4, 0.0, 0.0, -0.8); + + glutInitWindowSize(640, 480); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow("Raytraced Fractals"); + xsz = glutGet(GLUT_WINDOW_WIDTH); + ysz = glutGet(GLUT_WINDOW_HEIGHT); + + glutDisplayFunc(disp); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_CULL_FACE); + + glewInit(); + + if(load_shader() == -1) { + return 1; + } + + glutMainLoop(); + return 0; +} + +int load_shader() +{ + if(sdr) { + free_program(sdr); + } + + if(!(sdr = create_program_load("sdr/sdr.v.glsl", "sdr/julia.p.glsl"))) { + return -1; + } + set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w); + set_uniform_float(sdr, "err_thres", err_thres); + set_uniform_int(sdr, "iter", iter); + return 0; +} + +void disp() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(cam_theta, 0, 1, 0); + glRotatef(cam_phi, 1, 0, 0); + glTranslatef(0, 0, -cam_dist); + + float lpos[] = {-1, 1, 3, 0}; + glLightfv(GL_LIGHT0, GL_POSITION, lpos); + + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glScalef(tex_scale.x, tex_scale.y, 1.0); + + glBindTexture(GL_TEXTURE_2D, ray_tex); + glEnable(GL_TEXTURE_2D); + bind_program(sdr); + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord2f(0, 1); glVertex2f(-1, -1); + glTexCoord2f(1, 1); glVertex2f(1, -1); + glTexCoord2f(1, 0); glVertex2f(1, 1); + glTexCoord2f(0, 0); glVertex2f(-1, 1); + glEnd(); + + bind_program(0); + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + + glutSwapBuffers(); + assert(glGetError() == GL_NO_ERROR); +} + +void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0); + + if(ray_tex) { + glDeleteTextures(1, &ray_tex); + } + ray_tex = create_ray_texture(x, y, 50.0, &tex_scale); +} + + +void keyb(unsigned char key, int x, int y) +{ + switch(key) { + case 27: + exit(0); + + case '-': + if(iter > 1) { + iter--; + set_uniform_int(sdr, "iter", iter); + printf("iter: %d\n", iter); + glutPostRedisplay(); + } + break; + + case '=': + iter++; + set_uniform_int(sdr, "iter", iter); + printf("iter: %d\n", iter); + glutPostRedisplay(); + break; + + case ',': + err_thres -= 0.001; + set_uniform_float(sdr, "err_thres", err_thres); + printf("maximum error: %f\n", err_thres); + glutPostRedisplay(); + break; + + case '.': + err_thres += 0.001; + set_uniform_float(sdr, "err_thres", err_thres); + printf("maximum error: %f\n", err_thres); + glutPostRedisplay(); + break; + + case 's': + load_shader(); + glutPostRedisplay(); + break; + } +} + +int bnstate[16]; + +int prev_x = -1, prev_y; +void mouse(int bn, int state, int x, int y) +{ + bnstate[bn] = state == GLUT_DOWN ? 1 : 0; + if(state == GLUT_DOWN) { + if(bn == 3) { + cam_dist -= 0.1; + glutPostRedisplay(); + if(cam_dist < 0) cam_dist = 0; + } else if(bn == 4) { + cam_dist += 0.1; + glutPostRedisplay(); + } else { + prev_x = x; + prev_y = y; + } + } else { + prev_x = -1; + } +} + +void motion(int x, int y) +{ + if(bnstate[0]) { + cam_theta += (x - prev_x) * 0.5; + cam_phi += (y - prev_y) * 0.5; + + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + + glutPostRedisplay(); + } + + if(bnstate[1]) { + cam_y += (y - prev_y) * 0.1; + glutPostRedisplay(); + } + + if(bnstate[2]) { + cam_dist += (y - prev_y) * 0.1; + glutPostRedisplay(); + } + + prev_x = x; + prev_y = y; +} + +unsigned int create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale) +{ + unsigned int tex; + int tex_xsz = round_pow2(xsz); + int tex_ysz = round_pow2(ysz); + float *teximg, *dir; + + teximg = new float[3 * tex_xsz * tex_ysz]; + dir = teximg; + + for(int i=0; ix = (float)xsz / (float)tex_xsz; + tex_scale->y = (float)ysz / (float)tex_ysz; + } + return tex; +} + +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) +{ + float vfov = M_PI * vfov_deg / 180.0; + float aspect = (float)w / (float)h; + + float ysz = 2.0; + float xsz = aspect * ysz; + + float px = ((float)x / (float)w) * xsz - xsz / 2.0; + float py = 1.0 - ((float)y / (float)h) * ysz; + float pz = 1.0 / tan(0.5 * vfov); + + float mag = sqrt(px * px + py * py + pz * pz); + + return Vector3(px / mag, py / mag, pz / mag); +} + +static int round_pow2(int x) +{ + x--; + x = (x >> 1) | x; + x = (x >> 2) | x; + x = (x >> 4) | x; + x = (x >> 8) | x; + x = (x >> 16) | x; + return x + 1; +} diff -r 000000000000 -r 09bb67c000bc src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,324 @@ +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix__) +#include +#include +#endif /* unix */ + +#include "sdr.h" + +unsigned int create_vertex_shader(const char *src) +{ + return create_shader(src, GL_VERTEX_SHADER); +} + +unsigned int create_pixel_shader(const char *src) +{ + return create_shader(src, GL_FRAGMENT_SHADER); +} + +unsigned int create_shader(const char *src, unsigned int sdr_type) +{ + unsigned int sdr; + int success, info_len; + char *info_str = 0; + GLenum err; + + sdr = glCreateShader(sdr_type); + assert(glGetError() == GL_NO_ERROR); + glShaderSource(sdr, 1, &src, 0); + err = glGetError(); + assert(err == GL_NO_ERROR); + glCompileShader(sdr); + assert(glGetError() == GL_NO_ERROR); + + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); + assert(glGetError() == GL_NO_ERROR); + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetShaderInfoLog(sdr, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + } + } + + if(success) { + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); + } else { + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); + glDeleteShader(sdr); + sdr = 0; + } + + free(info_str); + return sdr; +} + +void free_shader(unsigned int sdr) +{ + glDeleteShader(sdr); +} + +unsigned int load_vertex_shader(const char *fname) +{ + return load_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int load_pixel_shader(const char *fname) +{ + return load_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int load_shader(const char *fname, unsigned int sdr_type) +{ +#if defined(unix) || defined(__unix__) + struct stat st; +#endif + unsigned int sdr; + size_t filesize; + FILE *fp; + char *src; + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); + return 0; + } + +#if defined(unix) || defined(__unix__) + fstat(fileno(fp), &st); + filesize = st.st_size; +#else + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); +#endif /* unix */ + + if(!(src = malloc(filesize + 1))) { + fclose(fp); + return 0; + } + fread(src, 1, filesize, fp); + src[filesize] = 0; + fclose(fp); + + fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname); + sdr = create_shader(src, sdr_type); + + free(src); + return sdr; +} + + +unsigned int get_vertex_shader(const char *fname) +{ + return get_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int get_pixel_shader(const char *fname) +{ + return get_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int get_shader(const char *fname, unsigned int sdr_type) +{ + unsigned int sdr; +#if 0 + if((res = get_resource(sdrman, fname))) { + /* TODO: validate that the shader matches sdr_type? */ + return (uintptr_t)res; + } +#endif + + if(!(sdr = load_shader(fname, sdr_type))) { + return 0; + } + add_shader(fname, sdr); + return sdr; +} + +int add_shader(const char *fname, unsigned int sdr) +{ + return 0;/*add_resource(sdrman, fname, (void*)(uintptr_t)sdr);*/ +} + +int remove_shader(const char *fname) +{ + return 0;/*remove_resource(sdrman, fname);*/ +} + + +/* ---- gpu programs ---- */ + +unsigned int create_program(void) +{ + unsigned int prog = glCreateProgram(); + assert(glGetError() == GL_NO_ERROR); + return prog; +} + +unsigned int create_program_link(unsigned int vs, unsigned int ps) +{ + unsigned int prog; + + if(!(prog = create_program())) { + return 0; + } + + attach_shader(prog, vs); + assert(glGetError() == GL_NO_ERROR); + attach_shader(prog, ps); + assert(glGetError() == GL_NO_ERROR); + + if(link_program(prog) == -1) { + free_program(prog); + return 0; + } + return prog; +} + +unsigned int create_program_load(const char *vfile, const char *pfile) +{ + unsigned int vs, ps; + + if(!(vs = get_vertex_shader(vfile)) || !(ps = get_pixel_shader(pfile))) { + return 0; + } + return create_program_link(vs, ps); +} + +void free_program(unsigned int sdr) +{ + glDeleteProgram(sdr); +} + +void attach_shader(unsigned int prog, unsigned int sdr) +{ + glAttachShader(prog, sdr); + assert(glGetError() == GL_NO_ERROR); +} + +int link_program(unsigned int prog) +{ + int linked, info_len, retval = 0; + char *info_str = 0; + + glLinkProgram(prog); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_LINK_STATUS, &linked); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetProgramInfoLog(prog, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + } + } + + if(linked) { + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); + } else { + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); + retval = -1; + } + + free(info_str); + return retval; +} + +int bind_program(unsigned int prog) +{ + GLenum err; + + glUseProgram(prog); + if(prog && (err = glGetError()) != GL_NO_ERROR) { + /* maybe the program is not linked, try to link first */ + if(err == GL_INVALID_OPERATION) { + if(link_program(prog) == -1) { + return -1; + } + glUseProgram(prog); + return glGetError() == GL_NO_ERROR ? 0 : -1; + } + return -1; + } + return 0; +} + +/* ugly but I'm not going to write the same bloody code over and over */ +#define BEGIN_UNIFORM_CODE \ + int loc, curr_prog; \ + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ + if(curr_prog != prog && bind_program(prog) == -1) { \ + return -1; \ + } \ + if((loc = glGetUniformLocation(prog, name)) != -1) + +#define END_UNIFORM_CODE \ + if(curr_prog != prog) { \ + bind_program(curr_prog); \ + } \ + return loc == -1 ? -1 : 0 + +int set_uniform_int(unsigned int prog, const char *name, int val) +{ + BEGIN_UNIFORM_CODE { + glUniform1i(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float(unsigned int prog, const char *name, float val) +{ + BEGIN_UNIFORM_CODE { + glUniform1f(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) +{ + BEGIN_UNIFORM_CODE { + glUniform3f(loc, x, y, z); + } + END_UNIFORM_CODE; +} + +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) +{ + BEGIN_UNIFORM_CODE { + glUniform4f(loc, x, y, z, w); + } + END_UNIFORM_CODE; +} + + +int get_attrib_loc(unsigned int prog, const char *name) +{ + int loc, curr_prog; + + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); + if(curr_prog != prog && bind_program(prog) == -1) { + return -1; + } + + loc = glGetAttribLocation(prog, (char*)name); + + if(curr_prog != prog) { + bind_program(curr_prog); + } + return loc; +} + +void set_attrib_float3(int attr_loc, float x, float y, float z) +{ + glVertexAttrib3f(attr_loc, x, y, z); +} diff -r 000000000000 -r 09bb67c000bc src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Thu Oct 21 23:39:26 2010 +0300 @@ -0,0 +1,47 @@ +#ifndef _SDR_H_ +#define _SDR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* ---- shaders ---- */ +unsigned int create_vertex_shader(const char *src); +unsigned int create_pixel_shader(const char *src); +unsigned int create_shader(const char *src, unsigned int sdr_type); +void free_shader(unsigned int sdr); + +unsigned int load_vertex_shader(const char *fname); +unsigned int load_pixel_shader(const char *fname); +unsigned int load_shader(const char *src, unsigned int sdr_type); + +unsigned int get_vertex_shader(const char *fname); +unsigned int get_pixel_shader(const char *fname); +unsigned int get_shader(const char *fname, unsigned int sdr_type); + +int add_shader(const char *fname, unsigned int sdr); +int remove_shader(const char *fname); + +/* ---- gpu programs ---- */ +unsigned int create_program(void); +unsigned int create_program_link(unsigned int vs, unsigned int ps); +unsigned int create_program_load(const char *vfile, const char *pfile); +void free_program(unsigned int sdr); + +void attach_shader(unsigned int prog, unsigned int sdr); +int link_program(unsigned int prog); +int bind_program(unsigned int prog); + +int set_uniform_int(unsigned int prog, const char *name, int val); +int set_uniform_float(unsigned int prog, const char *name, float val); +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); + +int get_attrib_loc(unsigned int prog, const char *name); +void set_attrib_float3(int attr_loc, float x, float y, float z); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SDR_H_ */