mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
The "alpha" blend mode now outputs more useful/intuitive alpha values (thanks Boolsheet)
See https://love2d.org/forums/viewtopic.php?f=4&t=16223 and http://www.opengl.org/discussion_boards/showthread.php/167554-FBO-and-blending
This commit is contained in:
@@ -114,7 +114,7 @@ bool Graphics::setMode(int width, int height, bool fullscreen, bool vsync, int f
|
|||||||
// Unload all volatile objects. These must be reloaded after
|
// Unload all volatile objects. These must be reloaded after
|
||||||
// the display mode change.
|
// the display mode change.
|
||||||
Volatile::unloadAll();
|
Volatile::unloadAll();
|
||||||
|
|
||||||
uninitializeContext();
|
uninitializeContext();
|
||||||
|
|
||||||
bool success = currentWindow->setWindow(width, height, fullscreen, vsync, fsaa);
|
bool success = currentWindow->setWindow(width, height, fullscreen, vsync, fsaa);
|
||||||
@@ -502,37 +502,76 @@ Font *Graphics::getFont() const
|
|||||||
|
|
||||||
void Graphics::setBlendMode(Graphics::BlendMode mode)
|
void Graphics::setBlendMode(Graphics::BlendMode mode)
|
||||||
{
|
{
|
||||||
if (GLEE_VERSION_1_4 || GLEE_ARB_imaging)
|
const int gl_1_4 = GLEE_VERSION_1_4;
|
||||||
|
|
||||||
|
GLenum func = GL_FUNC_ADD;
|
||||||
|
GLenum src_rgb = GL_ONE;
|
||||||
|
GLenum src_a = GL_ONE;
|
||||||
|
GLenum dst_rgb = GL_ZERO;
|
||||||
|
GLenum dst_a = GL_ZERO;
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
{
|
{
|
||||||
if (mode == BLEND_SUBTRACTIVE)
|
case BLEND_ALPHA:
|
||||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
if (gl_1_4 || GLEE_EXT_blend_func_separate)
|
||||||
|
{
|
||||||
|
src_rgb = GL_SRC_ALPHA;
|
||||||
|
src_a = GL_ONE;
|
||||||
|
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
{
|
||||||
|
// Fallback for OpenGL implementations without support for separate blend functions.
|
||||||
|
// This will most likely only be used for the Microsoft software renderer and
|
||||||
|
// since it's still stuck with OpenGL 1.1, the only expected difference is a
|
||||||
|
// different alpha value when reading back the default framebuffer (newScreenshot).
|
||||||
|
src_rgb = src_a = GL_SRC_ALPHA;
|
||||||
|
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLEND_MULTIPLICATIVE:
|
||||||
|
src_rgb = src_a = GL_DST_COLOR;
|
||||||
|
dst_rgb = dst_a = GL_ZERO;
|
||||||
|
break;
|
||||||
|
case BLEND_PREMULTIPLIED:
|
||||||
|
src_rgb = src_a = GL_ONE;
|
||||||
|
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
break;
|
||||||
|
case BLEND_SUBTRACTIVE:
|
||||||
|
func = GL_FUNC_REVERSE_SUBTRACT;
|
||||||
|
case BLEND_ADDITIVE:
|
||||||
|
src_rgb = src_a = GL_SRC_ALPHA;
|
||||||
|
dst_rgb = dst_a = GL_ONE;
|
||||||
|
break;
|
||||||
|
case BLEND_NONE:
|
||||||
|
default:
|
||||||
|
src_rgb = src_a = GL_ONE;
|
||||||
|
dst_rgb = dst_a = GL_ZERO;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gl_1_4 || GLEE_ARB_imaging)
|
||||||
|
glBlendEquation(func);
|
||||||
else if (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract)
|
else if (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract)
|
||||||
{
|
glBlendEquationEXT(func);
|
||||||
if (mode == BLEND_SUBTRACTIVE)
|
|
||||||
glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
|
|
||||||
else
|
|
||||||
glBlendEquationEXT(GL_FUNC_ADD_EXT);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mode == BLEND_SUBTRACTIVE)
|
if (func == GL_FUNC_REVERSE_SUBTRACT)
|
||||||
throw Exception("This graphics card does not support the subtract blend mode!");
|
throw Exception("This graphics card does not support the subtractive blend mode!");
|
||||||
// GL_FUNC_ADD is the default even without access to glBlendEquation, so that'll still work.
|
// GL_FUNC_ADD is the default even without access to glBlendEquation, so that'll still work.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == BLEND_ALPHA)
|
if (src_rgb == src_a && dst_rgb == dst_a)
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(src_rgb, dst_rgb);
|
||||||
else if (mode == BLEND_MULTIPLICATIVE)
|
else
|
||||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
{
|
||||||
else if (mode == BLEND_PREMULTIPLIED)
|
if (gl_1_4)
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFuncSeparate(src_rgb, dst_rgb, src_a, dst_a);
|
||||||
else if (mode == BLEND_NONE)
|
else if (GLEE_EXT_blend_func_separate)
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
glBlendFuncSeparateEXT(src_rgb, dst_rgb, src_a, dst_a);
|
||||||
else // mode == BLEND_ADDITIVE || mode == BLEND_SUBTRACTIVE
|
else
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
throw Exception("This graphics card does not support separated rgb and alpha blend functions!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setColorMode(Graphics::ColorMode mode)
|
void Graphics::setColorMode(Graphics::ColorMode mode)
|
||||||
@@ -551,29 +590,50 @@ void Graphics::setColorMode(Graphics::ColorMode mode)
|
|||||||
|
|
||||||
Graphics::BlendMode Graphics::getBlendMode() const
|
Graphics::BlendMode Graphics::getBlendMode() const
|
||||||
{
|
{
|
||||||
GLint dst, src;
|
const int gl_1_4 = GLEE_VERSION_1_4;
|
||||||
glGetIntegerv(GL_BLEND_DST, &dst);
|
|
||||||
glGetIntegerv(GL_BLEND_SRC, &src);
|
|
||||||
|
|
||||||
|
GLint src_rgb, src_a, dst_rgb, dst_a;
|
||||||
GLint equation = GL_FUNC_ADD;
|
GLint equation = GL_FUNC_ADD;
|
||||||
|
|
||||||
if (GLEE_VERSION_1_4 || GLEE_ARB_imaging || (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract))
|
if (gl_1_4 || GLEE_EXT_blend_func_separate)
|
||||||
|
{
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_RGB, &src_rgb);
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_ALPHA, &src_a);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_RGB, &dst_rgb);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_ALPHA, &dst_a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGetIntegerv(GL_BLEND_SRC, &src_rgb);
|
||||||
|
glGetIntegerv(GL_BLEND_DST, &dst_rgb);
|
||||||
|
src_a = src_rgb;
|
||||||
|
dst_a = dst_rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_1_4 || GLEE_ARB_imaging || (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract))
|
||||||
glGetIntegerv(GL_BLEND_EQUATION, &equation);
|
glGetIntegerv(GL_BLEND_EQUATION, &equation);
|
||||||
|
|
||||||
if (equation == GL_FUNC_REVERSE_SUBTRACT) // && src == GL_SRC_ALPHA && dst == GL_ONE
|
if (equation == GL_FUNC_REVERSE_SUBTRACT) // && src == GL_SRC_ALPHA && dst == GL_ONE
|
||||||
return BLEND_SUBTRACTIVE;
|
return BLEND_SUBTRACTIVE;
|
||||||
else if (src == GL_SRC_ALPHA && dst == GL_ONE) // && equation == GL_FUNC_ADD
|
// Everything else has equation == GL_FUNC_ADD.
|
||||||
return BLEND_ADDITIVE;
|
else if (src_rgb == src_a && dst_rgb == dst_a)
|
||||||
else if (src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) // && equation == GL_FUNC_ADD
|
{
|
||||||
|
if (src_rgb == GL_SRC_ALPHA && dst_rgb == GL_ONE)
|
||||||
|
return BLEND_ADDITIVE;
|
||||||
|
else if (src_rgb == GL_SRC_ALPHA && dst_rgb == GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
return BLEND_ALPHA; // alpha blend mode fallback for very old OpenGL versions.
|
||||||
|
else if (src_rgb == GL_DST_COLOR && dst_rgb == GL_ZERO)
|
||||||
|
return BLEND_MULTIPLICATIVE;
|
||||||
|
else if (src_rgb == GL_ONE && dst_rgb == GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
return BLEND_PREMULTIPLIED;
|
||||||
|
else if (src_rgb == GL_ONE && dst_rgb == GL_ZERO)
|
||||||
|
return BLEND_NONE;
|
||||||
|
}
|
||||||
|
else if (src_rgb == GL_SRC_ALPHA && src_a == GL_ONE &&
|
||||||
|
dst_rgb == GL_ONE_MINUS_SRC_ALPHA && dst_a == GL_ONE_MINUS_SRC_ALPHA)
|
||||||
return BLEND_ALPHA;
|
return BLEND_ALPHA;
|
||||||
else if (src == GL_DST_COLOR && dst == GL_ZERO) // && equation == GL_FUNC_ADD
|
|
||||||
return BLEND_MULTIPLICATIVE;
|
|
||||||
else if (src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) // && equation == GL_FUNC_ADD
|
|
||||||
return BLEND_PREMULTIPLIED;
|
|
||||||
else if (src == GL_ONE && dst == GL_ZERO)
|
|
||||||
return BLEND_NONE;
|
|
||||||
|
|
||||||
return BLEND_MAX_ENUM; // Should never be reached.
|
throw Exception("Unknown blend mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics::ColorMode Graphics::getColorMode() const
|
Graphics::ColorMode Graphics::getColorMode() const
|
||||||
|
|||||||
@@ -642,13 +642,19 @@ int w_setDefaultImageFilter(lua_State *L)
|
|||||||
|
|
||||||
int w_getBlendMode(lua_State *L)
|
int w_getBlendMode(lua_State *L)
|
||||||
{
|
{
|
||||||
Graphics::BlendMode mode = instance->getBlendMode();
|
try
|
||||||
const char *str;
|
{
|
||||||
if (!Graphics::getConstant(mode, str))
|
Graphics::BlendMode mode = instance->getBlendMode();
|
||||||
return luaL_error(L, "Invalid blend mode: %s", str);
|
const char *str;
|
||||||
|
if (!Graphics::getConstant(mode, str))
|
||||||
lua_pushstring(L, str);
|
return luaL_error(L, "Unknown blend mode");
|
||||||
return 1;
|
lua_pushstring(L, str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (love::Exception &e)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "%s", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_getColorMode(lua_State *L)
|
int w_getColorMode(lua_State *L)
|
||||||
@@ -656,8 +662,7 @@ int w_getColorMode(lua_State *L)
|
|||||||
Graphics::ColorMode mode = instance->getColorMode();
|
Graphics::ColorMode mode = instance->getColorMode();
|
||||||
const char *str;
|
const char *str;
|
||||||
if (!Graphics::getConstant(mode, str))
|
if (!Graphics::getConstant(mode, str))
|
||||||
return luaL_error(L, "Invalid color mode: %s", str);
|
return luaL_error(L, "Unknown color mode");
|
||||||
|
|
||||||
lua_pushstring(L, str);
|
lua_pushstring(L, str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -667,8 +672,10 @@ int w_getDefaultImageFilter(lua_State *L)
|
|||||||
const Image::Filter &f = instance->getDefaultImageFilter();
|
const Image::Filter &f = instance->getDefaultImageFilter();
|
||||||
const char *minstr;
|
const char *minstr;
|
||||||
const char *magstr;
|
const char *magstr;
|
||||||
Image::getConstant(f.min, minstr);
|
if (!Image::getConstant(f.min, minstr))
|
||||||
Image::getConstant(f.mag, magstr);
|
return luaL_error(L, "Unknown filter mode for argument #1");
|
||||||
|
if (!Image::getConstant(f.mag, magstr))
|
||||||
|
return luaL_error(L, "Unknown filter mode for argument #2");
|
||||||
lua_pushstring(L, minstr);
|
lua_pushstring(L, minstr);
|
||||||
lua_pushstring(L, magstr);
|
lua_pushstring(L, magstr);
|
||||||
return 2;
|
return 2;
|
||||||
@@ -719,7 +726,8 @@ int w_getLineStyle(lua_State *L)
|
|||||||
{
|
{
|
||||||
Graphics::LineStyle style = instance->getLineStyle();
|
Graphics::LineStyle style = instance->getLineStyle();
|
||||||
const char *str;
|
const char *str;
|
||||||
Graphics::getConstant(style, str);
|
if (!Graphics::getConstant(style, str))
|
||||||
|
return luaL_error(L, "Unknown line style");
|
||||||
lua_pushstring(L, str);
|
lua_pushstring(L, str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -770,7 +778,8 @@ int w_getPointStyle(lua_State *L)
|
|||||||
{
|
{
|
||||||
Graphics::PointStyle style = instance->getPointStyle();
|
Graphics::PointStyle style = instance->getPointStyle();
|
||||||
const char *str;
|
const char *str;
|
||||||
Graphics::getConstant(style, str);
|
if (!Graphics::getConstant(style, str))
|
||||||
|
return luaL_error(L, "Unknown point style");
|
||||||
lua_pushstring(L, str);
|
lua_pushstring(L, str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -858,7 +867,10 @@ int w_isSupported(lua_State *L)
|
|||||||
{
|
{
|
||||||
const char *str = luaL_checkstring(L, i);
|
const char *str = luaL_checkstring(L, i);
|
||||||
if (!Graphics::getConstant(str, support))
|
if (!Graphics::getConstant(str, support))
|
||||||
|
{
|
||||||
supported = false;
|
supported = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
switch (support)
|
switch (support)
|
||||||
{
|
{
|
||||||
case Graphics::SUPPORT_CANVAS:
|
case Graphics::SUPPORT_CANVAS:
|
||||||
|
|||||||
Reference in New Issue
Block a user