# HG changeset patch # User John Tsiombikas # Date 1348543177 -10800 # Node ID aa86119e32959f3f355f97b3305bee0bc195d700 # Parent b6bf86d4f1cfe0bd3e1735493c3d631dcdff4f7b added multipass deferred diff -r b6bf86d4f1cf -r aa86119e3295 prototype/Makefile.in --- a/prototype/Makefile.in Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/Makefile.in Tue Sep 25 06:19:37 2012 +0300 @@ -15,7 +15,7 @@ inc = -I. -Isrc -Ivmath -Idrawtext -Ikdtree `pkg-config --cflags freetype2` -CFLAGS = -pedantic $(warn) $(dbg) $(prof) $(opt) $(inc) +CFLAGS = -pedantic -fno-strict-aliasing $(warn) $(dbg) $(prof) $(opt) $(inc) CXXFLAGS = $(CFLAGS) $(cxx11_cflags) LDFLAGS = $(cxx11_ldflags) $(prof) $(libgl) $(libal) -lvorbisfile -lm -lassimp -limago -lpsys `pkg-config --libs freetype2` diff -r b6bf86d4f1cf -r aa86119e3295 prototype/data/test.level --- a/prototype/data/test.level Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/data/test.level Tue Sep 25 06:19:37 2012 +0300 @@ -17,7 +17,6 @@ ################################################################ ################################################################ ################################################################ -############################### ################################ ################################################################ ################################################################ ################################################################ @@ -29,9 +28,9 @@ ################################################################ ################################################################ ################################################################ -################################ ############################### -################################ ############# ################# ################################################################ +################################*############################### +################################*############################### ################################################################ ################################################################ ################################################################ @@ -63,3 +62,4 @@ ################################################################ ################################################################ ################################################################ +################################################################ diff -r b6bf86d4f1cf -r aa86119e3295 prototype/sdr/mrt.p.glsl --- a/prototype/sdr/mrt.p.glsl Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/sdr/mrt.p.glsl Tue Sep 25 06:19:37 2012 +0300 @@ -1,8 +1,8 @@ /* MRT assignments * 0 - RGB: position, A: shininess * 1 - RGB: normal - * 3 - RGB: diffuse color, A: shininess str. - * 4 - unused + * 2 - RGB: diffuse color, A: shininess str. + * 3 - unused */ uniform sampler2D tex_dif, tex_norm; diff -r b6bf86d4f1cf -r aa86119e3295 prototype/sdr/multi0.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/sdr/multi0.p.glsl Tue Sep 25 06:19:37 2012 +0300 @@ -0,0 +1,8 @@ +/* mutlipass renderer shader 0: RGB: position, A: shininess */ + +varying vec3 pos, norm, tang; + +void main() +{ + gl_FragColor = vec4(pos, gl_FrontMaterial.shininess); +} diff -r b6bf86d4f1cf -r aa86119e3295 prototype/sdr/multi1.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/sdr/multi1.p.glsl Tue Sep 25 06:19:37 2012 +0300 @@ -0,0 +1,23 @@ +/* multipass renderer shader 1: RGB: normal */ + +uniform sampler2D tex_norm; + +varying vec3 pos, norm, tang; + +void main() +{ + vec3 n = normalize(norm); + vec3 t = normalize(tang); + vec3 b = cross(n, t); + + mat3 tbn_mat = mat3( + t.x, t.y, t.z, + b.x, b.y, b.z, + n.x, n.y, n.z); + + // grab normal from the normal map, remap it and transform it to view space + n = texture2D(tex_norm, gl_TexCoord[0].st).xyz * 2.0 - 1.0; + n = normalize(tbn_mat * n); + + gl_FragColor = vec4(n, 0.0); +} diff -r b6bf86d4f1cf -r aa86119e3295 prototype/sdr/multi2.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/sdr/multi2.p.glsl Tue Sep 25 06:19:37 2012 +0300 @@ -0,0 +1,20 @@ +/* multipass renderer shader 2: RGB: diffuse color, A: shininess str. */ + +uniform sampler2D tex_dif; + +varying vec3 pos, norm, tang; + +const float fog_start = 3.0; +const float fog_end = 6.0; + +void main() +{ + float fog = clamp((fog_end + pos.z) / (fog_end - fog_start), 0.0, 1.0); + + vec4 texel = texture2D(tex_dif, gl_TexCoord[0].st); + vec3 diffuse = fog * (gl_FrontMaterial.diffuse * texel).xyz; + vec3 spec = fog * gl_FrontMaterial.specular.xyz; + float sstr = (spec.x + spec.y + spec.z) / 3.0; + + gl_FragColor = vec4(diffuse, sstr); +} diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/cfg.cc --- a/prototype/src/cfg.cc Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/cfg.cc Tue Sep 25 06:19:37 2012 +0300 @@ -7,13 +7,14 @@ Config::Config() { - width = 800; - height = 600; + width = 1280; + height = 800; stereo = false; sound = true; level_file = "0.level"; tileset_file = "default.tileset"; - use_deferred = true; + + rend = Renderer::any; } bool Config::parse_args(int argc, char **argv) @@ -33,17 +34,31 @@ level_file = argv[++i]; } else if(strcmp(argv[i], "-tileset") == 0) { tileset_file = argv[++i]; - } else if(strcmp(argv[i], "-no-deferred") == 0) { - use_deferred = false; + } else if(strcmp(argv[i], "-renderer") == 0) { + if(strcmp(argv[++i], "mrt") == 0) { + rend = Renderer::mrt; + } else if(strcmp(argv[i], "mp") == 0) { + rend = Renderer::multipass; + } else if(strcmp(argv[i], "fwd") == 0) { + rend = Renderer::fwd; + } else { + fprintf(stderr, "invalid renderer specified: %s\n", argv[i]); + return false; + } } 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(" -nosound disable sound output\n"); - printf(" -no-deferred disable deferred renderer\n"); - printf(" -h/-help print usage information and exit\n"); + 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(" -renderer specify which renderer to use\n"); + printf(" -stereo enable stereoscopic rendering\n"); + printf(" -nosound disable sound output\n"); + printf(" -h/-help print usage information and exit\n"); + printf("\n"); + printf("Renderers:\n"); + printf(" mrt - deferred renderer using multiple draw buffers\n"); + printf(" mp - multipass deferred renderer for each g-buffer\n"); + printf(" fwd - fallback forward renderer with simplistic lighting\n"); exit(0); } else { diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/cfg.h --- a/prototype/src/cfg.h Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/cfg.h Tue Sep 25 06:19:37 2012 +0300 @@ -1,13 +1,16 @@ #ifndef CFG_H_ #define CFG_H_ + + extern class Config { public: int width, height; bool stereo; bool sound; const char *level_file, *tileset_file; - bool use_deferred; + + enum class Renderer { any, mrt, multipass, fwd } rend; Config(); diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/light.cc --- a/prototype/src/light.cc Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/light.cc Tue Sep 25 06:19:37 2012 +0300 @@ -4,6 +4,8 @@ #include "renderer.h" #include "timer.h" +unsigned int PointLight::sph_vbo = 0; + Light::Light(const Color &col) : color(col) { @@ -159,6 +161,13 @@ bool PointLight::create_mesh() { + if(sph_vbo) { + vbo = sph_vbo; + return true; + } + + printf("building sphere mesh for point light drawing\n"); + const static int udiv = 8; const static int vdiv = 4; @@ -169,8 +178,8 @@ float du = 1.0 / (float)udiv; float dv = 1.0 / (float)vdiv; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); + glGenBuffers(1, &sph_vbo); + glBindBuffer(GL_ARRAY_BUFFER, sph_vbo); glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(Vector3), 0, GL_STATIC_DRAW); Vector3 *vptr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); @@ -191,6 +200,8 @@ } glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); + + vbo = sph_vbo; return true; } diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/light.h --- a/prototype/src/light.h Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/light.h Tue Sep 25 06:19:37 2012 +0300 @@ -36,6 +36,8 @@ float atten[3]; float radius; + static unsigned int sph_vbo; + bool create_mesh(); public: diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/main.cc --- a/prototype/src/main.cc Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/main.cc Tue Sep 25 06:19:37 2012 +0300 @@ -11,6 +11,7 @@ #include "tileset.h" #include "renderer.h" #include "renderer_deferred.h" +#include "renderer_multipass.h" #include "cmdcon.h" #include "cfg.h" #include "timer.h" @@ -117,15 +118,52 @@ } } - rend = new DeferredRenderer(); - if(!cfg.use_deferred || !rend->init(xsz, ysz)) { - printf("falling back to crappy renderer...\n"); + switch(cfg.rend) { + case Config::Renderer::mrt: + rend = new DeferredRenderer; + if(!rend->init(xsz, ysz)) { + fprintf(stderr, "failed to initialize deferred mrt renderer\n"); + delete rend; + return false; + } + break; - rend = new FwdRenderer(); + case Config::Renderer::multipass: + rend = new MultipassRenderer; if(!rend->init(xsz, ysz)) { - fprintf(stderr, "failed to create renderer\n"); + fprintf(stderr, "failed to initialize multipass deferred renderer\n"); + delete rend; return false; } + break; + + case Config::Renderer::fwd: + rend = new FwdRenderer; + if(!rend->init(xsz, ysz)) { + fprintf(stderr, "failed to initialize forward renderer\n"); + delete rend; + return false; + } + break; + + default: + // try each in turn falling back to progressively worse renderers + rend = new DeferredRenderer; + if(!rend->init(xsz, ysz)) { + printf("falling back to multipass renderer...\n"); + + delete rend; + rend = new MultipassRenderer(); + if(!rend->init(xsz, ysz)) { + printf("falling back to crappy renderer...\n"); + + rend = new FwdRenderer(); + if(!rend->init(xsz, ysz)) { + fprintf(stderr, "failed to create renderer\n"); + return false; + } + } + } } if(!init_cmdcon()) { diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/renderer_deferred.cc --- a/prototype/src/renderer_deferred.cc Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/renderer_deferred.cc Tue Sep 25 06:19:37 2012 +0300 @@ -22,6 +22,7 @@ mrt_prog = deferred_debug = deferred_omni = 0; curr_prog = 0; + num_draw_bufs = 1; } DeferredRenderer::~DeferredRenderer() @@ -65,6 +66,7 @@ fprintf(stderr, "%s: error: not enough draw buffers (%d), %d required\n", __func__, max_draw_buf, MRT_COUNT); return false; } + num_draw_bufs = MRT_COUNT; if(!create_fbo()) { return false; @@ -138,10 +140,17 @@ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); level->draw(); - glBindFramebufferEXT(GL_FRAMEBUFFER, 0); // post-process lighting + light_pass(level); + + glUseProgram(0); + curr_prog = 0; +} + +void DeferredRenderer::light_pass(const Level *level) const +{ glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT); glEnable(GL_BLEND); @@ -169,8 +178,6 @@ glDisable(GL_TEXTURE_2D); } - glUseProgram(0); - curr_prog = 0; glPopAttrib(); } @@ -211,18 +218,21 @@ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0); // attach to fbo - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, - GL_TEXTURE_2D, mrt_tex[i], 0); + GLenum color_att = num_draw_bufs >= MRT_COUNT ? GL_COLOR_ATTACHMENT0 + i : GL_COLOR_ATTACHMENT0; + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, color_att, GL_TEXTURE_2D, + mrt_tex[i], 0); CHECKGLERR; } - static GLenum draw_bufs[] = { - GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, - GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT, - GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT, - GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT - }; - glDrawBuffersARB(MRT_COUNT, draw_bufs); + if(num_draw_bufs >= MRT_COUNT) { + static GLenum draw_bufs[] = { + GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT, + GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT, + GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT + }; + glDrawBuffersARB(num_draw_bufs, draw_bufs); + } glGenRenderbuffersEXT(1, &rbuf_depth); glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth); diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/renderer_deferred.h --- a/prototype/src/renderer_deferred.h Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/renderer_deferred.h Tue Sep 25 06:19:37 2012 +0300 @@ -6,7 +6,7 @@ #define MRT_COUNT 3 class DeferredRenderer : public Renderer { -private: +protected: unsigned int fbo, rbuf_depth; unsigned int mrt_tex[MRT_COUNT]; int tex_xsz, tex_ysz; @@ -16,20 +16,24 @@ mutable unsigned int curr_prog; - bool create_fbo(); + int num_draw_bufs; + + virtual bool create_fbo(); public: DeferredRenderer(); - ~DeferredRenderer(); + virtual ~DeferredRenderer(); - bool init(int xsz, int ysz); + virtual bool init(int xsz, int ysz); - int get_tangent_location() const; - unsigned int get_current_program() const; + virtual int get_tangent_location() const; + virtual unsigned int get_current_program() const; - void resize(int xsz, int ysz); + virtual void resize(int xsz, int ysz); - void render(const Level *level) const; + virtual void render(const Level *level) const; + + virtual void light_pass(const Level *level) const; }; #endif // RENDERER_DEFERRED_H_ diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/renderer_multipass.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/src/renderer_multipass.cc Tue Sep 25 06:19:37 2012 +0300 @@ -0,0 +1,120 @@ +#include +#include +#include +#include "opengl.h" +#include "renderer_multipass.h" +#include "level.h" +#include "sdr.h" +#include "datapath.h" + +static unsigned int load_sdr(const char *vfname, const char *pfname); + + +MultipassRenderer::MultipassRenderer() +{ + for(int i=0; idraw(); + } + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + + // post-process lighting + light_pass(level); + + glUseProgram(0); + curr_prog = 0; +} + +static unsigned int load_sdr(const char *vfname, const char *pfname) +{ + char vsfile[PATH_MAX], psfile[PATH_MAX]; + const char *fname; + unsigned int prog; + + if((fname = datafile_path(vfname))) { + strcpy(vsfile, fname); + } else { + vsfile[0] = 0; + } + if((fname = datafile_path(pfname))) { + strcpy(psfile, fname); + } else { + psfile[0] = 0; + } + if(!(prog = create_program_load(vsfile, psfile))) { + fprintf(stderr, "failed to load shader program (%s, %s)\n", vsfile, psfile); + return 0; + } + return prog; +} diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/renderer_multipass.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/src/renderer_multipass.h Tue Sep 25 06:19:37 2012 +0300 @@ -0,0 +1,21 @@ +#ifndef RENDERER_MULTIPASS_H_ +#define RENDERER_MULTIPASS_H_ + +#include "renderer_deferred.h" + +class MultipassRenderer : public DeferredRenderer { +private: + unsigned int rt_prog[MRT_COUNT]; + +public: + MultipassRenderer(); + virtual ~MultipassRenderer(); + + virtual bool init(int xsz, int ysz); + + virtual int get_tangent_location() const; + + virtual void render(const Level *level) const; +}; + +#endif // RENDERER_MULTIPASS_H_ diff -r b6bf86d4f1cf -r aa86119e3295 prototype/src/tile.cc --- a/prototype/src/tile.cc Fri Sep 21 05:28:45 2012 +0300 +++ b/prototype/src/tile.cc Tue Sep 25 06:19:37 2012 +0300 @@ -141,8 +141,11 @@ void Tile::draw(unsigned int draw_mask) const { + int tang_loc = rend->get_tangent_location(); + for(size_t i=0; iset_attrib_location(MESH_ATTR_TANGENT, tang_loc); meshes[i]->draw(); } } @@ -152,6 +155,7 @@ { for(size_t i=0; idraw(); } } @@ -205,11 +209,6 @@ { int count = 0; - int attr_loc = rend->get_tangent_location(); - if(attr_loc == -1) { - fprintf(stderr, "warning: failed to retrieve tangent attribute location while loading tile\n"); - } - for(int i=0; i<(int)scn->mNumMeshes; i++) { // ignore any lines or other crap if(scn->mMeshes[i]->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { @@ -221,9 +220,6 @@ delete mesh; continue; } - if(attr_loc != -1) { - mesh->set_attrib_location(MESH_ATTR_TANGENT, attr_loc); - } Material mat; mat.load(scn->mMaterials[scn->mMeshes[i]->mMaterialIndex], tset->get_textures());