# HG changeset patch # User John Tsiombikas # Date 1357607808 -7200 # Node ID 2d27bfd21fc51113c214540e32769c9e839f92ba initial commit diff -r 000000000000 -r 2d27bfd21fc5 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,4 @@ +\.o$ +\.d$ +\.swp$ +^udg$ diff -r 000000000000 -r 2d27bfd21fc5 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,30 @@ +csrc = $(wildcard src/*.c) +ccsrc = $(wildcard src/*.cc) +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) +dep = $(obj:.o=.d) +bin = udg + +CFLAGS = -pedantic -Wall -g +CXXFLAGS = -std=c++11 $(CFLAGS) +LDFLAGS = $(libgl) -limago + +ifeq ($(shell uname -s), Darwin) + libgl = -framework OpenGL -framework GLUT -lGLEW +else + libgl = -lGL -lGLU -lglut -lGLEW +endif + +$(bin): $(obj) + $(CXX) -o $@ $(obj) $(LDFLAGS) + +-include $(dep) + +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +%.d: %.cc + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +.PHONY: clean +clean: + rm -f $(obj) $(bin) $(dep) diff -r 000000000000 -r 2d27bfd21fc5 sdr/dither.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/dither.p.glsl Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,22 @@ +uniform sampler2D framebuf, dither_tex; +uniform int dither_levels, dither_size; + +void main() +{ + float levels = float(dither_levels); + + vec4 pixel = texture2D(framebuf, gl_TexCoord[0].xy); + float lum = dot(pixel.xyz, vec3(0.2126, 0.7152, 0.0722)); + float coord_shift = floor(lum * levels) / levels; + + vec2 dsz2 = vec2(float(dither_size), float(dither_size)); + + vec2 coord = mod(gl_FragCoord.xy, dsz2) / float(dither_size); + coord.y = coord.y / levels + coord_shift; + float val = texture2D(dither_tex, coord).x; + + const vec3 dark_col = vec3(0.043, 0.286, 0.337); + const vec3 bright_col = vec3(0.965, 0.778, 0.555); + + gl_FragColor = vec4(mix(dark_col, bright_col, val), 1.0); +} diff -r 000000000000 -r 2d27bfd21fc5 sdr/dither.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/dither.v.glsl Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff -r 000000000000 -r 2d27bfd21fc5 src/dither_matrix.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dither_matrix.h Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,26 @@ +#ifndef DITHER_MATRIX_H_ +#define DITHER_MATRIX_H_ + +static const float dither_matrix2[2][2] = { + {0, 3}, {2, 1} +}; + +static const float dither_matrix4[4][4] = { + {0, 12, 3, 15}, + {8, 4, 11, 7}, + {2, 14, 1, 13}, + {10, 6, 9, 5} +}; + +static const float dither_matrix8[8][8] = { + {0, 48, 12, 60, 3, 51, 15, 63}, + {32, 16, 44, 28, 35, 19, 47, 31}, + {8, 56, 4, 52, 11, 59, 7, 55}, + {40, 24, 36, 20, 43, 27, 39, 23}, + {2, 50, 14, 62, 1, 49, 13, 61}, + {34, 18, 46, 30, 33, 17, 45, 29}, + {10, 58, 6, 54, 9, 57, 5, 53}, + {42, 26, 38, 22, 41, 25, 37, 21} +}; + +#endif /* DITHER_MATRIX_H_ */ diff -r 000000000000 -r 2d27bfd21fc5 src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Tue Jan 08 03:16:48 2013 +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 000000000000 -r 2d27bfd21fc5 src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Tue Jan 08 03:16:48 2013 +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 000000000000 -r 2d27bfd21fc5 src/udg.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/udg.cc Tue Jan 08 03:16:48 2013 +0200 @@ -0,0 +1,326 @@ +#include +#include +#include +#include +#include + +#ifndef __APPLE__ +#include +#else +#include +#endif + +#include "sdr.h" +#include "dither_matrix.h" + +#define DITHER_SZ 4 +#define DITHER_LEVELS 16 + +struct render_target { + unsigned int fbo; + unsigned int color_tex, depth_buf; +}; + +bool init(); +void cleanup(); +void disp(); +void idle(); +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); +struct render_target *create_rtarg(int xsz, int ysz); +void destroy_rtarg(struct render_target *rt); + +int xsz, ysz; +float cam_theta, cam_phi = 25, cam_dist = 8; +unsigned int dither_tex; +struct render_target *rtarg; +unsigned int prog; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(800, 600); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow("DBF UDG compo entry by Nuclear"); + + glutDisplayFunc(disp); + glutIdleFunc(idle); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + glewInit(); + + if(!init()) { + return 1; + } + + glutMainLoop(); + return 0; +} + +bool init() +{ + float *img = new float[DITHER_SZ * DITHER_SZ * DITHER_LEVELS]; + float *ptr = img; + + for(int i=0; i= thres ? 1.0 : 0.0; + } + } + } + + if(!(prog = create_program_load("sdr/dither.v.glsl", "sdr/dither.p.glsl"))) { + return false; + } + + glGenTextures(1, &dither_tex); + glBindTexture(GL_TEXTURE_2D, dither_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, DITHER_SZ, DITHER_SZ * DITHER_LEVELS, 0, GL_LUMINANCE, GL_FLOAT, img); + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + return true; +} + +void draw_backdrop() +{ + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glBegin(GL_QUADS); + glColor3f(0, 0, 0); + glVertex2f(-1, -1); + glVertex2f(1, -1); + glColor3f(1, 1, 1); + glVertex2f(1, 1); + glVertex2f(-1, 1); + glEnd(); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} + +void disp() +{ + float ldir[] = {-1, 1, 2, 0}; + + if(!rtarg) { + printf("(re)creating render target (%dx%d)\n", xsz, ysz); + if(!(rtarg = create_rtarg(xsz, ysz))) { + exit(0); + } + } + + glBindFramebufferEXT(GL_FRAMEBUFFER, rtarg->fbo); + + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + draw_backdrop(); + + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glLightfv(GL_LIGHT0, GL_POSITION, ldir); + + glTranslatef(0, 0, -cam_dist); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); + + glFrontFace(GL_CW); + glutSolidTeapot(1.0); + glFrontFace(GL_CCW); + + + + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glPushMatrix(); + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + + bind_program(prog); + set_uniform_int(prog, "framebuf", 0); + set_uniform_int(prog, "dither_tex", 1); + set_uniform_int(prog, "dither_levels", DITHER_LEVELS); + set_uniform_int(prog, "dither_size", DITHER_SZ); + + glActiveTextureARB(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rtarg->color_tex); + glActiveTextureARB(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, dither_tex); + + glBegin(GL_QUADS); + glColor3f(0, 1, 0); + 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(); + + glActiveTextureARB(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + glActiveTextureARB(GL_TEXTURE0); + glDisable(GL_TEXTURE_2D); + + bind_program(0); + + glPopAttrib(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glutSwapBuffers(); + assert(glGetError() == GL_NO_ERROR); +} + +void idle() +{ + glutPostRedisplay(); +} + +void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0); + + if(x != xsz || y != ysz) { + destroy_rtarg(rtarg); + rtarg = 0; + xsz = x; + ysz = y; + } +} + +void keyb(unsigned char key, int x, int y) +{ + switch(key) { + case 27: + exit(0); + } +} + +bool bnstate[16]; +int prev_x, prev_y; + +void mouse(int bn, int state, int x, int y) +{ + int idx = bn - GLUT_LEFT_BUTTON; + + if(idx < (int)(sizeof bnstate / sizeof *bnstate)) { + bnstate[idx] = state == GLUT_DOWN; + } + prev_x = x; + prev_y = y; +} + +void motion(int x, int y) +{ + int dx = x - prev_x; + int dy = y - prev_y; + prev_x = x; + prev_y = y; + + if(bnstate[0]) { + cam_theta = fmod(cam_theta + dx * 0.5, 360.0); + cam_phi += dy * 0.5; + if(cam_phi < -90) { + cam_phi = -90; + } + if(cam_phi > 90) { + cam_phi = 90; + } + } + if(bnstate[2]) { + cam_dist += dy * 0.1; + if(cam_dist < 0) { + cam_dist = 0; + } + } +} + +struct render_target *create_rtarg(int xsz, int ysz) +{ + struct render_target *rt = new render_target; + + glGenFramebuffersEXT(1, &rt->fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER, rt->fbo); + + // create the render target texture + glGenTextures(1, &rt->color_tex); + glBindTexture(GL_TEXTURE_2D, rt->color_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color_tex, 0); + + // create depth buffer + glGenRenderbuffersEXT(1, &rt->depth_buf); + glBindRenderbufferEXT(GL_RENDERBUFFER, rt->depth_buf); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, xsz, ysz); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth_buf); + + if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "incomplete fbo\n"); + return 0; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + return rt; +} + +void destroy_rtarg(struct render_target *rt) +{ + if(!rt) { + return; + } + glDeleteFramebuffersEXT(1, &rt->fbo); + glDeleteTextures(1, &rt->color_tex); + glDeleteRenderbuffersEXT(1, &rt->depth_buf); + delete rt; +}