Browse Source

Added "lighten" and "darken" blend modes (resolves issue #443).

They perform the equations res.rgba = max(dst.rgba, src.rgba) and res.rgba = min(dst.rgba, src.rgba) respectively.

They only work when the "premultiplied" blend alpha mode is used, and an error occurs otherwise.  They also aren't supported on some non-iOS OpenGL ES 2 systems. Check for support with love.graphics.getSupported().lighten.
Alex Szpakowski 9 years ago
parent
commit
b48117544d

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

@@ -205,6 +205,8 @@ 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 },
+	{ "lighten",  BLEND_LIGHTEN  },
+	{ "darken",   BLEND_DARKEN   },
 	{ "screen",   BLEND_SCREEN   },
 	{ "screen",   BLEND_SCREEN   },
 	{ "replace",  BLEND_REPLACE  },
 	{ "replace",  BLEND_REPLACE  },
 };
 };
@@ -265,6 +267,7 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
 {
 {
 	{ "multicanvasformats", SUPPORT_MULTI_CANVAS_FORMATS },
 	{ "multicanvasformats", SUPPORT_MULTI_CANVAS_FORMATS },
 	{ "clampzero", SUPPORT_CLAMP_ZERO },
 	{ "clampzero", SUPPORT_CLAMP_ZERO },
+	{ "lighten", SUPPORT_LIGHTEN },
 };
 };
 
 
 StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
 StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));

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

@@ -84,6 +84,8 @@ public:
 		BLEND_ADD,
 		BLEND_ADD,
 		BLEND_SUBTRACT,
 		BLEND_SUBTRACT,
 		BLEND_MULTIPLY,
 		BLEND_MULTIPLY,
+		BLEND_LIGHTEN,
+		BLEND_DARKEN,
 		BLEND_SCREEN,
 		BLEND_SCREEN,
 		BLEND_REPLACE,
 		BLEND_REPLACE,
 		BLEND_MAX_ENUM
 		BLEND_MAX_ENUM
@@ -138,6 +140,7 @@ public:
 	{
 	{
 		SUPPORT_MULTI_CANVAS_FORMATS,
 		SUPPORT_MULTI_CANVAS_FORMATS,
 		SUPPORT_CLAMP_ZERO,
 		SUPPORT_CLAMP_ZERO,
+		SUPPORT_LIGHTEN,
 		SUPPORT_MAX_ENUM
 		SUPPORT_MAX_ENUM
 	};
 	};
 
 

+ 34 - 5
src/modules/graphics/opengl/Graphics.cpp

@@ -1079,6 +1079,28 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
 	GLenum dstRGB = GL_ZERO;
 	GLenum dstRGB = GL_ZERO;
 	GLenum dstA   = GL_ZERO;
 	GLenum dstA   = GL_ZERO;
 
 
+	if (mode == BLEND_LIGHTEN || mode == BLEND_DARKEN)
+	{
+		if (!isSupported(SUPPORT_LIGHTEN))
+			throw love::Exception("The 'lighten' and 'darken' blend modes are not supported on this system.");
+	}
+
+	if (alphamode != BLENDALPHA_PREMULTIPLIED)
+	{
+		const char *modestr = "unknown";
+		switch (mode)
+		{
+		case BLEND_LIGHTEN:
+		case BLEND_DARKEN:
+		/*case BLEND_MULTIPLY:*/ // FIXME: Uncomment for 0.11.0
+			getConstant(mode, modestr);
+			throw love::Exception("The '%s' blend mode must be used with premultiplied alpha.", modestr);
+			break;
+		default:
+			break;
+		}
+	}
+
 	switch (mode)
 	switch (mode)
 	{
 	{
 	case BLEND_ALPHA:
 	case BLEND_ALPHA:
@@ -1096,6 +1118,12 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
 		srcA = GL_ZERO;
 		srcA = GL_ZERO;
 		dstRGB = dstA = GL_ONE;
 		dstRGB = dstA = GL_ONE;
 		break;
 		break;
+	case BLEND_LIGHTEN:
+		func = GL_MAX;
+		break;
+	case BLEND_DARKEN:
+		func = GL_MIN;
+		break;
 	case BLEND_SCREEN:
 	case BLEND_SCREEN:
 		srcRGB = srcA = GL_ONE;
 		srcRGB = srcA = GL_ONE;
 		dstRGB = dstA = GL_ONE_MINUS_SRC_COLOR;
 		dstRGB = dstA = GL_ONE_MINUS_SRC_COLOR;
@@ -1609,14 +1637,13 @@ Graphics::Stats Graphics::getStats() const
 
 
 double Graphics::getSystemLimit(SystemLimit limittype) const
 double Graphics::getSystemLimit(SystemLimit limittype) const
 {
 {
+	GLfloat limits[2];
+
 	switch (limittype)
 	switch (limittype)
 	{
 	{
 	case Graphics::LIMIT_POINT_SIZE:
 	case Graphics::LIMIT_POINT_SIZE:
-		{
-			GLfloat limits[2];
-			glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, limits);
-			return (double) limits[1];
-		}
+		glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, limits);
+		return (double) limits[1];
 	case Graphics::LIMIT_TEXTURE_SIZE:
 	case Graphics::LIMIT_TEXTURE_SIZE:
 		return (double) gl.getMaxTextureSize();
 		return (double) gl.getMaxTextureSize();
 	case Graphics::LIMIT_MULTI_CANVAS:
 	case Graphics::LIMIT_MULTI_CANVAS:
@@ -1636,6 +1663,8 @@ bool Graphics::isSupported(Support feature) const
 		return Canvas::isMultiFormatMultiCanvasSupported();
 		return Canvas::isMultiFormatMultiCanvasSupported();
 	case SUPPORT_CLAMP_ZERO:
 	case SUPPORT_CLAMP_ZERO:
 		return gl.isClampZeroTextureWrapSupported();
 		return gl.isClampZeroTextureWrapSupported();
+	case SUPPORT_LIGHTEN:
+		return GLAD_VERSION_1_4 || GLAD_ES_VERSION_3_0 || GLAD_EXT_blend_minmax;
 	default:
 	default:
 		return false;
 		return false;
 	}
 	}