nuclear@15: #include nuclear@15: #include nuclear@15: #include nuclear@15: #include nuclear@18: #include nuclear@15: #include "opengl.h" nuclear@15: #include "renderer.h" nuclear@15: #include "sdr.h" nuclear@15: #include "datapath.h" nuclear@15: nuclear@18: nuclear@17: static bool create_fbo(int xsz, int ysz); nuclear@18: static unsigned int load_sdr(const char *vfname, const char *pfname); nuclear@17: static int round_pow2(int x); nuclear@15: nuclear@17: nuclear@18: #define MRT_COUNT 1 nuclear@17: static unsigned int mrt_tex[MRT_COUNT]; nuclear@17: nuclear@17: static unsigned int mrt_prog; nuclear@18: static unsigned int deferred_omni, deferred_debug; nuclear@17: nuclear@17: static unsigned int fbo, rbuf_depth; nuclear@17: static const char *fbstname[] = { nuclear@17: "GL_FRAMEBUFFER_COMPLETE", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT", nuclear@17: "no such fbo error", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_FORMATS", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER", nuclear@17: "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER", nuclear@17: "GL_FRAMEBUFFER_UNSUPPORTED" nuclear@15: }; nuclear@15: nuclear@17: static int fb_xsz, fb_ysz, tex_xsz, tex_ysz; nuclear@15: nuclear@17: bool init_renderer(int xsz, int ysz) nuclear@17: { nuclear@17: if(!create_fbo(xsz, ysz)) { nuclear@17: return false; nuclear@17: } nuclear@18: nuclear@18: if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) { nuclear@18: return false; nuclear@18: } nuclear@18: if(!(deferred_debug = load_sdr("deferred.v.glsl", "deferred.p.glsl"))) { nuclear@17: return false; nuclear@17: } nuclear@17: return true; nuclear@17: } nuclear@17: nuclear@17: void destroy_renderer() nuclear@17: { nuclear@17: free_program(mrt_prog); nuclear@17: free_program(deferred_omni); nuclear@17: nuclear@17: glDeleteTextures(MRT_COUNT, mrt_tex); nuclear@17: glDeleteFramebuffersEXT(1, &fbo); nuclear@17: } nuclear@17: nuclear@17: void render_deferred(void (*draw_func)()) nuclear@17: { nuclear@18: int loc; nuclear@18: nuclear@18: // render into the MRT buffers nuclear@18: glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); nuclear@18: glUseProgram(mrt_prog); nuclear@17: draw_func(); nuclear@18: glUseProgram(0); nuclear@18: glBindFramebufferEXT(GL_FRAMEBUFFER, 0); nuclear@18: nuclear@18: nuclear@18: // post-process lighting nuclear@18: glPushAttrib(GL_ENABLE_BIT); nuclear@18: nuclear@18: glDisable(GL_LIGHTING); nuclear@18: glDisable(GL_DEPTH_TEST); nuclear@18: glBindTexture(GL_TEXTURE_2D, mrt_tex[0]); nuclear@18: glEnable(GL_TEXTURE_2D); nuclear@18: nuclear@18: glUseProgram(deferred_debug); nuclear@18: if((loc = glGetUniformLocation(deferred_debug, "tex0")) != -1) { nuclear@18: glUniform1i(loc, 0); nuclear@18: } nuclear@18: if((loc = glGetUniformLocation(deferred_debug, "tex_scale")) != -1) { nuclear@18: glUniform2f(loc, (float)fb_xsz / tex_xsz, (float)fb_ysz / tex_ysz); nuclear@18: } nuclear@18: nuclear@18: glBegin(GL_QUADS); nuclear@18: glTexCoord2f(0, 0); nuclear@18: glVertex2f(-1, -1); nuclear@18: glTexCoord2f(1, 0); nuclear@18: glVertex2f(1, -1); nuclear@18: glTexCoord2f(1, 1); nuclear@18: glVertex2f(1, 1); nuclear@18: glTexCoord2f(0, 1); nuclear@18: glVertex2f(-1, 1); nuclear@18: glEnd(); nuclear@18: nuclear@18: glUseProgram(0); nuclear@18: glPopAttrib(); nuclear@17: } nuclear@17: nuclear@17: static bool create_fbo(int xsz, int ysz) nuclear@17: { nuclear@17: unsigned int clamp = GL_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP; nuclear@17: nuclear@17: tex_xsz = round_pow2(xsz); nuclear@17: tex_ysz = round_pow2(ysz); nuclear@17: fb_xsz = xsz; nuclear@17: fb_ysz = ysz; nuclear@17: nuclear@17: if(!glGenFramebuffersEXT) { nuclear@17: fprintf(stderr, "FBO support missing\n"); nuclear@17: return false; nuclear@17: } nuclear@17: glGenFramebuffersEXT(1, &fbo); nuclear@18: glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); nuclear@17: nuclear@17: glGenTextures(MRT_COUNT, mrt_tex); nuclear@17: for(int i=0; i> 1) | x; nuclear@17: x = (x >> 2) | x; nuclear@17: x = (x >> 4) | x; nuclear@17: x = (x >> 8) | x; nuclear@17: x = (x >> 16) | x; nuclear@17: return x + 1; nuclear@15: }