diff --git a/src/modules/graphics/opengl/Framebuffer.cpp b/src/modules/graphics/opengl/Framebuffer.cpp index 4a36940d1..1acc97af8 100644 --- a/src/modules/graphics/opengl/Framebuffer.cpp +++ b/src/modules/graphics/opengl/Framebuffer.cpp @@ -7,8 +7,8 @@ namespace graphics { namespace opengl { + Framebuffer* Framebuffer::current = NULL; - bool Framebuffer::isGrabbing = false; Framebuffer::Framebuffer(int width, int height) : width(width), height(height) { @@ -47,7 +47,7 @@ namespace opengl GL_TEXTURE_2D, img, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer); - status_ = glCheckFramebufferStatus(GL_FRAMEBUFFER); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // unbind buffers and texture glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -55,37 +55,53 @@ namespace opengl Framebuffer::~Framebuffer() { + // reset framebuffer if still using this one + if (current == this) + stopGrab(); + + // clear fbo glDeleteTextures(1, &fbo); glDeleteRenderbuffers(1, &depthbuffer); glDeleteFramebuffers(1, &img); } - bool Framebuffer::grab() + void Framebuffer::bindDefaultBuffer() { - // don't allow nesting or forgetting Framebuffer::stop() - if (isGrabbing) - return false; + if (current != NULL) + current->stopGrab(); + } + void Framebuffer::startGrab() + { + // already grabbing + if (current == this) + return; + + // cleanup after previous fbo + if (current != NULL) + glPopAttrib(); + + // bind buffer and clear screen glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(.0f, .0f, .0f, .0f); glViewport(0, 0, width, height); - isGrabbing = true; - return true; + // indicate + current = this; } - bool Framebuffer::stop() + void Framebuffer::stopGrab() { - if (!isGrabbing) - return false; + // i am not grabbing. leave me alone + if (current != this) + return; + // bind default glBindFramebuffer(GL_FRAMEBUFFER, 0); glPopAttrib(); - isGrabbing = false; - - return true; + current = NULL; } void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const diff --git a/src/modules/graphics/opengl/Framebuffer.h b/src/modules/graphics/opengl/Framebuffer.h index 8e3e9ec31..22b4025e6 100644 --- a/src/modules/graphics/opengl/Framebuffer.h +++ b/src/modules/graphics/opengl/Framebuffer.h @@ -20,16 +20,18 @@ namespace opengl Framebuffer(int width, int height); virtual ~Framebuffer(); - unsigned int getStatus() const { return status_; } + unsigned int getStatus() const { return status; } - bool grab(); - bool stop(); + static Framebuffer* current; + static void bindDefaultBuffer(); + + void startGrab(); + void stopGrab(); virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const; - private: - static bool isGrabbing; + private: GLsizei width; GLsizei height; GLuint fbo; @@ -38,7 +40,7 @@ namespace opengl vertex vertices[4]; - GLenum status_; + GLenum status; }; } // opengl diff --git a/src/modules/graphics/opengl/wrap_Framebuffer.cpp b/src/modules/graphics/opengl/wrap_Framebuffer.cpp index 588cb92fb..db882805f 100644 --- a/src/modules/graphics/opengl/wrap_Framebuffer.cpp +++ b/src/modules/graphics/opengl/wrap_Framebuffer.cpp @@ -11,51 +11,29 @@ namespace opengl return luax_checktype(L, idx, "Framebuffer", GRAPHICS_FRAMEBUFFER_T); } - int w_Framebuffer_render(lua_State * L) + int w_Framebuffer_renderTo(lua_State * L) { + // As startGrab() clears the framebuffer, better not allow + // grabbing inside another grabbing + if (Framebuffer::current != NULL) { + Framebuffer::bindDefaultBuffer(); + return luaL_error(L, "Current render target not the default framebuffer!"); + } + Framebuffer * fbo = luax_checkfbo(L, 1); if (!lua_isfunction(L, 2)) return luaL_error(L, "Need a function to render to fbo"); - // prevent nesting - if (!fbo->grab()) { - fbo->stop(); // stop grabbing so errormessage is shown - return luaL_error(L, "Framebuffer:grab(): Cannot grab screen. Be sure to match every Framebuffer:grab() with Framebuffer:stop()."); - } - + fbo->startGrab(); lua_settop(L, 2); // make sure the function is on top of the stack lua_call(L, 0, 0); + fbo->stopGrab(); - // fbo can be stopped in function. - if (!fbo->stop()) - return luaL_error(L, "Framebuffer:render(): Screengrabbing already stopped."); - - return 0; - } - - int w_Framebuffer_grab(lua_State * L) - { - Framebuffer * fbo = luax_checkfbo(L, 1); - // prevent nesting - if (!fbo->grab()) { - fbo->stop(); // stop grabbing so errormessage is shown - return luaL_error(L, "Framebuffer:grab(): Cannot grab screen. Be sure to match every Framebuffer:grab() with Framebuffer:stop()."); - } - return 0; - } - - int w_Framebuffer_stop(lua_State * L) - { - Framebuffer * fbo = luax_checkfbo(L, 1); - if (!fbo->stop()) - return luaL_error(L, "Framebuffer:stop(): Screengrabbing already stopped."); return 0; } static const luaL_Reg functions[] = { - { "render", w_Framebuffer_render }, - { "grab", w_Framebuffer_grab }, - { "stop", w_Framebuffer_stop }, + { "renderTo", w_Framebuffer_renderTo }, { 0, 0 } }; diff --git a/src/modules/graphics/opengl/wrap_Framebuffer.h b/src/modules/graphics/opengl/wrap_Framebuffer.h index 0bdf9964f..563a3abbd 100644 --- a/src/modules/graphics/opengl/wrap_Framebuffer.h +++ b/src/modules/graphics/opengl/wrap_Framebuffer.h @@ -13,9 +13,7 @@ namespace opengl { //see Framebuffer.h Framebuffer * luax_checkfbo(lua_State * L, int idx); - int w_Framebuffer_render(lua_State * L); - int w_Framebuffer_bind(lua_State * L); - int w_Framebuffer_unbind(lua_State * L); + int w_Framebuffer_renderTo(lua_State * L); int luaopen_framebuffer(lua_State * L); } // opengl diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index fd3f04d0a..08baea2f3 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -595,6 +595,21 @@ namespace opengl return 1; } + int w_setRenderTarget(lua_State * L) + { + // called with nil -> reset to default buffer + if (lua_isnil(L, 1)) { + Framebuffer::bindDefaultBuffer(); + return 0; + } + + Framebuffer * fbo = luax_checkfbo(L, 1); + // this unbinds the previous fbo + fbo->startGrab(); + + return 0; + } + /** * Draws an Image at the specified coordinates, with rotation and * scaling along both axes. @@ -885,6 +900,7 @@ namespace opengl { "getPointStyle", w_getPointStyle }, { "getMaxPointSize", w_getMaxPointSize }, { "newScreenshot", w_newScreenshot }, + { "setRenderTarget", w_setRenderTarget }, { "draw", w_draw }, { "drawq", w_drawq }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index d7d51ec89..776978351 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -84,6 +84,7 @@ namespace opengl int w_getPointStyle(lua_State * L); int w_getMaxPointSize(lua_State * L); int w_newScreenshot(lua_State * L); + int w_setRenderTarget(lua_State * L); int w_draw(lua_State * L); int w_drawq(lua_State * L); int w_drawTest(lua_State * L);