# HG changeset patch # User John Tsiombikas # Date 1345508268 -10800 # Node ID 5c41e6fcb3009a5fb6c4e24b6b1759c9372dc5ae # Parent d98240a13793a36108b0a26e284ab7416e567aa2 - commandline arguments - stereoscopic rendering - FBO fixed diff -r d98240a13793 -r 5c41e6fcb300 prototype/sdr/deferred.p.glsl --- a/prototype/sdr/deferred.p.glsl Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/sdr/deferred.p.glsl Tue Aug 21 03:17:48 2012 +0300 @@ -1,4 +1,8 @@ +uniform sampler2D mrt0; +uniform vec2 tex_scale; + void main() { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + vec4 texel0 = texture2D(mrt0, gl_TexCoord[0].st * tex_scale); + gl_FragColor = texel0; } diff -r d98240a13793 -r 5c41e6fcb300 prototype/sdr/deferred.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/sdr/deferred.v.glsl Tue Aug 21 03:17:48 2012 +0300 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff -r d98240a13793 -r 5c41e6fcb300 prototype/sdr/mrt.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/sdr/mrt.v.glsl Tue Aug 21 03:17:48 2012 +0300 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/camera.cc --- a/prototype/src/camera.cc Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/src/camera.cc Tue Aug 21 03:17:48 2012 +0300 @@ -15,25 +15,6 @@ *mat = matrix().inverse(); } -void Camera::set_glmat(const Matrix4x4 &mat) const -{ -#ifdef SINGLE_PRECISION_MATH - if(glLoadTransposeMatrixfARB) { - glLoadTransposeMatrixfARB((float*)&mat); - } else { - Matrix4x4 tmat = mat.transposed(); - glLoadMatrixf((float*)&tmat); - } -#else - if(glLoadTransposeMatrixdARB) { - glLoadTransposeMatrixdARB((double*)&mat); - } else { - Matrix4x4 tmat = mat.transposed(); - glLoadMatrixd((double*)&tmat); - } -#endif -} - const Matrix4x4 &Camera::matrix() const { if(!mcache.valid) { @@ -54,12 +35,12 @@ void Camera::use() const { - set_glmat(matrix()); + mult_matrix(matrix()); } void Camera::use_inverse() const { - set_glmat(inv_matrix()); + mult_matrix(inv_matrix()); } void Camera::input_move(float x, float y, float z) diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/cfg.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/src/cfg.cc Tue Aug 21 03:17:48 2012 +0300 @@ -0,0 +1,46 @@ +#include +#include +#include +#include "cfg.h" + +Config cfg; + +Config::Config() +{ + width = 800; + height = 600; + stereo = false; + level_file = "0.level"; + tileset_file = "default.tileset"; +} + +bool Config::parse_args(int argc, char **argv) +{ + for(int i=1; ix\n"); + return false; + } + } else if(strcmp(argv[i], "-stereo") == 0) { + stereo = true; + } else if(strcmp(argv[i], "-level") == 0) { + level_file = argv[++i]; + } else if(strcmp(argv[i], "-tileset") == 0) { + tileset_file = argv[++i]; + } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { + printf("Usage: %s [options]\n", argv[0]); + printf(" -s WxH window size (resolution)\n"); + printf(" -level specify which level file to load\n"); + printf(" -tileset specify which tileset to use\n"); + printf(" -stereo enable stereoscopic rendering\n"); + printf(" -h/-help print usage information and exit\n"); + exit(0); + + } else { + fprintf(stderr, "unrecognized argument: %s\n", argv[i]); + return false; + } + } + return true; +} diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/cfg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/src/cfg.h Tue Aug 21 03:17:48 2012 +0300 @@ -0,0 +1,15 @@ +#ifndef CFG_H_ +#define CFG_H_ + +extern class Config { +public: + int width, height; + bool stereo; + const char *level_file, *tileset_file; + + Config(); + + bool parse_args(int argc, char **argv); +} cfg; + +#endif // CFG_H_ diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/main.cc --- a/prototype/src/main.cc Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/src/main.cc Tue Aug 21 03:17:48 2012 +0300 @@ -8,12 +8,15 @@ #include "datapath.h" #include "tileset.h" #include "renderer.h" +#include "cfg.h" bool init(int xsz, int ysz); void cleanup(); void idle(); void disp(); void draw(); +void view_matrix(int eye); +void proj_matrix(int eye); void update(unsigned long msec); void reshape(int x, int y); void keyb(unsigned char key, int x, int y); @@ -27,23 +30,21 @@ static FpsCamera cam; static bool keystate[256]; -static const char *level_file = "0.level"; +static float stereo_focus_dist = 0.25; +static float stereo_eye_sep = stereo_focus_dist / 30.0; + int main(int argc, char **argv) { - int xsz, ysz; - glutInit(&argc, argv); - if(argc > 1) { - level_file = argv[1]; + if(!cfg.parse_args(argc, argv)) { + return 1; } - glutInitWindowSize(800, 600); - glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE); - glutCreateWindow("prototype"); - xsz = glutGet(GLUT_WINDOW_WIDTH); - ysz = glutGet(GLUT_WINDOW_HEIGHT); + glutInitWindowSize(cfg.width, cfg.height); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (cfg.stereo ? GLUT_STEREO : 0)); + glutCreateWindow("dungeon crawler prototype"); glutIdleFunc(idle); glutDisplayFunc(disp); @@ -55,7 +56,7 @@ glewInit(); - if(!init(xsz, ysz)) { + if(!init(cfg.width, cfg.height)) { return 1; } @@ -83,14 +84,15 @@ // load a tileset tileset = new TileSet; - if(!tileset->load(datafile_path("default.tileset"))) { + printf("loading tileset: %s\n", cfg.tileset_file); + if(!tileset->load(datafile_path(cfg.tileset_file))) { return false; } set_active_tileset(tileset); level = new Level; - printf("loading level: %s\n", level_file); - if(!level->load(datafile_path(level_file))) { + printf("loading level: %s\n", cfg.level_file); + if(!level->load(datafile_path(cfg.level_file))) { return false; } @@ -116,13 +118,39 @@ { update(glutGet(GLUT_ELAPSED_TIME)); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if(cfg.stereo) { + glDrawBuffer(GL_BACK_LEFT); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - cam.use_inverse(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + proj_matrix(-1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + view_matrix(-1); - render_deferred(draw); + render_deferred(draw); + + glDrawBuffer(GL_BACK_RIGHT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + proj_matrix(1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + view_matrix(1); + + render_deferred(draw); + + } else { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + proj_matrix(0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + view_matrix(0); + + render_deferred(draw); + } glutSwapBuffers(); assert(glGetError() == GL_NO_ERROR); @@ -132,9 +160,31 @@ void draw() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); level->draw(); } +void view_matrix(int eye) +{ + float offs = stereo_eye_sep * eye * 0.5; + glTranslatef(-offs, 0, 0); + cam.use_inverse(); +} + +void proj_matrix(int eye) +{ + static const float fov = M_PI / 4.0; + static const float near_clip = 0.1; + static const float far_clip = 100.0; + + float top = near_clip * tan(fov * 0.5); + float right = top * (float)cfg.width / (float)cfg.height; + + float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist); + glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip); +} + + void update(unsigned long msec) { static unsigned long last_upd; @@ -169,16 +219,39 @@ void reshape(int x, int y) { glViewport(0, 0, x, y); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(45.0, (float)x / (float)y, 0.25, 100.0); + cfg.width = x; + cfg.height = y; } +static bool stereo_shift_pressed; + void keyb(unsigned char key, int x, int y) { switch(key) { case 27: exit(0); + + case 'z': + stereo_shift_pressed = true; + break; + + case '\n': + case '\r': + { + static bool fullscr; + if(glutGetModifiers() & GLUT_ACTIVE_ALT) { + fullscr = !fullscr; + if(fullscr) { + glutFullScreen(); + } else { + glutPositionWindow(20, 20); + } + } + } + break; + + default: + break; } keystate[key] = true; @@ -186,6 +259,15 @@ void key_release(unsigned char key, int x, int y) { + switch(key) { + case 'z': + stereo_shift_pressed = false; + break; + + default: + break; + } + keystate[key] = false; } @@ -206,6 +288,16 @@ prev_x = x; prev_y = y; + if(stereo_shift_pressed) { + if(dy != 0) { + stereo_focus_dist += dy * 0.01; + stereo_eye_sep = stereo_focus_dist / 30.0; + printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep); + glutPostRedisplay(); + } + return; + } + if(bnstate[0]) { cam.input_rotate(dy * 0.01, dx * 0.01, 0); glutPostRedisplay(); diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/opengl.cc --- a/prototype/src/opengl.cc Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/src/opengl.cc Tue Aug 21 03:17:48 2012 +0300 @@ -38,3 +38,24 @@ } #endif } + +const char *strglerr(int err) +{ + static const char *errnames[] = { + "GL_INVALID_ENUM", + "GL_INVALID_VALUE", + "GL_INVALID_OPERATION", + "GL_STACK_OVERFLOW", + "GL_STACK_UNDERFLOW", + "GL_OUT_OF_MEMORY", + "GL_INVALID_FRAMEBUFFER_OPERATION" + }; + + if(!err) { + return "GL_NO_ERROR"; + } + if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) { + return ""; + } + return errnames[err - GL_INVALID_ENUM]; +} diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/opengl.h --- a/prototype/src/opengl.h Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/src/opengl.h Tue Aug 21 03:17:48 2012 +0300 @@ -9,9 +9,21 @@ #include #endif +#define CHECKGLERR \ + do { \ + int err = glGetError(); \ + if(err) { \ + fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \ + abort(); \ + } \ + } while(0) + + class Matrix4x4; void load_matrix(const Matrix4x4 &m); void mult_matrix(const Matrix4x4 &m); +const char *strglerr(int err); + #endif /* OPENGL_H_ */ diff -r d98240a13793 -r 5c41e6fcb300 prototype/src/renderer.cc --- a/prototype/src/renderer.cc Mon Aug 20 06:11:58 2012 +0300 +++ b/prototype/src/renderer.cc Tue Aug 21 03:17:48 2012 +0300 @@ -2,21 +2,23 @@ #include #include #include +#include #include "opengl.h" #include "renderer.h" #include "sdr.h" #include "datapath.h" + static bool create_fbo(int xsz, int ysz); -static bool load_shaders(); +static unsigned int load_sdr(const char *vfname, const char *pfname); static int round_pow2(int x); -#define MRT_COUNT 4 +#define MRT_COUNT 1 static unsigned int mrt_tex[MRT_COUNT]; static unsigned int mrt_prog; -static unsigned int deferred_omni; +static unsigned int deferred_omni, deferred_debug; static unsigned int fbo, rbuf_depth; static const char *fbstname[] = { @@ -38,7 +40,11 @@ if(!create_fbo(xsz, ysz)) { return false; } - if(!load_shaders()) { + + if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) { + return false; + } + if(!(deferred_debug = load_sdr("deferred.v.glsl", "deferred.p.glsl"))) { return false; } return true; @@ -55,9 +61,45 @@ void render_deferred(void (*draw_func)()) { - bind_program(mrt_prog); + int loc; + + // render into the MRT buffers + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + glUseProgram(mrt_prog); draw_func(); - bind_program(0); + glUseProgram(0); + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + + + // post-process lighting + glPushAttrib(GL_ENABLE_BIT); + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, mrt_tex[0]); + glEnable(GL_TEXTURE_2D); + + glUseProgram(deferred_debug); + if((loc = glGetUniformLocation(deferred_debug, "tex0")) != -1) { + glUniform1i(loc, 0); + } + if((loc = glGetUniformLocation(deferred_debug, "tex_scale")) != -1) { + glUniform2f(loc, (float)fb_xsz / tex_xsz, (float)fb_ysz / tex_ysz); + } + + 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(); + + glUseProgram(0); + glPopAttrib(); } static bool create_fbo(int xsz, int ysz) @@ -74,11 +116,7 @@ return false; } glGenFramebuffersEXT(1, &fbo); - - glGenRenderbuffersEXT(1, &rbuf_depth); - glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth); - glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth); + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); glGenTextures(MRT_COUNT, mrt_tex); for(int i=0; i