Browse Source

Added an optional (true by default) boolean argument to love.graphics.setBlendMode to specify whether alpha should be multiplied with rgb when blending.
Removed the 'premultiplied' blend mode, since setBlendMode("alpha", false) accomplishes the same thing now.

The 'multiply' blend mode is unaffected by the new flag, since fixed-function hardware blending can't do the equivalent of setBlendMode("multiply", true).

Alex Szpakowski 10 years ago
parent
commit
88c8e0c071

+ 0 - 1
src/modules/graphics/Graphics.cpp

@@ -123,7 +123,6 @@ StringMap<Graphics::BlendMode, Graphics::BLEND_MAX_ENUM>::Entry Graphics::blendM
 	{ "add", BLEND_ADD },
 	{ "add", BLEND_ADD },
 	{ "subtract", BLEND_SUBTRACT },
 	{ "subtract", BLEND_SUBTRACT },
 	{ "multiply", BLEND_MULTIPLY },
 	{ "multiply", BLEND_MULTIPLY },
-	{ "premultiplied", BLEND_PREMULTIPLIED },
 	{ "screen", BLEND_SCREEN },
 	{ "screen", BLEND_SCREEN },
 	{ "replace", BLEND_REPLACE },
 	{ "replace", BLEND_REPLACE },
 };
 };

+ 0 - 1
src/modules/graphics/Graphics.h

@@ -50,7 +50,6 @@ public:
 		BLEND_ADD,
 		BLEND_ADD,
 		BLEND_SUBTRACT,
 		BLEND_SUBTRACT,
 		BLEND_MULTIPLY,
 		BLEND_MULTIPLY,
-		BLEND_PREMULTIPLIED,
 		BLEND_SCREEN,
 		BLEND_SCREEN,
 		BLEND_REPLACE,
 		BLEND_REPLACE,
 		BLEND_MAX_ENUM
 		BLEND_MAX_ENUM

+ 17 - 12
src/modules/graphics/opengl/Graphics.cpp

@@ -101,7 +101,7 @@ void Graphics::restoreState(const DisplayState &s)
 	setColor(s.color);
 	setColor(s.color);
 	setBackgroundColor(s.backgroundColor);
 	setBackgroundColor(s.backgroundColor);
 
 
-	setBlendMode(s.blendMode);
+	setBlendMode(s.blendMode, s.blendMultiplyAlpha);
 
 
 	setLineWidth(s.lineWidth);
 	setLineWidth(s.lineWidth);
 	setLineStyle(s.lineStyle);
 	setLineStyle(s.lineStyle);
@@ -137,8 +137,8 @@ void Graphics::restoreStateChecked(const DisplayState &s)
 	if (*(uint32 *) &s.backgroundColor.r != *(uint32 *) &cur.backgroundColor.r)
 	if (*(uint32 *) &s.backgroundColor.r != *(uint32 *) &cur.backgroundColor.r)
 		setBackgroundColor(s.backgroundColor);
 		setBackgroundColor(s.backgroundColor);
 
 
-	if (s.blendMode != cur.blendMode)
-		setBlendMode(s.blendMode);
+	if (s.blendMode != cur.blendMode || s.blendMultiplyAlpha != cur.blendMultiplyAlpha)
+		setBlendMode(s.blendMode, s.blendMultiplyAlpha);
 
 
 	// These are just simple assignments.
 	// These are just simple assignments.
 	setLineWidth(s.lineWidth);
 	setLineWidth(s.lineWidth);
@@ -923,7 +923,7 @@ Graphics::ColorMask Graphics::getColorMask() const
 	return states.back().colorMask;
 	return states.back().colorMask;
 }
 }
 
 
