# HG changeset patch # User John Tsiombikas # Date 1350603957 -10800 # Node ID a27528035e2082ee1fe8103459062143a1afff6c # Parent e198e94435c87723fcbb8268c954d4503c9875b5 - re-organized the renderer classes a bit wrt final render-target - implemented identity color-grading palette for now - broke particle systems.... - removed multipass renderer diff -r e198e94435c8 -r a27528035e20 prototype/sdr/post.p.glsl --- a/prototype/sdr/post.p.glsl Tue Oct 16 04:08:35 2012 +0300 +++ b/prototype/sdr/post.p.glsl Fri Oct 19 02:45:57 2012 +0300 @@ -1,6 +1,10 @@ uniform sampler2D fbtex; +uniform sampler3D paltex; void main() { - gl_FragColor = texture2D(fbtex, gl_TexCoord[0].st); + // lookup the render output color for this pixel + vec4 color = texture2D(fbtex, gl_TexCoord[0].st); + // use that color as an index into the palette + gl_FragColor = vec4(texture3D(paltex, color.xyz).xyz, color.a); } diff -r e198e94435c8 -r a27528035e20 prototype/src/colgrade.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prototype/src/colgrade.cc Fri Oct 19 02:45:57 2012 +0300 @@ -0,0 +1,74 @@ +#include +#include "opengl.h" +#include "colgrade.h" + +GradePalette::GradePalette() +{ + tex = 0; +} + +GradePalette::~GradePalette() +{ + destroy(); +} + +bool GradePalette::create(int sz) +{ + unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP; + + destroy(); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_3D, tex); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, clamp); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, clamp); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, clamp); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, sz, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + unsigned char *scanline = new unsigned char[sz * 3]; + + size = sz; + for(int i=0; iinit(xsz, ysz)) { - 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)) { @@ -152,15 +142,10 @@ printf("falling back to multipass renderer...\n"); delete rend; - rend = new MultipassRenderer(); + rend = new FwdRenderer(); 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; - } + fprintf(stderr, "failed to create renderer\n"); + return false; } } } diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer.cc --- a/prototype/src/renderer.cc Tue Oct 16 04:08:35 2012 +0300 +++ b/prototype/src/renderer.cc Fri Oct 19 02:45:57 2012 +0300 @@ -6,17 +6,34 @@ #include "datapath.h" static unsigned int load_sdr(const char *vfname, const char *pfname); +static int round_pow2(int x); Renderer *rend; Renderer::Renderer() { + fbo = 0; + rend_tex = rend_depth = 0; width = height = 0; + tex_xsz = tex_ysz = 0; + post_sdr = 0; } Renderer::~Renderer() { + if(post_sdr) { + free_program(post_sdr); + } + if(rend_tex) { + glDeleteTextures(1, &rend_tex); + } + if(rend_depth) { + glDeleteRenderbuffersEXT(1, &rend_depth); + } + if(fbo) { + glDeleteFramebuffersEXT(1, &fbo); + } } bool Renderer::init(int xsz, int ysz) @@ -24,6 +41,18 @@ width = xsz; height = ysz; + if(!create_rtarg()) { + return false; + } + + if(!(post_sdr = load_sdr("post.v.glsl", "post.p.glsl"))) { + return false; + } + + if(!gradepal.create()) { + return false; + } + rend = this; return true; } @@ -42,6 +71,20 @@ { width = xsz; height = ysz; + + // if we need a bigger rendertarget ... + if(xsz > tex_xsz || ysz > tex_ysz) { + tex_xsz = round_pow2(xsz); + tex_ysz = round_pow2(ysz); + + // ... resize the render target + glBindTexture(GL_TEXTURE_2D, rend_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + // ... resize the depth buffer + glBindRenderbufferEXT(GL_RENDERBUFFER, rend_depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz); + } } void Renderer::render_pre(const Level *level) const @@ -51,11 +94,106 @@ glFogf(GL_FOG_START, 3.0f); glFogf(GL_FOG_END, 6.0f); // TODO level->draw_pre(); + + // bind the render target + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rend_tex, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + CHECKGLERR; } void Renderer::render_post(const Level *level) const { level->draw_post(); + CHECKGLERR; + + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + + // draw the rendered output + glActiveTextureARB(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rend_tex); + glEnable(GL_TEXTURE_2D); + + // use the color-grading palette + glActiveTextureARB(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_3D, gradepal.get_texture()); + glEnable(GL_TEXTURE_3D); + + glUseProgram(post_sdr); + set_uniform_int(post_sdr, "fbtex", 0); + set_uniform_int(post_sdr, "paltex", 1); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f((float)width / tex_xsz, 0); + glVertex2f(1, -1); + glTexCoord2f((float)width / tex_xsz, (float)height / tex_ysz); + glVertex2f(1, 1); + glTexCoord2f(0, (float)height / tex_ysz); + glVertex2f(-1, 1); + glEnd(); + glUseProgram(0); + + glActiveTextureARB(GL_TEXTURE0); + + CHECKGLERR; +} + +static const char *fbstname[] = { + "GL_FRAMEBUFFER_COMPLETE", + "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT", + "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT", + "no such fbo error", + "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS", + "GL_FRAMEBUFFER_INCOMPLETE_FORMATS", + "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER", + "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER", + "GL_FRAMEBUFFER_UNSUPPORTED" +}; + +bool Renderer::create_rtarg() +{ + unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP; + + tex_xsz = round_pow2(width); + tex_ysz = round_pow2(height); + + if(!glGenFramebuffersEXT) { + fprintf(stderr, "FBO support missing!\n"); + return false; + } + glGenFramebuffersEXT(1, &fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + + // create the render target + glGenTextures(1, &rend_tex); + glBindTexture(GL_TEXTURE_2D, rend_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp); + 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_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rend_tex, 0); + + // create depth buffer + glGenRenderbuffersEXT(1, &rend_depth); + glBindRenderbufferEXT(GL_RENDERBUFFER, rend_depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rend_depth); + + int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + if(fbst != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]); + return false; + } + CHECKGLERR; + + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + return true; } @@ -75,8 +213,9 @@ bool FwdRenderer::init(int xsz, int ysz) { - width = xsz; - height = ysz; + if(!Renderer::init(xsz, ysz)) { + return false; + } if(glUseProgram && (sdrprog = load_sdr("fallback.v.glsl", "fallback.p.glsl"))) { tang_attr = get_attrib_loc(sdrprog, "attr_tangent"); @@ -128,3 +267,15 @@ } return prog; } + +static int round_pow2(int x) +{ + x--; + x = (x >> 1) | x; + x = (x >> 2) | x; + x = (x >> 4) | x; + x = (x >> 8) | x; + x = (x >> 16) | x; + return x + 1; +} + diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer.h --- a/prototype/src/renderer.h Tue Oct 16 04:08:35 2012 +0300 +++ b/prototype/src/renderer.h Fri Oct 19 02:45:57 2012 +0300 @@ -1,11 +1,22 @@ #ifndef RENDERER_H_ #define RENDERER_H_ +#include "colgrade.h" + class Level; class Renderer { protected: + // render target + unsigned int fbo; + unsigned int rend_tex, rend_depth; int width, height; + int tex_xsz, tex_ysz; + + GradePalette gradepal; + unsigned int post_sdr; + + virtual bool create_rtarg(); public: Renderer(); diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer_deferred.cc --- a/prototype/src/renderer_deferred.cc Tue Oct 16 04:08:35 2012 +0300 +++ b/prototype/src/renderer_deferred.cc Fri Oct 19 02:45:57 2012 +0300 @@ -10,17 +10,14 @@ static unsigned int load_sdr(const char *vfname, const char *pfname); static void attach_color_buffer(unsigned int fbo, int count, const unsigned int *tex); -static int round_pow2(int x); DeferredRenderer::DeferredRenderer() { - fbo = rbuf_depth = rend_tex = 0; + fbo = 0; for(int i=0; i tex_xsz || ysz > tex_ysz) { - tex_xsz = round_pow2(xsz); - tex_ysz = round_pow2(ysz); - + if(xsz > prev_tex_xsz || ysz > prev_tex_ysz) { // ... resize all the color buffers for(int i=0; i> 1) | x; - x = (x >> 2) | x; - x = (x >> 4) | x; - x = (x >> 8) | x; - x = (x >> 16) | x; - return x + 1; -} - #ifdef DBG_VIS_MRT // visualize the MRT buffers static void draw_deferred_debug() diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer_deferred.h --- a/prototype/src/renderer_deferred.h Tue Oct 16 04:08:35 2012 +0300 +++ b/prototype/src/renderer_deferred.h Fri Oct 19 02:45:57 2012 +0300 @@ -8,20 +8,17 @@ class DeferredRenderer : public Renderer { protected: // render targets - unsigned int fbo, rend_tex, rbuf_depth; unsigned int mrt_tex[MRT_COUNT]; - int tex_xsz, tex_ysz; // shaders unsigned int mrt_prog; unsigned int deferred_omni, deferred_debug; - unsigned int post_sdr; mutable unsigned int curr_prog; int num_draw_bufs; - virtual bool create_fbo(); + virtual bool create_rtarg(); public: DeferredRenderer(); diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer_multipass.cc --- a/prototype/src/renderer_multipass.cc Tue Oct 16 04:08:35 2012 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -#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; - - render_post(level); -} - -static unsigned int load_sdr(const char *vfname, const char *pfname) -{ - unsigned int prog; - - std::string vsfile = datafile_path(vfname); - std::string psfile = datafile_path(pfname); - - const char *vs = vsfile.empty() ? 0 : vsfile.c_str(); - const char *ps = psfile.empty() ? 0 : psfile.c_str(); - - if(!(prog = create_program_load(vs, ps))) { - fprintf(stderr, "failed to load shader program (%s, %s)\n", vs, ps); - return 0; - } - return prog; -} diff -r e198e94435c8 -r a27528035e20 prototype/src/renderer_multipass.h --- a/prototype/src/renderer_multipass.h Tue Oct 16 04:08:35 2012 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -#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_