# HG changeset patch # User John Tsiombikas # Date 1379730168 -10800 # Node ID f3672317e5c2013fd80a92f042b6250c352334c6 # Parent 402cbb6d9ce31a38ad8018251b3e98dae0d0e080 made teapots many sizes and more colorful, added phong shader diff -r 402cbb6d9ce3 -r f3672317e5c2 Makefile --- a/Makefile Sat Sep 21 04:15:20 2013 +0300 +++ b/Makefile Sat Sep 21 05:22:48 2013 +0300 @@ -1,12 +1,13 @@ -src = $(wildcard src/*.cc) +ccsrc = $(wildcard src/*.cc) +csrc = $(wildcard src/*.c) ovr_src = $(wildcard libovr/Src/*.cpp) \ $(wildcard libovr/Src/Kernel/*.cpp) \ $(wildcard libovr/Src/Util/*.cpp) -obj = $(src:.cc=.o) $(ovr_src:.cpp=.o) $(ovr_sys_src:.cpp=.o) +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) $(ovr_src:.cpp=.o) $(ovr_sys_src:.cpp=.o) bin = oculus1 - +CFLAGS = -pedantic -Wall -g CXXFLAGS = -Wall -g -I/usr/local/include $(ovr_include) -DUSE_OVR LDFLAGS = -L/usr/local/lib $(libgl) $(ovrlibs) -lvmath -lm diff -r 402cbb6d9ce3 -r f3672317e5c2 sdr.glsl --- a/sdr.glsl Sat Sep 21 04:15:20 2013 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -uniform sampler2D tex; -uniform float aspect, scale; -uniform float lens_center_offset; -uniform vec4 dist_factors; - -vec2 distort_texcoords(in vec2 tc); -float barrel_scale(float x, in vec4 k); - -void main() -{ - vec2 tc = distort_texcoords(gl_TexCoord[0].xy); - - float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0; - - gl_FragColor.rgb = texture2D(tex, tc).rgb * vis; - gl_FragColor.a = 1.0; -} - -vec2 distort_texcoords(in vec2 tc) -{ - // map tc [0, 1] -> [-1, 1] - vec2 pt = tc * 2.0 - 1.0; - - pt.x += lens_center_offset * 2.0; - pt.y /= aspect; // correct for aspect ratio - - float rad = barrel_scale(dot(pt, pt), dist_factors); - pt *= rad; // scale the point by the computer distortion radius - - pt /= scale; - pt.y *= aspect; - pt.x -= lens_center_offset * 2.0; - - // map back to range [0, 1] - return pt * 0.5 + 0.5; -} - -float barrel_scale(float rad, in vec4 k) -{ - float radsq = rad * rad; - float radquad = radsq * radsq; - return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq; -} diff -r 402cbb6d9ce3 -r f3672317e5c2 sdr/phong.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/phong.p.glsl Sat Sep 21 05:22:48 2013 +0300 @@ -0,0 +1,19 @@ +varying vec3 vpos, norm, ldir; + +void main() +{ + vec3 v = -normalize(vpos); + vec3 n = normalize(norm); + vec3 l = normalize(ldir); + vec3 h = normalize(v + l); + + float ndotl = max(dot(n, l), 0.0); + float ndoth = max(dot(n, h), 0.0); + + vec3 diff = gl_FrontMaterial.diffuse.rgb * gl_LightSource[0].diffuse.rgb * ndotl; + vec3 spec = gl_FrontMaterial.specular.rgb * gl_LightSource[0].specular.rgb * + pow(ndoth, gl_FrontMaterial.shininess); + + gl_FragColor.rgb = diff + spec; + gl_FragColor.a = 1.0; +} diff -r 402cbb6d9ce3 -r f3672317e5c2 sdr/phong.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/phong.v.glsl Sat Sep 21 05:22:48 2013 +0300 @@ -0,0 +1,11 @@ +varying vec3 vpos, norm, ldir; + +void main() +{ + gl_Position = ftransform(); + + vpos = (gl_ModelViewMatrix * gl_Vertex).xyz; + norm = gl_NormalMatrix * gl_Normal; + + ldir = gl_LightSource[0].position.xyz - vpos; +} diff -r 402cbb6d9ce3 -r f3672317e5c2 sdr/sdr.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/sdr.glsl Sat Sep 21 05:22:48 2013 +0300 @@ -0,0 +1,43 @@ +uniform sampler2D tex; +uniform float aspect, scale; +uniform float lens_center_offset; +uniform vec4 dist_factors; + +vec2 distort_texcoords(in vec2 tc); +float barrel_scale(float x, in vec4 k); + +void main() +{ + vec2 tc = distort_texcoords(gl_TexCoord[0].xy); + + float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0; + + gl_FragColor.rgb = texture2D(tex, tc).rgb * vis; + gl_FragColor.a = 1.0; +} + +vec2 distort_texcoords(in vec2 tc) +{ + // map tc [0, 1] -> [-1, 1] + vec2 pt = tc * 2.0 - 1.0; + + pt.x += lens_center_offset * 2.0; + pt.y /= aspect; // correct for aspect ratio + + float rad = barrel_scale(dot(pt, pt), dist_factors); + pt *= rad; // scale the point by the computer distortion radius + + pt /= scale; + pt.y *= aspect; + pt.x -= lens_center_offset * 2.0; + + // map back to range [0, 1] + return pt * 0.5 + 0.5; +} + +float barrel_scale(float rad, in vec4 k) +{ + float radsq = rad * rad; + float radquad = radsq * radsq; + return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq; +} diff -r 402cbb6d9ce3 -r f3672317e5c2 src/main.cc --- a/src/main.cc Sat Sep 21 04:15:20 2013 +0300 +++ b/src/main.cc Sat Sep 21 05:22:48 2013 +0300 @@ -5,14 +5,18 @@ #include "opengl.h" #include "vr.h" #include "camera.h" +#include "sdr.h" static bool init(); static void cleanup(); static void disp(); +static void disp_vr(); static void draw_scene(); -static void draw_teapot(); +static void draw_teapot(float size); static void draw_squares(); static void draw_grid(float size, float spacing); +static void toggle_mouselook(); +static void toggle_fullscreen(); static void idle(); static void reshape(int x, int y); static void keyb(unsigned char key, int x, int y); @@ -26,13 +30,16 @@ static VRFpsCamera cam; static int width, height; static bool use_vr = false; -static bool mouselook = false; static bool keystate[256]; static int rtarg_width, rtarg_height; static unsigned int fbo, tex[2], zbuf; +static unsigned int teapot_sdr; + +static bool fullscreen_pending; + int main(int argc, char **argv) { glutInitWindowSize(1280, 800); @@ -48,7 +55,7 @@ width = glutGet(GLUT_WINDOW_WIDTH); height = glutGet(GLUT_WINDOW_HEIGHT); - glutDisplayFunc(disp); + glutDisplayFunc(use_vr ? disp_vr : disp); glutIdleFunc(idle); glutReshapeFunc(reshape); glutKeyboardFunc(keyb); @@ -76,6 +83,7 @@ glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); + glEnable(GL_NORMALIZE); // y = height of neck cam.input_move(0, 1.65, 0); @@ -93,39 +101,38 @@ rtarg_width = (xsz + xsz / 2) / 2; rtarg_height = ysz + ysz / 2; - } else { - rtarg_width = width; - rtarg_height = height; + + printf("render target: %dx%d\n", rtarg_width, rtarg_height); + + // create render targets for each eye + GLenum wrap_mode = GL_CLAMP_TO_EDGE; + if(!GLEW_SGIS_texture_edge_clamp) { + wrap_mode = GL_CLAMP; + } + + glGenTextures(2, tex); + for(int i=0; i<2; i++) { + glBindTexture(GL_TEXTURE_2D, tex[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + } + + // create the depth render buffer + glGenRenderbuffers(1, &zbuf); + glBindRenderbuffer(GL_RENDERBUFFER, zbuf); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height); + + // create the FBO + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf); } - printf("render target: %dx%d\n", rtarg_width, rtarg_height); - - // create render targets for each eye - GLenum wrap_mode = GL_CLAMP_TO_EDGE; - if(!GLEW_SGIS_texture_edge_clamp) { - wrap_mode = GL_CLAMP; - } - - glGenTextures(2, tex); - for(int i=0; i<2; i++) { - glBindTexture(GL_TEXTURE_2D, tex[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - } - - // create the depth render buffer - glGenRenderbuffers(1, &zbuf); - glBindRenderbuffer(GL_RENDERBUFFER, zbuf); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height); - - // create the FBO - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf); + teapot_sdr = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl"); return true; } @@ -159,6 +166,7 @@ cam.input_move(inpv.x, inpv.y, inpv.z); } +// display function used in regular mode static void disp() { static long prev_msec; @@ -167,12 +175,33 @@ prev_msec = msec; handle_input(dt); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, (float)width / (float)height, 0.25, 500.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + cam.use_inverse(); + draw_scene(); + + glutSwapBuffers(); + assert(glGetError() == GL_NO_ERROR); +} + +// display function used in VR mode +static void disp_vr() +{ + static long prev_msec; + long msec = glutGet(GLUT_ELAPSED_TIME); + float dt = (msec - prev_msec) / 1000.0; + prev_msec = msec; + + handle_input(dt); cam.track_vr(); - /*glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - float fov = RAD_TO_DEG(vr_get_fov()); - gluPerspective(fov, (float)rtarg_width / (float)rtarg_height, 0.25, 500.0);*/ float proj_matrix[16]; float eye_dist = vr_get_eyedist(); @@ -230,7 +259,6 @@ glFinish(); } - static void draw_scene() { float lpos[] = {0, 60, 0, 1}; @@ -238,21 +266,33 @@ draw_grid(50.0, 2.5); - static Vector2 teapos[] = { - Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8) + static const Vector2 teapos[] = { + Vector2(-8, -8), Vector2(8, -8), Vector2(8, 8), Vector2(-8, 8) }; + static const float teasize[] = { 1.0, 2.0, 1.7, 1.4 }; + static const float teacolor[][4] = { + {1.0, 0.4, 0.2, 1.0}, {0.2, 0.35, 1.0, 1.0}, {1.0, 0.9, 0.3, 1.0}, {0.3, 1.0, 0.4, 1.0} + }; + static const float spec[] = {0.8, 0.8, 0.8, 1.0}; + + glUseProgram(teapot_sdr); for(int i=0; i<4; i++) { + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, teacolor[i]); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.0); + glPushMatrix(); glTranslatef(teapos[i].x, 0, teapos[i].y); - draw_teapot(); + draw_teapot(teasize[i]); glPopMatrix(); } + glUseProgram(0); draw_squares(); } -static void draw_teapot() +static void draw_teapot(float size) { static int tealist; @@ -263,9 +303,16 @@ glEndList(); } + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glScalef(size, size, size); + glTranslatef(0, 0.73, 0); + glFrontFace(GL_CW); glCallList(tealist); glFrontFace(GL_CCW); + + glPopMatrix(); } static void draw_squares() @@ -338,8 +385,82 @@ glPopAttrib(); } +static bool mouselook; + +static void toggle_mouselook() +{ + mouselook = !mouselook; + if(mouselook) { + glutPassiveMotionFunc(passive); + glutSetCursor(GLUT_CURSOR_NONE); + glutWarpPointer(width / 2, height / 2); + } else { + glutPassiveMotionFunc(0); + glutSetCursor(GLUT_CURSOR_INHERIT); + } +} + +static void toggle_fullscreen() +{ + static bool fullscreen; + static int prev_x, prev_y; + static int prev_xsz, prev_ysz; + + fullscreen = !fullscreen; + + if(fullscreen) { + prev_x = glutGet(GLUT_WINDOW_X); + prev_y = glutGet(GLUT_WINDOW_Y); + prev_xsz = width; + prev_ysz = height; + + if(use_vr) { + // go fullscreen to the correct monitor + int x, y; + vr_get_display_pos(&x, &y); + glutPositionWindow(x, y); + + // also warp the mouse and enable mouselook + glutWarpPointer(x + width / 2, y + height / 2); + + /* Ok this next line needs some explanation: + * glutPositionWindow, doesn't necessarilly get executed directly. + * GLUT might defer it for the next round of event processing, just + * so that it may coalesce multiple positioning requests. + * However that means that if we just called glutFullScreen right + * here, the window manager would have no idea that the window will + * move to another monitor, thus making it the size of the monitor + * it occupied before the move. + * So I'm setting a flag here, and execute the glutFullScreen call + * at the next idle invocation. (would display be a safer place?). + */ + fullscreen_pending = true; + } else { + glutFullScreen(); + toggle_mouselook(); + } + } else { + glutReshapeWindow(prev_xsz, prev_ysz); + glutPositionWindow(prev_x, prev_y); + + if(mouselook) { + toggle_mouselook(); + } + } + glutPostRedisplay(); +} + + static void idle() { + if(fullscreen_pending) { + glutFullScreen(); + + if(!mouselook) { + toggle_mouselook(); + } + fullscreen_pending = false; + } glutPostRedisplay(); } @@ -362,33 +483,11 @@ exit(0); case 'm': - mouselook = !mouselook; - if(mouselook) { - glutPassiveMotionFunc(passive); - glutSetCursor(GLUT_CURSOR_NONE); - glutWarpPointer(width / 2, height / 2); - } else { - glutPassiveMotionFunc(0); - glutSetCursor(GLUT_CURSOR_INHERIT); - } + toggle_mouselook(); break; case 'f': - { - static bool fullscreen; - static int prev_xsz, prev_ysz; - - fullscreen = !fullscreen; - - if(fullscreen) { - prev_xsz = width; - prev_ysz = height; - glutFullScreen(); - } else { - glutReshapeWindow(prev_xsz, prev_ysz); - } - glutPostRedisplay(); - } + toggle_fullscreen(); break; } diff -r 402cbb6d9ce3 -r f3672317e5c2 src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Sat Sep 21 05:22:48 2013 +0300 @@ -0,0 +1,427 @@ +/* +Printblobs - halftoning display hack +Copyright (C) 2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#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 402cbb6d9ce3 -r f3672317e5c2 src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Sat Sep 21 05:22:48 2013 +0300 @@ -0,0 +1,76 @@ +/* +Printblobs - halftoning display hack +Copyright (C) 2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#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 402cbb6d9ce3 -r f3672317e5c2 src/vr.cc --- a/src/vr.cc Sat Sep 21 04:15:20 2013 +0300 +++ b/src/vr.cc Sat Sep 21 05:22:48 2013 +0300 @@ -98,9 +98,15 @@ float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5; vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize; - // grab the display name + // grab the display info vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1]; strcpy(vr_ctx.info.display, info.DisplayDeviceName); + + vr_ctx.info.display_xoffs = info.DesktopX; + vr_ctx.info.display_yoffs = info.DesktopY; + + printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display, + vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs); } // get the sensor device @@ -209,6 +215,17 @@ return true; } +extern "C" const char *vr_get_display_name(void) +{ + return vr_ctx.info.display; +} + +extern "C" void vr_get_display_pos(int *xptr, int *yptr) +{ + *xptr = vr_ctx.info.display_xoffs; + *yptr = vr_ctx.info.display_yoffs; +} + extern "C" int vr_get_width(void) { return vr_ctx.info.width; diff -r 402cbb6d9ce3 -r f3672317e5c2 src/vr.h --- a/src/vr.h Sat Sep 21 04:15:20 2013 +0300 +++ b/src/vr.h Sat Sep 21 05:22:48 2013 +0300 @@ -22,6 +22,9 @@ int vr_init(enum vr_init_mode mode); void vr_shutdown(void); +const char *vr_get_display_name(void); +void vr_get_display_pos(int *xptr, int *yptr); + int vr_get_width(void); int vr_get_height(void); diff -r 402cbb6d9ce3 -r f3672317e5c2 src/vr_impl.h --- a/src/vr_impl.h Sat Sep 21 04:15:20 2013 +0300 +++ b/src/vr_impl.h Sat Sep 21 05:22:48 2013 +0300 @@ -13,6 +13,8 @@ struct { char *display; + int display_xoffs, display_yoffs; + // the full width and height of the display (both eyes) int width, height; float fov;