Add love.graphics.setBlendState, which sets the lower level blend operation and factor values which higher level blend modes are based on.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2019-12-27 09:57:42 -05:00
parent efa2bd7837
commit b41f1316fa
7 changed files with 226 additions and 86 deletions
+75 -39
View File
@@ -26,48 +26,44 @@ namespace love
namespace graphics
{
BlendState getBlendState(BlendMode mode, BlendAlpha alphamode)
// These are all with premultiplied alpha. computeBlendState adjusts for
// alpha-multiply if needed.
static const BlendState states[BLEND_MAX_ENUM] =
{
BlendState s;
// BLEND_ALPHA
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA},
s.enable = mode != BLEND_NONE;
s.operationRGB = BLENDOP_ADD;
s.operationA = BLENDOP_ADD;
// BLEND_ADD
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
switch (mode)
{
case BLEND_ALPHA:
s.srcFactorRGB = s.srcFactorA = BLENDFACTOR_ONE;
s.dstFactorRGB = s.dstFactorA = BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
break;
case BLEND_MULTIPLY:
s.srcFactorRGB = s.srcFactorA = BLENDFACTOR_DST_COLOR;
s.dstFactorRGB = s.dstFactorA = BLENDFACTOR_ZERO;
break;
case BLEND_SUBTRACT:
s.operationRGB = s.operationA = BLENDOP_REVERSE_SUBTRACT;
case BLEND_ADD:
s.srcFactorRGB = BLENDFACTOR_ONE;
s.srcFactorA = BLENDFACTOR_ZERO;
s.dstFactorRGB = s.dstFactorA = BLENDFACTOR_ONE;
break;
case BLEND_LIGHTEN:
s.operationRGB = s.operationA = BLENDOP_MAX;
break;
case BLEND_DARKEN:
s.operationRGB = s.operationA = BLENDOP_MIN;
break;
case BLEND_SCREEN:
s.srcFactorRGB = s.srcFactorA = BLENDFACTOR_ONE;
s.dstFactorRGB = s.dstFactorA = BLENDFACTOR_ONE_MINUS_SRC_COLOR;
break;
case BLEND_REPLACE:
case BLEND_NONE:
default:
s.srcFactorRGB = s.srcFactorA = BLENDFACTOR_ONE;
s.dstFactorRGB = s.dstFactorA = BLENDFACTOR_ZERO;
break;
}
// BLEND_SUBTRACT
{BLENDOP_REVERSE_SUBTRACT, BLENDOP_REVERSE_SUBTRACT, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
// BLEND_MULTIPLY
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_DST_COLOR, BLENDFACTOR_DST_COLOR, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
// BLEND_LIGHTEN
{BLENDOP_MAX, BLENDOP_MAX, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
// BLEND_DARKEN
{BLENDOP_MAX, BLENDOP_MAX, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
// BLEND_SCREEN
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE_MINUS_SRC_COLOR, BLENDFACTOR_ONE_MINUS_SRC_COLOR},
// BLEND_REPLACE
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
// BLEND_NONE
{},
// BLEND_CUSTOM - N/A
{},
};
BlendState computeBlendState(BlendMode mode, BlendAlpha alphamode)
{
BlendState s = states[mode];
// We can only do alpha-multiplication when srcRGB would have been unmodified.
if (s.srcFactorRGB == BLENDFACTOR_ONE && alphamode == BLENDALPHA_MULTIPLY && mode != BLEND_NONE)
@@ -76,6 +72,45 @@ BlendState getBlendState(BlendMode mode, BlendAlpha alphamode)
return s;
}
BlendMode computeBlendMode(BlendState s, BlendAlpha &alphamode)
{
if (!s.enable)
{
alphamode = BLENDALPHA_PREMULTIPLIED;
return BLEND_NONE;
}
// Temporarily disable alpha multiplication when comparing to our list.
bool alphamultiply = s.srcFactorRGB == BLENDFACTOR_SRC_ALPHA;
if (alphamultiply)
s.srcFactorRGB = BLENDFACTOR_ONE;
for (int i = 0; i < (int) BLEND_MAX_ENUM; i++)
{
if (i != (int) BLEND_CUSTOM && states[i] == s)
{
alphamode = alphamultiply ? BLENDALPHA_MULTIPLY : BLENDALPHA_PREMULTIPLIED;
return (BlendMode) i;
}
}
alphamode = BLENDALPHA_PREMULTIPLIED;
return BLEND_CUSTOM;
}
bool isAlphaMultiplyBlendSupported(BlendMode mode)
{
switch (mode)
{
case BLEND_LIGHTEN:
case BLEND_DARKEN:
case BLEND_MULTIPLY:
return false;
default:
return true;
}
}
CompareMode getReversedCompareMode(CompareMode mode)
{
switch (mode)
@@ -99,6 +134,7 @@ static StringMap<BlendMode, BLEND_MAX_ENUM>::Entry blendModeEntries[] =
{ "screen", BLEND_SCREEN },
{ "replace", BLEND_REPLACE },
{ "none", BLEND_NONE },
{ "custom", BLEND_CUSTOM },
};
static StringMap<BlendMode, BLEND_MAX_ENUM> blendModes(blendModeEntries, sizeof(blendModeEntries));