From 939041886c3d4544096658e24167a2de8daf5ed7 Mon Sep 17 00:00:00 2001 From: vrld Date: Tue, 26 Apr 2011 22:10:34 +0200 Subject: [PATCH] Add masking (see issue #211). Only "hard" masks are supported, no semitransparent ones. --HG-- branch : minor --- src/modules/graphics/opengl/Graphics.cpp | 23 ++++++++++++++ src/modules/graphics/opengl/Graphics.h | 16 ++++++++++ src/modules/graphics/opengl/wrap_Graphics.cpp | 30 +++++++++++++++++++ src/modules/graphics/opengl/wrap_Graphics.h | 2 ++ 4 files changed, 71 insertions(+) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 4fabd5327..8cc43c0a2 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -173,6 +173,7 @@ namespace opengl SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0)); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); // FSAA if(fsaa > 0) @@ -425,6 +426,28 @@ namespace opengl return 4; } + void Graphics::defineMask() + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glEnable(GL_STENCIL_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_ALWAYS, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + + void Graphics::useMask() + { + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + void Graphics::discardMask() + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_STENCIL_TEST); + } + Image * Graphics::newImage(love::image::ImageData * data) { // Create the image. diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 70596c09b..8be7661f2 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -234,6 +234,22 @@ namespace opengl **/ int getScissor(lua_State * L); + /** + * Enables the stencil buffer and set stencil function to fill it + */ + void defineMask(); + + /** + * Set stencil function to mask the following drawing calls using + * the current stencil buffer + */ + void useMask(); + + /** + * Disables the stencil buffer + */ + void discardMask(); + /** * Creates an Image object with padding and/or optimization. **/ diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 883128a40..2b1a88cd7 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -144,6 +144,33 @@ namespace opengl return instance->getScissor(L); } + int w_defineMask(lua_State * L) + { + // just return the function + if (!lua_isfunction(L, 1)) + return luaL_typerror(L, 1, "function"); + lua_settop(L, 1); + return 1; + } + + int w_setMask(lua_State * L) + { + // no argument -> clear mask + if (lua_isnoneornil(L, 1)) { + instance->discardMask(); + return 0; + } + + if (!lua_isfunction(L, 1)) + return luaL_typerror(L, 1, "mask"); + + instance->defineMask(); + lua_call(L, lua_gettop(L) - 1, 0); // call mask(...) + instance->useMask(); + + return 0; + } + int w_newImage(lua_State * L) { // Convert to File, if necessary. @@ -1020,6 +1047,9 @@ namespace opengl { "setScissor", w_setScissor }, { "getScissor", w_getScissor }, + { "defineMask", w_defineMask }, + { "setMask", w_setMask }, + { "point", w_point }, { "line", w_line }, { "triangle", w_triangle }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index e34256570..d17dd7511 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -50,6 +50,8 @@ namespace opengl int w_isCreated(lua_State * L); int w_setScissor(lua_State * L); int w_getScissor(lua_State * L); + int w_defineMask(lua_State * L); + int w_setMask(lua_State * L); int w_newImage(lua_State * L); int w_newQuad(lua_State * L); int w_newFrame(lua_State * L);