Browse Source

Add masking (see issue #211). Only "hard" masks are supported, no
semitransparent ones.

--HG--
branch : minor

vrld 14 years ago
parent
commit
939041886c

+ 23 - 0
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.

+ 16 - 0
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.
 		**/

+ 30 - 0
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 },

+ 2 - 0
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);