Merged bartbes/love-experiments/stencil-functions into minor

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2014-08-09 20:18:09 -03:00
7 changed files with 161 additions and 61 deletions
+18
View File
@@ -109,6 +109,16 @@ bool Graphics::getConstant(StackType in, const char *&out)
return stackTypes.find(in, out);
}
bool Graphics::getConstant(const char *in, ClearType &out)
{
return clearTypes.find(in, out);
}
bool Graphics::getConstant(ClearType in, const char *&out)
{
return clearTypes.find(in, out);
}
StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] =
{
{ "line", Graphics::DRAW_LINE },
@@ -183,5 +193,13 @@ StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM>::Entry Graphics::stackT
StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM> Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries));
StringMap<Graphics::ClearType, Graphics::CLEAR_MAX_ENUM>::Entry Graphics::clearTypeEntries[] =
{
{"all", Graphics::CLEAR_ALL},
{"stencil", Graphics::CLEAR_STENCIL},
};
StringMap<Graphics::ClearType, Graphics::CLEAR_MAX_ENUM> Graphics::clearTypes(Graphics::clearTypeEntries, sizeof(Graphics::clearTypeEntries));
} // graphics
} // love
+13
View File
@@ -103,6 +103,13 @@ public:
STACK_MAX_ENUM
};
enum ClearType
{
CLEAR_ALL,
CLEAR_STENCIL,
CLEAR_MAX_ENUM
};
struct RendererInfo
{
std::string name;
@@ -158,6 +165,9 @@ public:
static bool getConstant(const char *in, StackType &out);
static bool getConstant(StackType in, const char *&out);
static bool getConstant(const char *in, ClearType &out);
static bool getConstant(ClearType in, const char *&out);
private:
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
@@ -184,6 +194,9 @@ private:
static StringMap<StackType, STACK_MAX_ENUM>::Entry stackTypeEntries[];
static StringMap<StackType, STACK_MAX_ENUM> stackTypes;
static StringMap<ClearType, CLEAR_MAX_ENUM>::Entry clearTypeEntries[];
static StringMap<ClearType, CLEAR_MAX_ENUM> clearTypes;
}; // Graphics
} // graphics
+7 -1
View File
@@ -823,7 +823,7 @@ void Canvas::clear(Color c)
// Don't use the state-shadowed gl.setClearColor because we want to save
// the previous clear color.
glClearColor(glcolor[0], glcolor[1], glcolor[2], glcolor[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (attachedCanvases.size() > 0)
strategy->setAttachments(attachedCanvases);
@@ -850,6 +850,12 @@ bool Canvas::checkCreateStencil()
bool success = strategy->createStencil(width, height, msaa_samples, depth_stencil);
if (success)
{
// We don't want the stencil buffer filled with garbage.
glClear(GL_STENCIL_BUFFER_BIT);
}
if (current && current != this)
strategy->bindFBO(current->fbo);
else if (!current)
+75 -21
View File
@@ -47,7 +47,7 @@ Graphics::Graphics()
: width(0)
, height(0)
, created(false)
, activeStencil(false)
, writingToStencil(false)
, displayedMinReqWarning(false)
{
states.reserve(10);
@@ -95,6 +95,8 @@ void Graphics::restoreState(const DisplayState &s)
else
setScissor();
setStencilTest(s.stencilTest, s.stencilInvert);
setFont(s.font.get());
setShader(s.shader.get());
setCanvas(s.canvases);
@@ -132,6 +134,9 @@ void Graphics::restoreStateChecked(const DisplayState &s)
setScissor();
}
if (s.stencilTest != cur.stencilTest || s.stencilInvert != cur.stencilInvert)
setStencilTest(s.stencilTest, s.stencilInvert);
setFont(s.font.get());
setShader(s.shader.get());
@@ -350,14 +355,27 @@ void Graphics::setDebug(bool enable)
void Graphics::reset()
{
DisplayState s;
discardStencil();
origin();
drawToStencilBuffer(false);
restoreState(s);
origin();
}
void Graphics::clear()
void Graphics::clear(ClearType type)
{
glClear(GL_COLOR_BUFFER_BIT);
GLbitfield mask = 0;
switch (type)
{
case CLEAR_ALL:
default:
mask = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
break;
case CLEAR_STENCIL:
mask = GL_STENCIL_BUFFER_BIT;
break;
}
glClear(mask);
}
void Graphics::present()
@@ -409,38 +427,68 @@ bool Graphics::getScissor(int &x, int &y, int &width, int &height) const
return states.back().scissor;
}
void Graphics::defineStencil()
void Graphics::drawToStencilBuffer(bool enable)
{
if (writingToStencil == enable)
return;
writingToStencil = enable;
if (!enable)
{
const DisplayState &state = states.back();
// Revert the color write mask.
setColorMask(state.colorMask);
// Use the user-set stencil test state when writes are disabled.
setStencilTest(state.stencilTest, state.stencilInvert);
return;
}
// Make sure the active canvas has a stencil buffer.
if (Canvas::current)
Canvas::current->checkCreateStencil();
// Disable color writes but don't save the mask values.
// Disable color writes but don't save the state for it.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glClear(GL_STENCIL_BUFFER_BIT);
// The stencil test must be enabled in order to write to the stencil buffer.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
activeStencil = true;
}
void Graphics::useStencil(bool invert)
void Graphics::setStencilTest(bool enable, bool invert)
{
glStencilFunc(GL_EQUAL, (GLint)(!invert), 1); // invert ? 0 : 1
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
setColorMask(states.back().colorMask);
}
DisplayState &state = states.back();
state.stencilTest = enable;
state.stencilInvert = invert;
void Graphics::discardStencil()
{
if (!activeStencil)
if (writingToStencil)
return;
setColorMask(states.back().colorMask);
glDisable(GL_STENCIL_TEST);
activeStencil = false;
if (!enable)
{
glDisable(GL_STENCIL_TEST);
return;
}
// Make sure the active canvas has a stencil buffer.
if (Canvas::current)
Canvas::current->checkCreateStencil();
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, invert ? 0 : 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
void Graphics::getStencilTest(bool &enable, bool &invert)
{
const DisplayState &state = states.back();
enable = state.stencilTest;
invert = state.stencilInvert;
}
Image *Graphics::newImage(love::image::ImageData *data, const Image::Flags &flags)
@@ -1279,6 +1327,8 @@ Graphics::DisplayState::DisplayState()
, pointSize(1.0f)
, scissor(false)
, scissorBox()
, stencilTest(false)
, stencilInvert(false)
, font(nullptr)
, shader(nullptr)
, wireframe(false)
@@ -1298,6 +1348,8 @@ Graphics::DisplayState::DisplayState(const DisplayState &other)
, pointSize(other.pointSize)
, scissor(other.scissor)
, scissorBox(other.scissorBox)
, stencilTest(other.stencilTest)
, stencilInvert(other.stencilInvert)
, font(other.font)
, shader(other.shader)
, canvases(other.canvases)
@@ -1322,6 +1374,8 @@ Graphics::DisplayState &Graphics::DisplayState::operator = (const DisplayState &
pointSize = other.pointSize;
scissor = other.scissor;
scissorBox = other.scissorBox;
stencilTest = other.stencilTest;
stencilInvert = other.stencilInvert;
font = other.font;
shader = other.shader;
+14 -16
View File
@@ -80,7 +80,7 @@ public:
/**
* Clears the screen.
**/
void clear();
void clear(ClearType type = CLEAR_ALL);
/**
* Flips buffers. (Rendered geometry is presented on screen).
@@ -124,22 +124,16 @@ public:
bool getScissor(int &x, int &y, int &width, int &height) const;
/**
* Enables the stencil buffer and set stencil function to fill it
*/
void defineStencil();
* Enables or disables drawing to the stencil buffer. When enabled, the
* color buffer is disabled.
**/
void drawToStencilBuffer(bool enable);
/**
* Set stencil function to mask the following drawing calls using
* the current stencil buffer
* @param invert Invert the mask, i.e. draw everywhere expect where
* the mask is defined.
*/
void useStencil(bool invert = false);
/**
* Disables the stencil buffer
*/
void discardStencil();
* Sets whether stencil testing is enabled.
**/
void setStencilTest(bool enable, bool invert);
void getStencilTest(bool &enable, bool &invert);
/**
* Creates an Image object with padding and/or optimization.
@@ -443,6 +437,10 @@ private:
bool scissor;
OpenGL::Viewport scissorBox;
// Stencil.
bool stencilTest;
bool stencilInvert;
Object::StrongRef<Font> font;
Object::StrongRef<Shader> shader;
@@ -471,7 +469,7 @@ private:
int height;
bool created;
bool activeStencil;
bool writingToStencil;
std::vector<DisplayState> states;
std::vector<StackType> stackTypes; // Keeps track of the pushed stack types.
+31 -21
View File
@@ -44,9 +44,15 @@ int w_reset(lua_State *)
return 0;
}
int w_clear(lua_State *)
int w_clear(lua_State *L)
{
instance()->clear();
Graphics::ClearType type = Graphics::CLEAR_ALL;
const char *tname = lua_isnoneornil(L, 1) ? nullptr : luaL_checkstring(L, 1);
if (tname && !Graphics::getConstant(tname, type))
return luaL_error(L, "Invalid graphics clear type: %s", tname);
instance()->clear(type);
return 0;
}
@@ -118,32 +124,35 @@ int w_getScissor(lua_State *L)
return 4;
}
static int setStencil(lua_State *L, bool invert)
int w_stencil(lua_State *L)
{
// no argument -> clear stencil
if (lua_isnoneornil(L, 1))
{
instance()->discardStencil();
return 0;
}
luaL_checktype(L, 1, LUA_TFUNCTION);
instance()->defineStencil();
lua_call(L, lua_gettop(L) - 1, 0); // call stencil(...)
instance()->useStencil(invert);
instance()->drawToStencilBuffer(true);
// Call stencilfunc(...)
lua_call(L, lua_gettop(L) - 1, 0);
instance()->drawToStencilBuffer(false);
return 0;
}
int w_setStencil(lua_State *L)
int w_setStencilTest(lua_State *L)
{
return setStencil(L, false);
bool enable = luax_toboolean(L, 1);
bool invert = luax_toboolean(L, 2);
instance()->setStencilTest(enable, invert);
return 0;
}
int w_setInvertedStencil(lua_State *L)
int w_getStencilTest(lua_State *L)
{
return setStencil(L, true);
bool enabled, inverted;
instance()->getStencilTest(enabled, inverted);
luax_pushboolean(L, enabled);
luax_pushboolean(L, inverted);
return 2;
}
static const char *imageFlagName(Image::FlagType flagtype)
@@ -869,8 +878,8 @@ int w_newScreenshot(lua_State *L)
int w_setCanvas(lua_State *L)
{
// discard stencil testing
instance()->discardStencil();
// Disable stencil writes.
instance()->drawToStencilBuffer(false);
// called with none -> reset to default buffer
if (lua_isnoneornil(L, 1))
@@ -1414,8 +1423,9 @@ static const luaL_Reg functions[] =
{ "setScissor", w_setScissor },
{ "getScissor", w_getScissor },
{ "setStencil", w_setStencil },
{ "setInvertedStencil", w_setInvertedStencil },
{ "stencil", w_stencil },
{ "setStencilTest", w_setStencilTest },
{ "getStencilTest", w_getStencilTest },
{ "point", w_point },
{ "line", w_line },
+3 -2
View File
@@ -48,8 +48,9 @@ int w_getHeight(lua_State *L);
int w_getDimensions(lua_State *L);
int w_setScissor(lua_State *L);
int w_getScissor(lua_State *L);
int w_setStencil(lua_State *L);
int w_setInvertedStencil(lua_State *L);
int w_stencil(lua_State *L);
int w_setStencilTest(lua_State *L);
int w_getStencilTest(lua_State *L);
int w_newImage(lua_State *L);
int w_newQuad(lua_State *L);
int w_newFont(lua_State *L);