# HG changeset patch # User John Tsiombikas # Date 1355660656 -7200 # Node ID a39c301cdcce8450f94157e1e5022201d72284d4 # Parent 1757973feaed2e99242c07512a158999c94095ed terrain raytracing pretty much done diff -r 1757973feaed -r a39c301cdcce Makefile --- a/Makefile Sun Dec 16 00:37:35 2012 +0200 +++ b/Makefile Sun Dec 16 14:24:16 2012 +0200 @@ -1,11 +1,13 @@ -src = $(wildcard src/*.cc) -obj = $(src:.cc=.o) +csrc = $(wildcard src/*.c) +ccsrc = $(wildcard src/*.cc) +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) dep = $(obj:.o=.d) bin = blobo opt = -O3 -ffast-math dbg = -g +CFLAGS = -pedantic -Wall $(opt) $(dbg) CXXFLAGS = -ansi -pedantic -Wall $(opt) $(dbg) LDFLAGS = $(libgl) -lvmath -limago @@ -20,8 +22,11 @@ -include $(dep) +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + %.d: %.cc - @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ .PHONY: clean clean: diff -r 1757973feaed -r a39c301cdcce README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Sun Dec 16 14:24:16 2012 +0200 @@ -0,0 +1,3 @@ +bloboland +--------- +by John Tsiombikas (nuclear) diff -r 1757973feaed -r a39c301cdcce RUN --- a/RUN Sun Dec 16 00:37:35 2012 +0200 +++ b/RUN Sun Dec 16 14:24:16 2012 +0200 @@ -1,3 +1,3 @@ #!/bin/sh -./blobo -world 100x100x32 -genscale 10 $* +./blobo -world 128x128x80 -genscale 10 -size 1024x640 $* diff -r 1757973feaed -r a39c301cdcce sdr/bloboray.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/bloboray.p.glsl Sun Dec 16 14:24:16 2012 +0200 @@ -0,0 +1,152 @@ +struct Ray { + vec3 origin; + vec3 dir; +}; + +struct AABBox { + vec3 vmin, vmax; +}; + +struct HitPoint { + bool hit; + float t0, t1; + vec3 pos, normal; + vec4 color; +}; + +vec3 shade(Ray ray, HitPoint hit); +HitPoint intersect_voxels(Ray ray); +HitPoint intersect_aabb(Ray ray, AABBox aabb); +Ray get_primary_ray(float x, float y); + +#define RAY_STEP 0.001 + +#define FOV camprop.x +#define ASPECT camprop.y +uniform vec4 camprop; +uniform vec3 volsize; +uniform sampler3D voltex; + +//const vec3 worldsize = vec3(4.0, 4.0, 2.0); +const vec3 worldsize = vec3(1.0, 1.0, 0.5); + +void main() +{ + Ray ray = get_primary_ray(gl_TexCoord[0].x, gl_TexCoord[0].y); + + vec3 color = vec3(0.0, 0.0, 0.0); + HitPoint hit = intersect_voxels(ray); + if(hit.hit) { + color = shade(ray, hit); + } + + gl_FragColor = vec4(color, 1.0); +} + +vec3 shade(Ray ray, HitPoint hit) +{ + const vec3 light_pos = vec3(-2, 3, 2); + vec3 ldir = normalize(light_pos - hit.pos); + + vec3 vdir = normalize(-ray.dir); + vec3 hvec = normalize(vdir + ldir); + + float ndotl = max(dot(hit.normal, ldir), 0.0); + float ndoth = max(dot(hit.normal, hvec), 0.0); + + vec3 diffuse = hit.color.xyz * ndotl; + vec3 specular = vec3(0.4, 0.4, 0.4) * pow(ndoth, 60.0); + + return diffuse + specular; +} + +vec4 fetch_voxel(vec3 pt) +{ + pt *= 1.0 / worldsize; + return texture3D(voltex, pt * 0.5 + 0.5); +} + +vec3 calc_voxel_normal(vec3 pt) +{ + vec3 offs = 1.8 / volsize; + float dfdx = fetch_voxel(pt + vec3(offs.x, 0.0, 0.0)).w - fetch_voxel(pt - vec3(offs.x, 0.0, 0.0)).w; + float dfdy = fetch_voxel(pt + vec3(0.0, offs.y, 0.0)).w - fetch_voxel(pt - vec3(0.0, offs.y, 0.0)).w; + float dfdz = fetch_voxel(pt + vec3(0.0, 0.0, offs.z)).w - fetch_voxel(pt - vec3(0.0, 0.0, offs.z)).w; + + return -normalize(vec3(dfdx, dfdy, dfdz)); +} + +HitPoint intersect_voxels(Ray ray) +{ + HitPoint hit; + //AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0)); + AABBox aabb = AABBox(-worldsize.xzy, worldsize.xzy); + + + hit = intersect_aabb(ray, aabb); + if(!hit.hit) { + return hit; + } + + /* start tracing from the first intersection, or if it's behind + * the viewer, start from 0. + */ + float dist = max(hit.t0, 0.0); + float end_dist = hit.t1; + + while(dist < end_dist) { + vec3 pt = ray.origin + ray.dir * dist; + vec4 voxel = fetch_voxel(pt.xzy); + + + if(voxel.a > 0.5) { + hit.t0 = dist; + hit.pos = pt; + hit.normal = calc_voxel_normal(pt.xzy).xzy; + hit.color = voxel; + return hit; + } + + dist += RAY_STEP; + } + + hit.hit = false; + return hit; +} + +HitPoint intersect_aabb(Ray ray, AABBox aabb) +{ + HitPoint res; + + vec3 invR = 1.0 / ray.dir; + vec3 tbot = invR * (aabb.vmin - ray.origin); + vec3 ttop = invR * (aabb.vmax - ray.origin); + vec3 tmin = min(ttop, tbot); + vec3 tmax = max(ttop, tbot); + vec2 t = max(tmin.xx, tmin.yz); + float t0 = max(t.x, t.y); + t = min(tmax.xx, tmax.yz); + float t1 = min(t.x, t.y); + + if(t0 <= t1) { + res.hit = true; + res.t0 = t0; + res.t1 = t1; + } else { + res.hit = false; + } + return res; +} + +Ray get_primary_ray(float x, float y) +{ + vec3 dir; + dir.x = ASPECT * (2.0 * x - 1.0); + dir.y = 2.0 * y - 1.0; + dir.z = -1.0 / tan(FOV / 2.0); + + Ray ray; + ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; + ray.dir = gl_NormalMatrix * normalize(dir); + return ray; +} diff -r 1757973feaed -r a39c301cdcce sdr/bloboray.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/bloboray.v.glsl Sun Dec 16 14:24:16 2012 +0200 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff -r 1757973feaed -r a39c301cdcce src/camera.cc --- a/src/camera.cc Sun Dec 16 00:37:35 2012 +0200 +++ b/src/camera.cc Sun Dec 16 14:24:16 2012 +0200 @@ -148,8 +148,8 @@ { mat->reset_identity(); mat->translate(Vector3(pos.x, pos.y, pos.z)); - mat->rotate(Vector3(0, theta, 0)); - mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, -theta, 0)); + mat->rotate(Vector3(-phi, 0, 0)); } void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const diff -r 1757973feaed -r a39c301cdcce src/game.cc --- a/src/game.cc Sun Dec 16 00:37:35 2012 +0200 +++ b/src/game.cc Sun Dec 16 14:24:16 2012 +0200 @@ -31,14 +31,16 @@ float lpos[] = {-1, 1, 1, 0}; glLightfv(GL_LIGHT0, GL_POSITION, lpos); - printf("initializing renderer\n"); - rend = new Renderer; - rend->init(); - printf("generating level\n"); level = new Level; level->generate(); + printf("initializing renderer\n"); + rend = new Renderer; + if(!rend->init(level)) { + return false; + } + cam.input_move(0, 2, 2); cam.input_rotate(0, M_PI / 5, 0); @@ -75,6 +77,8 @@ void game_render() { + rend->set_aspect((float)win_xsz / (float)win_ysz); + if(opt.stereo) { glDrawBuffer(GL_BACK_LEFT); @@ -85,7 +89,7 @@ glLoadIdentity(); view_matrix(-1); - rend->render(level); + rend->render(); glDrawBuffer(GL_BACK_RIGHT); @@ -96,7 +100,7 @@ glLoadIdentity(); view_matrix(1); - rend->render(level); + rend->render(); } else { glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -105,7 +109,7 @@ glLoadIdentity(); view_matrix(0); - rend->render(level); + rend->render(); } } @@ -128,7 +132,7 @@ { float offs = stereo_eye_sep * eye * 0.5; glTranslatef(-offs, 0, 0); - cam.use_inverse(); + cam.use(); } static void proj_matrix(int eye) diff -r 1757973feaed -r a39c301cdcce src/level.cc --- a/src/level.cc Sun Dec 16 00:37:35 2012 +0200 +++ b/src/level.cc Sun Dec 16 14:24:16 2012 +0200 @@ -12,6 +12,19 @@ delete terrain; } +static float terrain_func(float x, float y, float z) +{ + float nx = (x * 2.0 - 1.0) * 0.9; + float ny = (y * 2.0 - 1.0) * 0.9; + float valley = nx * nx + ny * ny; + + float s = opt.gen_noise_scale; + float noise = 0.2 * fbm2(x * s, y * s, 3) * (valley + 0.25); + float grad = 0.75 - z + noise + valley * 0.4; + + return grad; +} + void Level::generate() { delete terrain; @@ -24,29 +37,33 @@ for(int i=0; iset_voxel(i, j, k, voxel); } } diff -r 1757973feaed -r a39c301cdcce src/renderer.cc --- a/src/renderer.cc Sun Dec 16 00:37:35 2012 +0200 +++ b/src/renderer.cc Sun Dec 16 14:24:16 2012 +0200 @@ -1,10 +1,16 @@ #include "opengl.h" #include "renderer.h" +#include "sdr.h" Renderer::Renderer() { leveltex = 0; sdrprog = 0; + + level = 0; + + fov = M_PI / 4.0; + aspect = 1.0; } Renderer::~Renderer() @@ -12,14 +18,18 @@ shutdown(); } -bool Renderer::init() +bool Renderer::init(Level *level) { - sdrprog = new SdrProg; - /*if(!sdrprog->load("sdr/bloboray.v.glsl", "sdr/bloboray.p.glsl")) { + if(!(sdrprog = create_program_load("sdr/bloboray.v.glsl", "sdr/bloboray.p.glsl"))) { return false; - }*/ + } + + Volume *vol = level->terrain; leveltex = new Texture3D; + leveltex->create(vol->get_size(0), vol->get_size(1), vol->get_size(2)); + + this->level = level; return true; } @@ -27,16 +37,48 @@ void Renderer::shutdown() { delete leveltex; - delete sdrprog; + if(sdrprog) { + free_program(sdrprog); + } +} + +void Renderer::set_fov(float fov) +{ + this->fov = fov; +} + +void Renderer::set_aspect(float aspect) +{ + this->aspect = aspect; } static void draw_cube(const Vector3 &pos, float sz); -void Renderer::render(const Level *lvl) const +void Renderer::render() const { - Volume *vol = lvl->terrain; + leveltex->update((float*)level->terrain->get_data_ptr()); + bind_texture(leveltex); - glEnable(GL_COLOR_MATERIAL); + set_uniform_float3(sdrprog, "volsize", level->terrain->get_size(0), + level->terrain->get_size(1), level->terrain->get_size(2)); + set_uniform_float4(sdrprog, "camprop", fov, aspect, 0, 0); + bind_program(sdrprog); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(1, -1); + glTexCoord2f(1, 1); + glVertex2f(1, 1); + glTexCoord2f(0, 1); + glVertex2f(-1, 1); + glEnd(); + + bind_program(0); + bind_texture(0); + + /*glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glBegin(GL_QUADS); @@ -60,6 +102,7 @@ glEnd(); glDisable(GL_COLOR_MATERIAL); + */ } diff -r 1757973feaed -r a39c301cdcce src/renderer.h --- a/src/renderer.h Sun Dec 16 00:37:35 2012 +0200 +++ b/src/renderer.h Sun Dec 16 14:24:16 2012 +0200 @@ -1,23 +1,28 @@ #ifndef RENDERER_H_ #define RENDERER_H_ -#include "shaders.h" #include "texture.h" #include "level.h" class Renderer { private: - mutable Texture3D *leveltex; - SdrProg *sdrprog; + Level *level; + Texture3D *leveltex; + unsigned int sdrprog; + + float fov, aspect; public: Renderer(); ~Renderer(); - bool init(); + bool init(Level *lvl); void shutdown(); - void render(const Level *lvl) const; + void set_fov(float fov); + void set_aspect(float aspect); + + void render() const; }; #endif // RENDERER_H_ diff -r 1757973feaed -r a39c301cdcce src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Sun Dec 16 14:24:16 2012 +0200 @@ -0,0 +1,410 @@ +#include +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix__) +#include +#include +#endif /* unix */ + +#include "sdr.h" + +static const char *sdrtypestr(unsigned int sdrtype); + +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_tessctl_shader(const char *src) +{ + return create_shader(src, GL_TESS_CONTROL_SHADER); +} + +unsigned int create_tesseval_shader(const char *src) +{ + return create_shader(src, GL_TESS_EVALUATION_SHADER); +} + +unsigned int create_geometry_shader(const char *src) +{ + return create_shader(src, GL_GEOMETRY_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_tessctl_shader(const char *fname) +{ + return load_shader(fname, GL_TESS_CONTROL_SHADER); +} + +unsigned int load_tesseval_shader(const char *fname) +{ + return load_shader(fname, GL_TESS_EVALUATION_SHADER); +} + +unsigned int load_geometry_shader(const char *fname) +{ + return load_shader(fname, GL_GEOMETRY_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... ", sdrtypestr(sdr_type), 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_tessctl_shader(const char *fname) +{ + return get_shader(fname, GL_TESS_CONTROL_SHADER); +} + +unsigned int get_tesseval_shader(const char *fname) +{ + return get_shader(fname, GL_TESS_EVALUATION_SHADER); +} + +unsigned int get_geometry_shader(const char *fname) +{ + return get_shader(fname, GL_GEOMETRY_SHADER); +} + +unsigned int get_shader(const char *fname, unsigned int sdr_type) +{ + unsigned int sdr; + if(!(sdr = load_shader(fname, sdr_type))) { + return 0; + } + return sdr; +} + + +/* ---- 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 sdr0, ...) +{ + unsigned int prog, sdr; + va_list ap; + + if(!(prog = create_program())) { + return 0; + } + + attach_shader(prog, sdr0); + if(glGetError()) { + return 0; + } + + va_start(ap, sdr0); + while((sdr = va_arg(ap, unsigned int))) { + attach_shader(prog, sdr); + if(glGetError()) { + return 0; + } + } + va_end(ap); + + 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 = 0, ps = 0; + + if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) { + return 0; + } + if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) { + return 0; + } + return create_program_link(vs, ps, 0); +} + +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 linking 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((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ + return -1; \ + } \ + if((loc = glGetUniformLocation(prog, name)) != -1) + +#define END_UNIFORM_CODE \ + if((unsigned int)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_float2(unsigned int prog, const char *name, float x, float y) +{ + BEGIN_UNIFORM_CODE { + glUniform2f(loc, x, y); + } + 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 set_uniform_matrix4(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); + } + END_UNIFORM_CODE; +} + +int get_attrib_loc(unsigned int prog, const char *name) +{ + int loc, curr_prog; + + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { + return -1; + } + + loc = glGetAttribLocation(prog, (char*)name); + + if((unsigned int)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); +} + +static const char *sdrtypestr(unsigned int sdrtype) +{ + switch(sdrtype) { + case GL_VERTEX_SHADER: + return "vertex"; + case GL_FRAGMENT_SHADER: + return "pixel"; + case GL_TESS_CONTROL_SHADER: + return "tessellation control"; + case GL_TESS_EVALUATION_SHADER: + return "tessellation evaluation"; + case GL_GEOMETRY_SHADER: + return "geometry"; + + default: + break; + } + return ""; +} diff -r 1757973feaed -r a39c301cdcce src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Sun Dec 16 14:24:16 2012 +0200 @@ -0,0 +1,59 @@ +#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_tessctl_shader(const char *src); +unsigned int create_tesseval_shader(const char *src); +unsigned int create_geometry_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_tessctl_shader(const char *fname); +unsigned int load_tesseval_shader(const char *fname); +unsigned int load_geometry_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_tessctl_shader(const char *fname); +unsigned int get_tesseval_shader(const char *fname); +unsigned int get_geometry_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 sdr0, ...); +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_float2(unsigned int prog, const char *name, float x, float y); +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 set_uniform_matrix4(unsigned int prog, const char *name, float *mat); +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); + +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_ */ diff -r 1757973feaed -r a39c301cdcce src/shaders.cc --- a/src/shaders.cc Sun Dec 16 00:37:35 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -#include -#include -#include -#ifdef _MSC_VER -#include -#else -#include -#endif -#include -#include "shaders.h" - -Shader::Shader(unsigned int type) -{ - sdr = glCreateShader(type); - compiled = false; - - assert(glGetError() == GL_NO_ERROR); -} - -Shader::~Shader() -{ - glDeleteShader(sdr); -} - -void Shader::set_source(const char *src) -{ - glShaderSource(sdr, 1, &src, 0); - compiled = false; - - assert(glGetError() == GL_NO_ERROR); -} - -bool Shader::compile() -{ - if(compiled) { - return true; - } - - glCompileShader(sdr); - - int len; - glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &len); - if(len) { - char *buf = (char*)alloca(len + 1); - glGetShaderInfoLog(sdr, len, &len, buf); - fprintf(stderr, "compiler: %s\n", buf); - } - - int status; - glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); - if(!status) { - fprintf(stderr, "shader compilation failed\n"); - return false; - } - - compiled = true; - return true; -} - -bool Shader::is_compiled() const -{ - return compiled; -} - -bool Shader::load(const char *fname) -{ - FILE *fp; - - if(!(fp = fopen(fname, "rb"))) { - fprintf(stderr, "failed to open shader file: %s\n", fname); - return false; - } - - fseek(fp, 0, SEEK_END); - long sz = ftell(fp); - rewind(fp); - - char *buf = new char[sz + 1]; - if((long)fread(buf, 1, sz, fp) < sz) { - fprintf(stderr, "failed to read shader contents\n"); - fclose(fp); - return false; - } - fclose(fp); - - set_source(buf); - delete [] buf; - - return compile(); -} - -// ---- shader manager ---- -static std::map sdrcache; - -Shader *get_shader(const char *fname, unsigned int type) -{ - std::map::const_iterator it; - - if((it = sdrcache.find(std::string(fname))) != sdrcache.end()) { - return it->second; - } - - Shader *sdr = new Shader(type); - if(!sdr->load(fname)) { - delete sdr; - return 0; - } - sdrcache[fname] = sdr; - return sdr; -} - - -// ---- class SdrProg ---- - -SdrProg::SdrProg() -{ - prog = glCreateProgram(); - linked = false; - assert(glGetError() == GL_NO_ERROR); -} - -SdrProg::~SdrProg() -{ - glDeleteProgram(prog); -} - -void SdrProg::add_shader(Shader *sdr) -{ - if(sdr->compile()) { - glAttachShader(prog, sdr->sdr); - assert(glGetError() == GL_NO_ERROR); - - shaders.push_back(sdr); - linked = false; - } -} - -bool SdrProg::link() -{ - if(linked) { - return true; - } - - glLinkProgram(prog); - - int len; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); - if(len) { - char *buf = (char*)alloca(len + 1); - glGetProgramInfoLog(prog, len, &len, buf); - assert(glGetError() == GL_NO_ERROR); - fprintf(stderr, "linker: %s\n", buf); - } - - int status; - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if(!status) { - fprintf(stderr, "program linking failed\n"); - return false; - } - - linked = true; - return true; -} - -bool SdrProg::load(const char *vsfname, const char *psfname) -{ - Shader *sdr; - - if(vsfname) { - if(!(sdr = get_shader(vsfname, GL_VERTEX_SHADER))) { - return false; - } - add_shader(sdr); - } - - if(psfname) { - if(!(sdr = get_shader(psfname, GL_FRAGMENT_SHADER))) { - return false; - } - add_shader(sdr); - } - return link(); -} - -int SdrProg::get_uniform_location(const char *name) -{ - bind_program(this); - return glGetUniformLocation(prog, name); -} - -int SdrProg::get_attribute_location(const char *name) -{ - bind_program(this); - return glGetAttribLocation(prog, name); -} - -void SdrProg::set_uniform(const char *name, int val) -{ - set_uniform(get_uniform_location(name), val); -} - -void SdrProg::set_uniform(const char *name, float val) -{ - set_uniform(get_uniform_location(name), val); -} - -void SdrProg::set_uniform(const char *name, const Vector2 &v) -{ - set_uniform(get_uniform_location(name), v); -} - -void SdrProg::set_uniform(const char *name, const Vector3 &v) -{ - set_uniform(get_uniform_location(name), v); -} - -void SdrProg::set_uniform(const char *name, const Vector4 &v) -{ - set_uniform(get_uniform_location(name), v); -} - -void SdrProg::set_uniform(const char *name, const Matrix4x4 &mat) -{ - set_uniform(get_uniform_location(name), mat); -} - - -void SdrProg::set_uniform(int loc, int val) -{ - if(loc >= 0) { - bind_program(this); - glUniform1i(loc, val); - } -} - -void SdrProg::set_uniform(int loc, float val) -{ - if(loc >= 0) { - bind_program(this); - glUniform1f(loc, val); - } -} - -void SdrProg::set_uniform(int loc, const Vector2 &v) -{ - if(loc >= 0) { - bind_program(this); - glUniform2f(loc, v.x, v.y); - } -} - -void SdrProg::set_uniform(int loc, const Vector3 &v) -{ - if(loc >= 0) { - bind_program(this); - glUniform3f(loc, v.x, v.y, v.z); - } -} - -void SdrProg::set_uniform(int loc, const Vector4 &v) -{ - if(loc >= 0) { - bind_program(this); - glUniform4f(loc, v.x, v.y, v.z, v.w); - } -} - -void SdrProg::set_uniform(int loc, const Matrix4x4 &mat) -{ - if(loc >= 0) { - bind_program(this); - // loading transpose matrix (3rd arg true) -#ifdef SINGLE_PRECISION_MATH - glUniformMatrix4fv(loc, 1, GL_TRUE, (float*)mat.m); -#else - glUniformMatrix4dv(loc, 1, GL_TRUE, (double*)mat.m); -#endif - } -} - -bool bind_program(const SdrProg *prog) -{ - if(!prog) { - glUseProgram(0); - return true; - } - - if(!((SdrProg*)prog)->link()) { - return false; - } - glUseProgram(prog->prog); - if(glGetError()) { - return false; - } - return true; -} diff -r 1757973feaed -r a39c301cdcce src/shaders.h --- a/src/shaders.h Sun Dec 16 00:37:35 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#ifndef SDR_H_ -#define SDR_H_ - -#include -#include "vmath/vmath.h" - -class Shader { -private: - bool compiled; - -public: - unsigned int sdr; - - Shader(unsigned int type); - ~Shader(); - - void set_source(const char *src); - - bool compile(); - bool is_compiled() const; - - bool load(const char *fname); -}; - - -// public shader manager interface -Shader *get_shader(const char *fname, unsigned int type); - - -class SdrProg { -private: - // SdrProg does not own the shader objects - std::vector shaders; - bool linked; - -public: - unsigned int prog; - - SdrProg(); - ~SdrProg(); - - void add_shader(Shader *sdr); - bool link(); - - bool load(const char *vsfname, const char *psfname); - - int get_uniform_location(const char *name); - int get_attribute_location(const char *name); - - void set_uniform(const char *name, int val); - void set_uniform(const char *name, float val); - void set_uniform(const char *name, const Vector2 &v); - void set_uniform(const char *name, const Vector3 &v); - void set_uniform(const char *name, const Vector4 &v); - void set_uniform(const char *name, const Matrix4x4 &mat); - - void set_uniform(int loc, int val); - void set_uniform(int loc, float val); - void set_uniform(int loc, const Vector2 &v); - void set_uniform(int loc, const Vector3 &v); - void set_uniform(int loc, const Vector4 &v); - void set_uniform(int loc, const Matrix4x4 &mat); -}; - -bool bind_program(const SdrProg *prog); - -#endif /* SDR_H_ */ diff -r 1757973feaed -r a39c301cdcce src/texture.cc --- a/src/texture.cc Sun Dec 16 00:37:35 2012 +0200 +++ b/src/texture.cc Sun Dec 16 14:24:16 2012 +0200 @@ -3,9 +3,9 @@ void bind_texture(const Texture *tex, int texunit) { - static const Texture *curr_tex[8]; + static const Texture *cur_tex[8]; - if(tex == curr_tex[texunit]) { + if(tex == cur_tex[texunit]) { return; } @@ -14,11 +14,11 @@ glEnable(tex->type); glBindTexture(tex->type, tex->tex); } else { - glDisable(tex->type); + glDisable(cur_tex[texunit]->type); } glActiveTexture(GL_TEXTURE0); - curr_tex[texunit] = tex; + cur_tex[texunit] = tex; } @@ -61,6 +61,12 @@ size[1] = ysz; } +void Texture2D::update(float *data) +{ + glBindTexture(type, tex); + glTexSubImage2D(type, 0, 0, 0, size[0], size[1], GL_RGBA, GL_FLOAT, data); +} + Texture3D::Texture3D() { type = GL_TEXTURE_3D; @@ -68,6 +74,9 @@ glBindTexture(type, tex); glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(type, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } void Texture3D::create(int xsz, int ysz, int zsz, float *data) @@ -79,3 +88,9 @@ size[1] = ysz; size[2] = zsz; } + +void Texture3D::update(float *data) +{ + glBindTexture(type, tex); + glTexSubImage3D(type, 0, 0, 0, 0, size[0], size[1], size[2], GL_RGBA, GL_FLOAT, data); +} diff -r 1757973feaed -r a39c301cdcce src/texture.h --- a/src/texture.h Sun Dec 16 00:37:35 2012 +0200 +++ b/src/texture.h Sun Dec 16 14:24:16 2012 +0200 @@ -14,6 +14,8 @@ virtual int get_size(int idx) const; + virtual void update(float *data) = 0; + friend void bind_texture(const Texture *tex, int texunit); }; @@ -24,6 +26,8 @@ Texture2D(); void create(int xsz, int ysz, float *data = 0); + + void update(float *data); }; class Texture3D : public Texture { @@ -31,6 +35,8 @@ Texture3D(); void create(int xsz, int ysz, int zsz, float *data = 0); + + void update(float *data); }; #endif // TEXTURE_H_