Commits

Alex Szpakowski  committed 6f9dbde

Added love.graphics.setAlphaTest (issue #534)

  • Participants
  • Parent commits 5eb0d05

Comments (0)

Files changed (6)

File src/modules/graphics/Graphics.cpp

 	return pointStyles.find(in, out);
 }
 
+bool Graphics::getConstant(const char *in, AlphaTestMode &out)
+{
+	return alphaTests.find(in, out);
+}
+
+bool Graphics::getConstant(AlphaTestMode in, const char *&out)
+{
+	return alphaTests.find(in, out);
+}
+
 bool Graphics::getConstant(const char *in, Support &out)
 {
 	return support.find(in, out);
 
 StringMap<Graphics::PointStyle, Graphics::POINT_MAX_ENUM> Graphics::pointStyles(Graphics::pointStyleEntries, sizeof(Graphics::pointStyleEntries));
 
+StringMap<Graphics::AlphaTestMode, Graphics::ALPHATEST_MAX_ENUM>::Entry Graphics::alphaTestEntries[] =
+{
+	{ "<", Graphics::ALPHATEST_LESS },
+	{ "<=", Graphics::ALPHATEST_LEQUAL },
+	{ "==", Graphics::ALPHATEST_EQUAL },
+	{ "~=", Graphics::ALPHATEST_NOTEQUAL },
+	{ ">=", Graphics::ALPHATEST_GEQUAL },
+	{ ">", Graphics::ALPHATEST_GREATER },
+};
+
+StringMap<Graphics::AlphaTestMode, Graphics::ALPHATEST_MAX_ENUM> Graphics::alphaTests(Graphics::alphaTestEntries, sizeof(Graphics::alphaTestEntries));
+
 StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::supportEntries[] =
 {
 	{ "canvas", Graphics::SUPPORT_CANVAS },

File src/modules/graphics/Graphics.h

 		POINT_MAX_ENUM
 	};
 
+	enum AlphaTestMode
+	{
+		ALPHATEST_LESS = 1,
+		ALPHATEST_LEQUAL,
+		ALPHATEST_EQUAL,
+		ALPHATEST_NOTEQUAL,
+		ALPHATEST_GEQUAL,
+		ALPHATEST_GREATER,
+		ALPHATEST_MAX_ENUM
+	};
+
 	enum Support
 	{
 		SUPPORT_CANVAS = 1,
 	static bool getConstant(const char *in, PointStyle &out);
 	static bool getConstant(PointStyle in, const char  *&out);
 
+	static bool getConstant(const char *in, AlphaTestMode &out);
+	static bool getConstant(AlphaTestMode in, const char *&out);
+
 	static bool getConstant(const char *in, Support &out);
 	static bool getConstant(Support in, const char  *&out);
 
 	static StringMap<PointStyle, POINT_MAX_ENUM>::Entry pointStyleEntries[];
 	static StringMap<PointStyle, POINT_MAX_ENUM> pointStyles;
 
+	static StringMap<AlphaTestMode, ALPHATEST_MAX_ENUM>::Entry alphaTestEntries[];
+	static StringMap<AlphaTestMode, ALPHATEST_MAX_ENUM> alphaTests;
+
 	static StringMap<Support, SUPPORT_MAX_ENUM>::Entry supportEntries[];
 	static StringMap<Support, SUPPORT_MAX_ENUM> support;
 

File src/modules/graphics/opengl/Graphics.cpp

 	glGetFloatv(GL_POINT_SIZE, &s.pointSize);
 	//get point style
 	s.pointStyle = (glIsEnabled(GL_POINT_SMOOTH) == GL_TRUE) ? Graphics::POINT_SMOOTH : Graphics::POINT_ROUGH;
+	// get alpha test status
+	s.alphaTest = isAlphaTestEnabled();
+	if (s.alphaTest)
+	{
+		// if alpha testing is enabled, store mode and reference alpha
+		s.alphaTestMode = getAlphaTestMode();
+		s.alphaTestRef = getAlphaTestRef();
+	}
 	//get scissor status
 	s.scissor = (glIsEnabled(GL_SCISSOR_TEST) == GL_TRUE);
 	//do we have scissor, if so, store the box
 	setBlendMode(s.blendMode);
 	setLine(lineWidth, s.lineStyle);
 	setPoint(s.pointSize, s.pointStyle);
+	if (s.alphaTest)
+		setAlphaTest(s.alphaTestMode, s.alphaTestRef);
+	else
+		setAlphaTest();
 	if (s.scissor)
 		setScissor(s.scissorBox[0], s.scissorBox[1], s.scissorBox[2], s.scissorBox[3]);
 	else
 	if (GLEE_VERSION_1_4 || GLEE_SGIS_generate_mipmap)
 		glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
 
+	// Set default alpha test mode and value
+	glAlphaFunc(GL_GREATER, 0.0f);
+	setAlphaTest();
+
 	// Enable textures
 	glEnable(GL_TEXTURE_2D);
 	setActiveTextureUnit(0);
 	glDisable(GL_STENCIL_TEST);
 }
 
+void Graphics::setAlphaTest(Graphics::AlphaTestMode mode, unsigned char refalpha)
+{
+	GLclampf ref = refalpha / 255.0f;
+
+	glEnable(GL_ALPHA_TEST);
+
+	switch (mode)
+	{
+	case ALPHATEST_LESS:
+		glAlphaFunc(GL_LESS, ref);
+		break;
+	case ALPHATEST_LEQUAL:
+		glAlphaFunc(GL_LEQUAL, ref);
+		break;
+	case ALPHATEST_EQUAL:
+		glAlphaFunc(GL_EQUAL, ref);
+		break;
+	case ALPHATEST_NOTEQUAL:
+		glAlphaFunc(GL_NOTEQUAL, ref);
+		break;
+	case ALPHATEST_GEQUAL:
+		glAlphaFunc(GL_GEQUAL, ref);
+		break;
+	case ALPHATEST_GREATER:
+		glAlphaFunc(GL_GREATER, ref);
+		break;
+	default:
+		glDisable(GL_ALPHA_TEST);
+		break;
+	}
+}
+
+void Graphics::setAlphaTest()
+{
+	glDisable(GL_ALPHA_TEST);
+}
+
+bool Graphics::isAlphaTestEnabled()
+{
+	return glIsEnabled(GL_ALPHA_TEST) == GL_TRUE;
+}
+
+Graphics::AlphaTestMode Graphics::getAlphaTestMode()
+{
+	GLint func;
+	glGetIntegerv(GL_ALPHA_TEST_FUNC, &func);
+
+	switch (func)
+	{
+	case GL_LESS:
+		return ALPHATEST_LESS;
+	case GL_LEQUAL:
+		return ALPHATEST_LEQUAL;
+	case GL_EQUAL:
+		return ALPHATEST_EQUAL;
+	case GL_NOTEQUAL:
+		return ALPHATEST_NOTEQUAL;
+	case GL_GEQUAL:
+		return ALPHATEST_GEQUAL;
+	case GL_GREATER:
+		return ALPHATEST_GREATER;
+	default:
+		return ALPHATEST_MAX_ENUM;
+	}
+}
+
+unsigned char Graphics::getAlphaTestRef()
+{
+	GLfloat ref;
+	glGetFloatv(GL_ALPHA_TEST_REF, &ref);
+
+	return ref * 255;
+}
+
 Image *Graphics::newImage(love::image::ImageData *data)
 {
 	// Create the image.

File src/modules/graphics/opengl/Graphics.h

 	float pointSize;
 	Graphics::PointStyle pointStyle;
 
+	bool alphaTest;
+	Graphics::AlphaTestMode alphaTestMode;
+	unsigned char alphaTestRef;
+
 	// Scissor.
 	bool scissor;
 	GLint scissorBox[4];
 		lineStyle = Graphics::LINE_SMOOTH;
 		pointSize = 1.0f;
 		pointStyle = Graphics::POINT_SMOOTH;
+		alphaTest = false;
 		scissor = false;
 		colorMask[0] = colorMask[1] = colorMask[2] = colorMask[3] = true;
 		caption = "";
 	void discardStencil();
 
 	/**
+	 * Enables alpha testing for all following draw calls
+	 * @param mode The alpha comparison mode used when performing the alpha test
+	 * @param refalpha The reference alpha value used when perfoming the alpha test
+	 */
+	void setAlphaTest(Graphics::AlphaTestMode mode, unsigned char refalpha);
+
+	/**
+	 * Disables alpha testing
+	 */
+	void setAlphaTest();
+
+	/**
+	 * True if alpha testing is enabled
+	 */
+	bool isAlphaTestEnabled();
+
+	/**
+	 * Gets the current alpha test comparison mode
+	 */
+	Graphics::AlphaTestMode getAlphaTestMode();
+
+	/**
+	 * Gets the current alpha test reference alpha value (0-255)
+	 */
+	unsigned char getAlphaTestRef();
+
+	/**
 	 * Creates an Image object with padding and/or optimization.
 	 **/
 	Image *newImage(love::image::ImageData *data);

File src/modules/graphics/opengl/wrap_Graphics.cpp

 	return setStencil(L, true);
 }
 
+int w_setAlphaTest(lua_State *L)
+{
+	// disable alpha testing if no arguments are given
+	if (lua_gettop(L) == 0)
+	{
+		instance->setAlphaTest();
+		return 0;
+	}
+
+	const char *modestr = luaL_checkstring(L, 1);
+	unsigned char refalpha = (unsigned char) luaL_checkinteger(L, 2);
+
+	Graphics::AlphaTestMode mode;
+	if (!Graphics::getConstant(modestr, mode))
+		return luaL_error(L, "Invalid alpha test mode: %s", modestr);
+
+	instance->setAlphaTest(mode, refalpha);
+
+	return 0;
+}
+
+int w_getAlphaTest(lua_State *L)
+{
+	// return nil if not enabled
+	if (!instance->isAlphaTestEnabled())
+		return 0;
+	
+	Graphics::AlphaTestMode mode = instance->getAlphaTestMode();
+	
+	const char *modestr;
+	if (!Graphics::getConstant(mode, modestr))
+		return 0; // also return nil if alpha test mode isn't valid
+
+	unsigned char refalpha = instance->getAlphaTestRef();
+
+	lua_pushstring(L, modestr);
+	lua_pushnumber(L, refalpha);
+
+	return 2;
+}
+
 int w_newImage(lua_State *L)
 {
 	love::image::ImageData *data = 0;
 	{ "setStencil", w_setStencil },
 	{ "setInvertedStencil", w_setInvertedStencil },
 
+	{ "setAlphaTest", w_setAlphaTest },
+	{ "getAlphaTest", w_getAlphaTest },
+
 	{ "point", w_point },
 	{ "line", w_line },
 	{ "rectangle", w_rectangle },

File src/modules/graphics/opengl/wrap_Graphics.h

 int w_getScissor(lua_State *L);
 int w_defineMask(lua_State *L);
 int w_setMask(lua_State *L);
+int w_setAlphaTest(lua_State *L);
+int w_getAlphaTest(lua_State *L);
 int w_newImage(lua_State *L);
 int w_newQuad(lua_State *L);
 int w_newQuad(lua_State *L);