-void Graphics::setBlendMode(Graphics::BlendMode mode)
+void Graphics::setBlendMode(BlendMode mode, bool multiplyalpha)
 {
 {
 	GLenum func   = GL_FUNC_ADD;
 	GLenum func   = GL_FUNC_ADD;
 	GLenum srcRGB = GL_ONE;
 	GLenum srcRGB = GL_ONE;
@@ -934,22 +934,18 @@ void Graphics::setBlendMode(Graphics::BlendMode mode)
 	switch (mode)
 	switch (mode)
 	{
 	{
 	case BLEND_ALPHA:
 	case BLEND_ALPHA:
-		srcRGB = GL_SRC_ALPHA;
-		srcA = GL_ONE;
+		srcRGB = srcA = GL_ONE;
 		dstRGB = dstA = GL_ONE_MINUS_SRC_ALPHA;
 		dstRGB = dstA = GL_ONE_MINUS_SRC_ALPHA;
 		break;
 		break;
 	case BLEND_MULTIPLY:
 	case BLEND_MULTIPLY:
 		srcRGB = srcA = GL_DST_COLOR;
 		srcRGB = srcA = GL_DST_COLOR;
 		dstRGB = dstA = GL_ZERO;
 		dstRGB = dstA = GL_ZERO;
 		break;
 		break;
-	case BLEND_PREMULTIPLIED:
-		srcRGB = srcA = GL_ONE;
-		dstRGB = dstA = GL_ONE_MINUS_SRC_ALPHA;
-		break;
 	case BLEND_SUBTRACT:
 	case BLEND_SUBTRACT:
 		func = GL_FUNC_REVERSE_SUBTRACT;
 		func = GL_FUNC_REVERSE_SUBTRACT;
 	case BLEND_ADD:
 	case BLEND_ADD:
-		srcRGB = srcA = GL_SRC_ALPHA;
+		srcRGB = GL_ONE;
+		srcA = GL_SRC_ALPHA; // FIXME: This isn't correct...
 		dstRGB = dstA = GL_ONE;
 		dstRGB = dstA = GL_ONE;
 		break;
 		break;
 	case BLEND_SCREEN:
 	case BLEND_SCREEN:
@@ -963,14 +959,20 @@ void Graphics::setBlendMode(Graphics::BlendMode mode)
 		break;
 		break;
 	}
 	}
 
 
+	// We can only do alpha-multiplication when srcRGB would have been unmodified.
+	if (srcRGB == GL_ONE && multiplyalpha)
+		srcRGB = GL_SRC_ALPHA;
+
 	glBlendEquation(func);
 	glBlendEquation(func);
 	glBlendFuncSeparate(srcRGB, dstRGB, srcA, dstA);
 	glBlendFuncSeparate(srcRGB, dstRGB, srcA, dstA);
 
 
 	states.back().blendMode = mode;
 	states.back().blendMode = mode;
+	states.back().blendMultiplyAlpha = multiplyalpha;
 }
 }
 
 
-Graphics::BlendMode Graphics::getBlendMode() const
+Graphics::BlendMode Graphics::getBlendMode(bool &multiplyalpha) const
 {
 {
+	multiplyalpha = states.back().blendMultiplyAlpha;
 	return states.back().blendMode;
 	return states.back().blendMode;
 }
 }
 
 
@@ -1493,6 +1495,7 @@ Graphics::DisplayState::DisplayState()
 	: color(255, 255, 255, 255)
 	: color(255, 255, 255, 255)
 	, backgroundColor(0, 0, 0, 255)
 	, backgroundColor(0, 0, 0, 255)
 	, blendMode(BLEND_ALPHA)
 	, blendMode(BLEND_ALPHA)
+	, blendMultiplyAlpha(true)
 	, lineWidth(1.0f)
 	, lineWidth(1.0f)
 	, lineStyle(LINE_SMOOTH)
 	, lineStyle(LINE_SMOOTH)
 	, lineJoin(LINE_JOIN_MITER)
 	, lineJoin(LINE_JOIN_MITER)
