Add new variants of love.graphics.clear for controlling how the depth and stencil buffers are cleared.

- Add love.graphics.clear(r, g, b, a [, stencilvalue, depthvalue]).
- Add love.graphics.clear(color1, color2, …, [, stencilvalue, depthvalue]).
- Add love.graphics.clear(false, stencilvalue, depthvalue).

stencilvalue and depthvalue are either true, false, or a number. True is the default behaviour and clears that buffer to the default value (0 for stencil, 1 for depth), false prevents clearing.

The third variant listed above only clears the depth and/or stencil buffers and not the color buffer.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-04-11 22:32:40 -03:00
parent 72c7602650
commit 0001b4695e
9 changed files with 194 additions and 53 deletions
+6 -9
View File
@@ -26,6 +26,7 @@
#include "common/Module.h"
#include "common/StringMap.h"
#include "common/Vector.h"
#include "common/Optional.h"
#include "StreamBuffer.h"
#include "vertex.h"
#include "Color.h"
@@ -58,6 +59,8 @@ class Text;
class Video;
class Buffer;
typedef Optional<Colorf> OptionalColorf;
const int MAX_COLOR_RENDER_TARGETS = 8;
/**
@@ -253,12 +256,6 @@ public:
}
};
struct OptionalColorf
{
Colorf c;
bool enabled;
};
struct StreamDrawRequest
{
vertex::PrimitiveMode primitiveMode = vertex::PrimitiveMode::TRIANGLES;
@@ -397,8 +394,8 @@ public:
**/
void reset();
virtual void clear(Colorf color) = 0;
virtual void clear(const std::vector<OptionalColorf> &colors) = 0;
virtual void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) = 0;
virtual void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) = 0;
virtual void discard(const std::vector<bool> &colorbuffers, bool depthstencil) = 0;
@@ -525,7 +522,7 @@ public:
/**
* Clear the stencil buffer in the active Canvas(es.)
**/
virtual void clearStencil() = 0;
virtual void clearStencil(int value) = 0;
/**
* Sets the enabled color components when rendering.
+1
View File
@@ -128,6 +128,7 @@ public:
UniformType baseType;
TextureType textureType;
bool isDepthTexture;
std::string name;
union
+8
View File
@@ -60,7 +60,11 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
gl.framebufferTexture(attachment, texType, texture, 0, layer, face);
if (isPixelFormatDepthStencil(format))
{
glClearDepth(1.0);
glClearStencil(0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
else
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -116,7 +120,11 @@ static bool createRenderbuffer(int width, int height, int &samples, PixelFormat
if (status == GL_FRAMEBUFFER_COMPLETE && (reqsamples <= 1 || samples > 1))
{
if (isPixelFormatDepthStencil(pixelformat))
{
glClearDepth(1.0);
glClearStencil(0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
else
{
// Initialize the buffer to transparent black.
+52 -15
View File
@@ -703,15 +703,36 @@ void Graphics::endPass()
}
}
void Graphics::clear(Colorf c)
void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth)
{
flushStreamDraws();
if (c.hasValue || stencil.hasValue || depth.hasValue)
flushStreamDraws();
gammaCorrectColor(c);
glClearColor(c.r, c.g, c.b, c.a);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLbitfield flags = 0;
if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
if (c.hasValue)
{
gammaCorrectColor(c.value);
glClearColor(c.value.r, c.value.g, c.value.b, c.value.a);
flags |= GL_COLOR_BUFFER_BIT;
}
if (stencil.hasValue)
{
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
if (depth.hasValue)
{
glClearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
glClear(flags);
if (flags != 0 && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
{
// This seems to be enough to fix the bug for me. Other methods I've
// tried (e.g. dummy draws) don't work in all cases.
@@ -720,9 +741,9 @@ void Graphics::clear(Colorf c)
}
}
void Graphics::clear(const std::vector<OptionalColorf> &colors)
void Graphics::clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth)
{
if (colors.size() == 0)
if (colors.size() == 0 && !stencil.hasValue && !depth.hasValue)
return;
int ncanvases = (int) states.back().renderTargets.colors.size();
@@ -730,8 +751,8 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors)
if (ncolors <= 1 && ncanvases <= 1)
{
if (colors[0].enabled)
clear(colors[0].c);
if (colors[0].hasValue)
clear(colors[0].value, stencil, depth);
return;
}
@@ -742,10 +763,10 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors)
for (int i = 0; i < ncolors; i++)
{
if (!colors[i].enabled)
if (!colors[i].hasValue)
continue;
Colorf c = colors[i].c;
Colorf c = colors[i].value;
gammaCorrectColor(c);
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0)
@@ -775,7 +796,22 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors)
glDrawBuffers(ncanvases, bufs);
}
glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLbitfield flags = 0;
if (stencil.hasValue)
{
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
if (depth.hasValue)
{
glClearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
glClear(flags);
if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
{
@@ -1250,9 +1286,10 @@ void Graphics::setStencilTest()
setStencilTest(COMPARE_ALWAYS, 0);
}
void Graphics::clearStencil()
void Graphics::clearStencil(int value)
{
glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearStencil(value);
glClear(GL_STENCIL_BUFFER_BIT);
}
void Graphics::setColor(Colorf c)
+3 -3
View File
@@ -88,8 +88,8 @@ public:
void flushStreamDraws() override;
void clear(Colorf color) override;
void clear(const std::vector<OptionalColorf> &colors) override;
void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override;
void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) override;
void discard(const std::vector<bool> &colorbuffers, bool depthstencil) override;
@@ -109,7 +109,7 @@ public:
void setStencilTest(CompareMode compare, int value) override;
void setStencilTest() override;
void clearStencil() override;
void clearStencil(int value) override;
void setColorMask(ColorMask mask) override;
+69 -26
View File
@@ -65,46 +65,84 @@ int w_reset(lua_State *)
int w_clear(lua_State *L)
{
Colorf color;
OptionalColorf color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
std::vector<OptionalColorf> colors;
if (lua_isnoneornil(L, 1))
color.set(0.0, 0.0, 0.0, 0.0);
else if (lua_istable(L, 1))
OptionalInt stencil(0);
OptionalDouble depth(1.0);
int argtype = lua_type(L, 1);
int startidx = -1;
if (argtype == LUA_TTABLE)
{
std::vector<Graphics::OptionalColorf> colors((size_t) lua_gettop(L));
int maxn = lua_gettop(L);
colors.reserve(maxn);
for (int i = 0; i < lua_gettop(L); i++)
for (int i = 0; i < maxn; i++)
{
if (lua_isnoneornil(L, i + 1) || luax_objlen(L, i + 1) == 0)
argtype = lua_type(L, i + 1);
if (argtype == LUA_TNUMBER || argtype == LUA_TBOOLEAN)
{
colors[i].enabled = false;
startidx = i + 1;
break;
}
else if (argtype == LUA_TNIL || argtype == LUA_TNONE || luax_objlen(L, i + 1) == 0)
{
colors.push_back(OptionalColorf());
continue;
}
for (int j = 1; j <= 4; j++)
lua_rawgeti(L, i + 1, j);
colors[i].enabled = true;
colors[i].c.r = (float) luaL_checknumber(L, -4);
colors[i].c.g = (float) luaL_checknumber(L, -3);
colors[i].c.b = (float) luaL_checknumber(L, -2);
colors[i].c.a = (float) luaL_optnumber(L, -1, 1.0);
OptionalColorf c;
c.hasValue = true;
c.value.r = (float) luaL_checknumber(L, -4);
c.value.g = (float) luaL_checknumber(L, -3);
c.value.b = (float) luaL_checknumber(L, -2);
c.value.a = (float) luaL_optnumber(L, -1, 1.0);
colors.push_back(c);
lua_pop(L, 4);
}
luax_catchexcept(L, [&]() { instance()->clear(colors); });
return 0;
}
else
else if (argtype == LUA_TBOOLEAN)
{
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, 1.0);
color.hasValue = luax_toboolean(L, 1);
startidx = 2;
}
else if (argtype != LUA_TNONE && argtype != LUA_TNIL)
{
color.hasValue = true;
color.value.r = (float) luaL_checknumber(L, 1);
color.value.g = (float) luaL_checknumber(L, 2);
color.value.b = (float) luaL_checknumber(L, 3);
color.value.a = (float) luaL_optnumber(L, 4, 1.0);
startidx = 5;
}
luax_catchexcept(L, [&]() { instance()->clear(color); });
if (startidx >= 0)
{
argtype = lua_type(L, startidx);
if (argtype == LUA_TBOOLEAN)
stencil.hasValue = luax_toboolean(L, startidx);
else if (argtype == LUA_TNUMBER)
stencil.value = (int) luaL_checkinteger(L, startidx);
argtype = lua_type(L, startidx + 1);
if (argtype == LUA_TBOOLEAN)
depth.hasValue = luax_toboolean(L, startidx + 1);
else if (argtype == LUA_TNUMBER)
depth.value = luaL_checknumber(L, startidx + 1);
}
if (colors.empty())
luax_catchexcept(L, [&]() { instance()->clear(color, stencil, depth); });
else
luax_catchexcept(L, [&]() { instance()->clear(colors, stencil, depth); });
return 0;
}
@@ -128,8 +166,8 @@ int w_discard(lua_State *L)
colorbuffers = std::vector<bool>(numbuffers, discardcolor);
}
bool stencil = luax_optboolean(L, 2, true);
instance()->discard(colorbuffers, stencil);
bool depthstencil = luax_optboolean(L, 2, true);
instance()->discard(colorbuffers, depthstencil);
return 0;
}
@@ -463,8 +501,13 @@ int w_stencil(lua_State *L)
int stencilvalue = (int) luaL_optnumber(L, 3, 1);
// Fourth argument: whether to keep the contents of the stencil buffer.
if (lua_toboolean(L, 4) == 0)
instance()->clearStencil();
int argtype = lua_type(L, 4);
if (argtype == LUA_TNONE || argtype == LUA_TNIL || (argtype == LUA_TBOOLEAN && luax_toboolean(L, 4) == false))
instance()->clearStencil(0);
else if (argtype == LUA_TNUMBER)
instance()->clearStencil((int) luaL_checkinteger(L, 4));
else if (argtype != LUA_TBOOLEAN)
luaL_checktype(L, 4, LUA_TBOOLEAN);
luax_catchexcept(L, [&](){ instance()->drawToStencilBuffer(action, stencilvalue); });