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@19: #define MRT_COUNT 4 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@19: int max_draw_buf; nuclear@19: nuclear@19: glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buf); nuclear@19: CHECKGLERR; nuclear@19: printf("max draw buffers: %d\n", max_draw_buf); nuclear@19: if(max_draw_buf < MRT_COUNT) { nuclear@19: fprintf(stderr, "OpenGL implementation doesn't support enough draw buffers\n"); nuclear@19: return false; nuclear@19: } nuclear@19: nuclear@17: if(!create_fbo(xsz, ysz)) { nuclear@17: return false; nuclear@17: } nuclear@19: CHECKGLERR; 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@19: static GLenum draw_bufs[] = { nuclear@19: GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, nuclear@19: GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT, nuclear@19: GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT, nuclear@19: GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT nuclear@19: }; nuclear@19: nuclear@18: // render into the MRT buffers nuclear@18: glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); nuclear@19: glDrawBuffersARB(MRT_COUNT, draw_bufs); nuclear@19: 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: nuclear@18: glUseProgram(deferred_debug); nuclear@19: 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: }