From 88c8e0c071ea7e5a71458c6b326ae4f1cf625264 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 24 Jun 2015 16:47:10 -0300 Subject: [PATCH] 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). --- src/modules/graphics/Graphics.cpp | 1 - src/modules/graphics/Graphics.h | 1 - src/modules/graphics/opengl/Graphics.cpp | 29 +++++++++++-------- src/modules/graphics/opengl/Graphics.h | 5 ++-- src/modules/graphics/opengl/wrap_Graphics.cpp | 10 +++++-- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 7a4f9f738..7c1a24db6 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -123,7 +123,6 @@ StringMap::Entry Graphics::blendM { "add", BLEND_ADD }, { "subtract", BLEND_SUBTRACT }, { "multiply", BLEND_MULTIPLY }, - { "premultiplied", BLEND_PREMULTIPLIED }, { "screen", BLEND_SCREEN }, { "replace", BLEND_REPLACE }, }; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 7777d06f8..13c7eed75 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -50,7 +50,6 @@ public: BLEND_ADD, BLEND_SUBTRACT, BLEND_MULTIPLY, - BLEND_PREMULTIPLIED, BLEND_SCREEN, BLEND_REPLACE, BLEND_MAX_ENUM diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index a3a5feee6..603275097 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -101,7 +101,7 @@ void Graphics::restoreState(const DisplayState &s) setColor(s.color); setBackgroundColor(s.backgroundColor); - setBlendMode(s.blendMode); + setBlendMode(s.blendMode, s.blendMultiplyAlpha); setLineWidth(s.lineWidth); setLineStyle(s.lineStyle); @@ -137,8 +137,8 @@ void Graphics::restoreStateChecked(const DisplayState &s) if (*(uint32 *) &s.backgroundColor.r != *(uint32 *) &cur.backgroundColor.r) 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. setLineWidth(s.lineWidth); @@ -923,7 +923,7 @@ Graphics::ColorMask Graphics::getColorMask() const return states.back().colorMask; } -void Graphics::setBlendMode(Graphics::BlendMode mode) +void Graphics::setBlendMode(BlendMode mode, bool multiplyalpha) { GLenum func = GL_FUNC_ADD; GLenum srcRGB = GL_ONE; @@ -934,22 +934,18 @@ void Graphics::setBlendMode(Graphics::BlendMode mode) switch (mode) { case BLEND_ALPHA: - srcRGB = GL_SRC_ALPHA; - srcA = GL_ONE; + srcRGB = srcA = GL_ONE; dstRGB = dstA = GL_ONE_MINUS_SRC_ALPHA; break; case BLEND_MULTIPLY: srcRGB = srcA = GL_DST_COLOR; dstRGB = dstA = GL_ZERO; break; - case BLEND_PREMULTIPLIED: - srcRGB = srcA = GL_ONE; - dstRGB = dstA = GL_ONE_MINUS_SRC_ALPHA; - break; case BLEND_SUBTRACT: func = GL_FUNC_REVERSE_SUBTRACT; case BLEND_ADD: - srcRGB = srcA = GL_SRC_ALPHA; + srcRGB = GL_ONE; + srcA = GL_SRC_ALPHA; // FIXME: This isn't correct... dstRGB = dstA = GL_ONE; break; case BLEND_SCREEN: @@ -963,14 +959,20 @@ void Graphics::setBlendMode(Graphics::BlendMode mode) break; } + // We can only do alpha-multiplication when srcRGB would have been unmodified. + if (srcRGB == GL_ONE && multiplyalpha) + srcRGB = GL_SRC_ALPHA; + glBlendEquation(func); glBlendFuncSeparate(srcRGB, dstRGB, srcA, dstA); 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; } @@ -1493,6 +1495,7 @@ Graphics::DisplayState::DisplayState() : color(255, 255, 255, 255) , backgroundColor(0, 0, 0, 255) , blendMode(BLEND_ALPHA) + , blendMultiplyAlpha(true) , lineWidth(1.0f) , lineStyle(LINE_SMOOTH) , lineJoin(LINE_JOIN_MITER) @@ -1515,6 +1518,7 @@ Graphics::DisplayState::DisplayState(const DisplayState &other) : color(other.color) , backgroundColor(other.backgroundColor) , blendMode(other.blendMode) + , blendMultiplyAlpha(other.blendMultiplyAlpha) , lineWidth(other.lineWidth) , lineStyle(other.lineStyle) , lineJoin(other.lineJoin) @@ -1543,6 +1547,7 @@ Graphics::DisplayState &Graphics::DisplayState::operator = (const DisplayState & color = other.color; backgroundColor = other.backgroundColor; blendMode = other.blendMode; + blendMultiplyAlpha = other.blendMultiplyAlpha; lineWidth = other.lineWidth; lineStyle = other.lineStyle; lineJoin = other.lineJoin; diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 7233b506f..ba9a97ac1 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -232,12 +232,12 @@ public: /** * Sets the current blend mode. **/ - void setBlendMode(BlendMode mode); + void setBlendMode(BlendMode mode, bool multiplyalpha); /** * Gets the current blend mode. **/ - BlendMode getBlendMode() const; + BlendMode getBlendMode(bool &multiplyalpha) const; /** * Sets the default filter for images, canvases, and fonts. @@ -467,6 +467,7 @@ private: Color backgroundColor; BlendMode blendMode; + bool blendMultiplyAlpha; float lineWidth; LineStyle lineStyle; diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 98c885b05..6057a14bc 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -967,7 +967,9 @@ int w_setBlendMode(lua_State *L) if (!Graphics::getConstant(str, mode)) 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; } @@ -975,14 +977,16 @@ int w_getBlendMode(lua_State *L) { const char *str; Graphics::BlendMode mode; + bool multiplyalpha = false; - luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(); }); + luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(multiplyalpha); }); if (!Graphics::getConstant(mode, str)) return luaL_error(L, "Unknown blend mode"); lua_pushstring(L, str); - return 1; + lua_pushboolean(L, multiplyalpha); + return 2; } int w_setDefaultFilter(lua_State *L)