@@ -1515,6 +1518,7 @@ Graphics::DisplayState::DisplayState(const DisplayState &other)
 	: color(other.color)
 	: color(other.color)
 	, backgroundColor(other.backgroundColor)
 	, backgroundColor(other.backgroundColor)
 	, blendMode(other.blendMode)
 	, blendMode(other.blendMode)
+	, blendMultiplyAlpha(other.blendMultiplyAlpha)
 	, lineWidth(other.lineWidth)
 	, lineWidth(other.lineWidth)
 	, lineStyle(other.lineStyle)
 	, lineStyle(other.lineStyle)
 	, lineJoin(other.lineJoin)
 	, lineJoin(other.lineJoin)
@@ -1543,6 +1547,7 @@ Graphics::DisplayState &Graphics::DisplayState::operator = (const DisplayState &
 	color = other.color;
 	color = other.color;
 	backgroundColor = other.backgroundColor;
 	backgroundColor = other.backgroundColor;
 	blendMode = other.blendMode;
 	blendMode = other.blendMode;
+	blendMultiplyAlpha = other.blendMultiplyAlpha;
 	lineWidth = other.lineWidth;
 	lineWidth = other.lineWidth;
 	lineStyle = other.lineStyle;
 	lineStyle = other.lineStyle;
 	lineJoin = other.lineJoin;
 	lineJoin = other.lineJoin;

+ 3 - 2
src/modules/graphics/opengl/Graphics.h

@@ -232,12 +232,12 @@ public:
 	/**
 	/**
 	 * Sets the current blend mode.
 	 * Sets the current blend mode.
 	 **/
 	 **/
-	void setBlendMode(BlendMode mode);
+	void setBlendMode(BlendMode mode, bool multiplyalpha);
 
 
 	/**
 	/**
 	 * Gets the current blend mode.
 	 * Gets the current blend mode.
 	 **/
 	 **/
-	BlendMode getBlendMode() const;
+	BlendMode getBlendMode(bool &multiplyalpha) const;
 
 
 	/**
 	/**
 	 * Sets the default filter for images, canvases, and fonts.
 	 * Sets the default filter for images, canvases, and fonts.
@@ -467,6 +467,7 @@ private:
 		Color backgroundColor;
 		Color backgroundColor;
 
 
 		BlendMode blendMode;
 		BlendMode blendMode;
+		bool blendMultiplyAlpha;
 
 
 		float lineWidth;
 		float lineWidth;
 		LineStyle lineStyle;
 		LineStyle lineStyle;

+ 7 - 3
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -967,7 +967,9 @@ int w_setBlendMode(lua_State *L)
 	if (!Graphics::getConstant(str, mode))
 	if (!Graphics::getConstant(str, mode))
 		return luaL_error(L, "Invalid blend mode: %s", str);
 		return luaL_error(L, "Invalid blend mode: %s", str);
 
 
-	luax_catchexcept(L, [&](){ instance()->setBlendMode(mode); });
+	bool multiplyalpha = luax_optboolean(L, 2, true);
+
+	luax_catchexcept(L, [&](){ instance()->setBlendMode(mode, multiplyalpha); });
 	return 0;
 	return 0;
 }
 }
 
 
@@ -975,14 +977,16 @@ int w_getBlendMode(lua_State *L)
 {
 {
 	const char *str;
 	const char *str;
 	Graphics::BlendMode mode;
 	Graphics::BlendMode mode;
+	bool multiplyalpha = false;
 
 
-	luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(); });
+	luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(multiplyalpha); });
 
 
 	if (!Graphics::getConstant(mode, str))
 	if (!Graphics::getConstant(mode, str))
 		return luaL_error(L, "Unknown blend mode");
 		return luaL_error(L, "Unknown blend mode");
 
 
 	lua_pushstring(L, str);
 	lua_pushstring(L, str);
-	return 1;
+	lua_pushboolean(L, multiplyalpha);
+	return 2;
 }
 }
 
 
 int w_setDefaultFilter(lua_State *L)
 int w_setDefaultFilter(lua_State *L)