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)