Browse Source

When multiple canvases are active at once (MRT), individual canvases can now be selectively cleared with love.graphics.clear(c1, c2, ...) by passing empty tables for the canvases that shouldn't be cleared, and color tables for the canvases that should.

Alex Szpakowski 9 years ago
parent
commit
09e6a9a434

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

@@ -448,21 +448,29 @@ void Graphics::clear(Colorf c)
 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 }
 
 
-void Graphics::clear(const std::vector<Colorf> &colors)
+void Graphics::clear(const std::vector<OptionalColorf> &colors)
 {
 {
 	if (colors.size() == 0)
 	if (colors.size() == 0)
 		return;
 		return;
 
 
 	if (states.back().canvases.size() == 0)
 	if (states.back().canvases.size() == 0)
-		return clear(colors[0]);
+	{
+		if (colors[0].enabled)
+			clear({colors[0].r, colors[0].g, colors[0].b, colors[0].a});
+
+		return;
+	}
 
 
 	if (colors.size() != states.back().canvases.size())
 	if (colors.size() != states.back().canvases.size())
 		throw love::Exception("Number of clear colors must match the number of active canvases (%ld)", states.back().canvases.size());
 		throw love::Exception("Number of clear colors must match the number of active canvases (%ld)", states.back().canvases.size());
 
 
-	std::vector<GLenum> bufs;
+	bool drawbuffermodified = false;
 
 
 	for (int i = 0; i < (int) colors.size(); i++)
 	for (int i = 0; i < (int) colors.size(); i++)
 	{
 	{
+		if (!colors[i].enabled)
+			continue;
+
 		GLfloat c[] = {colors[i].r/255.f, colors[i].g/255.f, colors[i].b/255.f, colors[i].a/255.f};
 		GLfloat c[] = {colors[i].r/255.f, colors[i].g/255.f, colors[i].b/255.f, colors[i].a/255.f};
 
 
 		// TODO: Investigate a potential bug on AMD drivers in Windows/Linux
 		// TODO: Investigate a potential bug on AMD drivers in Windows/Linux
@@ -478,10 +486,11 @@ void Graphics::clear(const std::vector<Colorf> &colors)
 			glClearBufferfv(GL_COLOR, i, c);
 			glClearBufferfv(GL_COLOR, i, c);
 		else
 		else
 		{
 		{
-			bufs.push_back(GL_COLOR_ATTACHMENT0 + i);
 			glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
 			glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
 			glClearColor(c[0], c[1], c[2], c[3]);
 			glClearColor(c[0], c[1], c[2], c[3]);
 			glClear(GL_COLOR_BUFFER_BIT);
 			glClear(GL_COLOR_BUFFER_BIT);
+
+			drawbuffermodified = true;
 		}
 		}
 	}
 	}
 
 
@@ -489,8 +498,13 @@ void Graphics::clear(const std::vector<Colorf> &colors)
 
 
 	// Revert to the expected draw buffers once we're done, if glClearBuffer
 	// Revert to the expected draw buffers once we're done, if glClearBuffer
 	// wasn't supported.
 	// wasn't supported.
-	if (!(GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0))
+	if (drawbuffermodified)
 	{
 	{
+		std::vector<GLenum> bufs;
+
+		for (int i = 0; i < (int) states.back().canvases.size(); i++)
+			bufs.push_back(GL_COLOR_ATTACHMENT0 + i);
+
 		if (bufs.size() > 1)
 		if (bufs.size() > 1)
 			glDrawBuffers((int) bufs.size(), &bufs[0]);
 			glDrawBuffers((int) bufs.size(), &bufs[0]);
 		else
 		else

+ 7 - 1
src/modules/graphics/opengl/Graphics.h

@@ -62,6 +62,12 @@ class Graphics : public love::graphics::Graphics
 {
 {
 public:
 public:
 
 
+	struct OptionalColorf
+	{
+		float r, g, b, a;
+		bool enabled;
+	};
+
 	Graphics();
 	Graphics();
 	virtual ~Graphics();
 	virtual ~Graphics();
 
 
@@ -92,7 +98,7 @@ public:
 	/**
 	/**
 	 * Clears each active canvas to a different color.
 	 * Clears each active canvas to a different color.
 	 **/
 	 **/
-	void clear(const std::vector<Colorf> &colors);
+	void clear(const std::vector<OptionalColorf> &colors);
 
 
 	/**
 	/**
 	 * Discards the contents of the screen.
 	 * Discards the contents of the screen.

+ 18 - 14
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -55,19 +55,26 @@ int w_reset(lua_State *)
 
 
 int w_clear(lua_State *L)
 int w_clear(lua_State *L)
 {
 {
-	std::vector<Colorf> colors(1);
+	Colorf color;
 
 
 	if (lua_isnoneornil(L, 1))
 	if (lua_isnoneornil(L, 1))
-		colors[0].set(0, 0, 0, 0);
+		color.set(0, 0, 0, 0);
 	else if (lua_istable(L, 1))
 	else if (lua_istable(L, 1))
 	{
 	{
-		colors.resize((size_t) lua_gettop(L));
+		std::vector<Graphics::OptionalColorf> colors((size_t) lua_gettop(L));
 
 
 		for (int i = 0; i < lua_gettop(L); i++)
 		for (int i = 0; i < lua_gettop(L); i++)
 		{
 		{
+			if (lua_isnoneornil(L, i + 1) || luax_objlen(L, i + 1) == 0)
+			{
+				colors[i].enabled = false;
+				continue;
+			}
+
 			for (int j = 1; j <= 4; j++)
 			for (int j = 1; j <= 4; j++)
 				lua_rawgeti(L, i + 1, j);
 				lua_rawgeti(L, i + 1, j);
 
 
+			colors[i].enabled = true;
 			colors[i].r = (float) luaL_checknumber(L, -4);
 			colors[i].r = (float) luaL_checknumber(L, -4);
 			colors[i].g = (float) luaL_checknumber(L, -3);
 			colors[i].g = (float) luaL_checknumber(L, -3);
 			colors[i].b = (float) luaL_checknumber(L, -2);
 			colors[i].b = (float) luaL_checknumber(L, -2);
@@ -75,22 +82,19 @@ int w_clear(lua_State *L)
 
 
 			lua_pop(L, 4);
 			lua_pop(L, 4);
 		}
 		}
+
+		luax_catchexcept(L, [&]() { instance()->clear(colors); });
+		return 0;
 	}
 	}
 	else
 	else
 	{
 	{
-		colors[0].r = (float) luaL_checknumber(L, 1);
-		colors[0].g = (float) luaL_checknumber(L, 2);
-		colors[0].b = (float) luaL_checknumber(L, 3);
-		colors[0].a = (float) luaL_optnumber(L, 4, 255);
+		color.r = (float) luaL_checknumber(L, 1);
+		color.g = (float) luaL_checknumber(L, 2);
+		color.b = (float) luaL_checknumber(L, 3);
+		color.a = (float) luaL_optnumber(L, 4, 255);
 	}
 	}
 
 
-	luax_catchexcept(L, [&]() {
-		if (colors.size() == 1)
-			instance()->clear(colors[0]);
-		else
-			instance()->clear(colors);
-	});
-
+	luax_catchexcept(L, [&]() { instance()->clear(color); });
 	return 0;
 	return 0;
 }
 }