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);
 }
 
-void Graphics::clear(const std::vector<Colorf> &colors)
+void Graphics::clear(const std::vector<OptionalColorf> &colors)
 {
 	if (colors.size() == 0)
 		return;
 
 	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())
 		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++)
 	{
+		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};
 
 		// 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);
 		else
 		{
-			bufs.push_back(GL_COLOR_ATTACHMENT0 + i);
 			glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
 			glClearColor(c[0], c[1], c[2], c[3]);
 			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
 	// 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)
 			glDrawBuffers((int) bufs.size(), &bufs[0]);
 		else

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

@@ -62,6 +62,12 @@ class Graphics : public love::graphics::Graphics
 {
 public:
 
+	struct OptionalColorf
+	{
+		float r, g, b, a;
+		bool enabled;
+	};
+
 	Graphics();
 	virtual ~Graphics();
 
@@ -92,7 +98,7 @@ public:
 	/**
 	 * 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.

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

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