lovr.graphics.stencil;

This commit is contained in:
bjorn 2017-12-18 19:48:28 -08:00
parent 8acd7444af
commit 77d8b96cfd
6 changed files with 99 additions and 26 deletions

View File

@ -27,6 +27,7 @@ map_int_t MatrixTypes;
map_int_t MeshAttributeTypes;
map_int_t MeshDrawModes;
map_int_t MeshUsages;
map_int_t StencilActions;
map_int_t TextureFormats;
map_int_t VerticalAligns;
map_int_t Windings;
@ -72,6 +73,12 @@ static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
}
}
static void stencilCallback(void* userdata) {
lua_State* L = userdata;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_call(L, 0, 0);
}
// Base
int l_lovrGraphicsInit(lua_State* L) {
@ -161,6 +168,14 @@ int l_lovrGraphicsInit(lua_State* L) {
map_set(&MeshUsages, "dynamic", MESH_DYNAMIC);
map_set(&MeshUsages, "stream", MESH_STREAM);
map_init(&StencilActions);
map_set(&StencilActions, "replace", STENCIL_REPLACE);
map_set(&StencilActions, "increment", STENCIL_INCREMENT);
map_set(&StencilActions, "decrement", STENCIL_DECREMENT);
map_set(&StencilActions, "incrementwrap", STENCIL_INCREMENT_WRAP);
map_set(&StencilActions, "decrementwrap", STENCIL_DECREMENT_WRAP);
map_set(&StencilActions, "invert", STENCIL_INVERT);
map_init(&TextureFormats);
map_set(&TextureFormats, "rgb", FORMAT_RGB);
map_set(&TextureFormats, "rgba", FORMAT_RGBA);
@ -238,7 +253,8 @@ int l_lovrGraphicsReset(lua_State* L) {
int l_lovrGraphicsClear(lua_State* L) {
bool color = lua_gettop(L) < 1 || lua_toboolean(L, 1);
bool depth = lua_gettop(L) < 2 || lua_toboolean(L, 2);
lovrGraphicsClear(color, depth);
bool stencil = lua_gettop(L) < 3 || lua_toboolean(L, 3);
lovrGraphicsClear(color, depth, stencil);
return 0;
}
@ -726,6 +742,19 @@ int l_lovrGraphicsPrint(lua_State* L) {
return 0;
}
int l_lovrGraphicsStencil(lua_State* L) {
luaL_checktype(L, 1, LUA_TFUNCTION);
StencilAction action = *(StencilAction*) luax_optenum(L, 2, "replace", &StencilActions, "stencil action");
int replaceValue = luaL_optinteger(L, 3, 1);
bool keepValues = lua_toboolean(L, 4);
if (!keepValues) {
lovrGraphicsClear(false, false, true);
}
lua_settop(L, 1);
lovrGraphicsStencil(action, replaceValue, stencilCallback, L);
return 0;
}
// Types
int l_lovrGraphicsNewAnimator(lua_State* L) {
@ -1054,6 +1083,7 @@ const luaL_Reg lovrGraphics[] = {
{ "sphere", l_lovrGraphicsSphere },
{ "skybox", l_lovrGraphicsSkybox },
{ "print", l_lovrGraphicsPrint },
{ "stencil", l_lovrGraphicsStencil },
{ "newAnimator", l_lovrGraphicsNewAnimator },
{ "newCanvas", l_lovrGraphicsNewCanvas },
{ "newFont", l_lovrGraphicsNewFont },

View File

@ -78,7 +78,7 @@ Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasType
}
lovrAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Error creating Canvas");
lovrGraphicsClear(true, true);
lovrGraphicsClear(true, true, true);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return canvas;

View File

@ -80,9 +80,9 @@ void lovrGraphicsReset() {
lovrGraphicsOrigin();
}
void lovrGraphicsClear(bool color, bool depth) {
if (!color && !depth) return;
glClear((color ? GL_COLOR_BUFFER_BIT : 0) | (depth ? GL_DEPTH_BUFFER_BIT : 0));
void lovrGraphicsClear(bool color, bool depth, bool stencil) {
if (!color && !depth && !stencil) return;
glClear((color ? GL_COLOR_BUFFER_BIT : 0) | (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0));
}
void lovrGraphicsPresent() {
@ -451,26 +451,33 @@ void lovrGraphicsGetStencilTest(CompareMode* mode, int* value) {
}
void lovrGraphicsSetStencilTest(CompareMode mode, int value) {
if (mode != state.stencilMode || value != state.stencilValue) {
state.stencilMode = mode;
state.stencilValue = value;
if (mode != COMPARE_NONE) {
state.stencilMode = mode;
state.stencilValue = value;
if (state.stencilWriting) {
return;
}
if (mode != COMPARE_NONE) {
if (!state.stencilEnabled) {
glEnable(GL_STENCIL_TEST);
GLenum glMode = mode;
switch (mode) {
case COMPARE_LESS: glMode = GL_GREATER; break;
case COMPARE_LEQUAL: glMode = GL_GEQUAL; break;
case COMPARE_GEQUAL: glMode = GL_LEQUAL; break;
case COMPARE_GREATER: glMode = GL_LESS; break;
default: break;
}
glStencilFunc(glMode, value, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
} else {
glDisable(GL_STENCIL_TEST);
state.stencilEnabled = true;
}
GLenum glMode = mode;
switch (mode) {
case COMPARE_LESS: glMode = GL_GREATER; break;
case COMPARE_LEQUAL: glMode = GL_GEQUAL; break;
case COMPARE_GEQUAL: glMode = GL_LEQUAL; break;
case COMPARE_GREATER: glMode = GL_LESS; break;
default: break;
}
glStencilFunc(glMode, value, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
} else if (state.stencilEnabled) {
glDisable(GL_STENCIL_TEST);
state.stencilEnabled = false;
}
}
@ -1063,6 +1070,28 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
lovrGraphicsPop();
}
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata) {
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
if (!state.stencilEnabled) {
glEnable(GL_STENCIL_TEST);
state.stencilEnabled = true;
}
glStencilFunc(GL_ALWAYS, replaceValue, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, action);
state.stencilWriting = true;
callback(userdata);
state.stencilWriting = false;
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
lovrGraphicsSetStencilTest(state.stencilMode, state.stencilValue);
}
// Internal State
void lovrGraphicsPushView() {
if (++state.view >= MAX_VIEWS) {

View File

@ -15,6 +15,8 @@
#define DEFAULT_SHADER_COUNT 4
#define MAX_TEXTURES 16
typedef void (*StencilCallback)(void* userdata);
typedef enum {
BLEND_ALPHA,
BLEND_ADD,
@ -57,6 +59,15 @@ typedef enum {
COMPARE_GREATER = GL_GREATER
} CompareMode;
typedef enum {
STENCIL_REPLACE = GL_REPLACE,
STENCIL_INCREMENT = GL_INCR,
STENCIL_DECREMENT = GL_DECR,
STENCIL_INCREMENT_WRAP = GL_INCR_WRAP,
STENCIL_DECREMENT_WRAP = GL_DECR_WRAP,
STENCIL_INVERT = GL_INVERT
} StencilAction;
typedef enum {
MATRIX_MODEL,
MATRIX_VIEW
@ -115,6 +126,8 @@ typedef struct {
View views[MAX_VIEWS];
int view;
Texture* textures[MAX_TEXTURES];
bool stencilEnabled;
bool stencilWriting;
uint32_t program;
uint32_t vertexArray;
uint32_t vertexBuffer;
@ -126,7 +139,7 @@ typedef struct {
void lovrGraphicsInit();
void lovrGraphicsDestroy();
void lovrGraphicsReset();
void lovrGraphicsClear(bool color, bool depth);
void lovrGraphicsClear(bool color, bool depth, bool stencil);
void lovrGraphicsPresent();
void lovrGraphicsPrepare(Material* material, float* pose);
void lovrGraphicsCreateWindow(int w, int h, bool fullscreen, int msaa, const char* title, const char* icon);
@ -187,6 +200,7 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
void lovrGraphicsSphere(Material* material, mat4 transform, int segments);
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az);
void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAlign halign, VerticalAlign valign);
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata);
// Internal State
void lovrGraphicsPushView();

View File

@ -352,7 +352,7 @@ static void fakeRenderTo(headsetRenderCallback callback, void* userdata) {
lovrGraphicsMatrixTransform(MATRIX_VIEW, inv);
lovrGraphicsSetProjection(state.projection);
lovrGraphicsClear(true, true);
lovrGraphicsClear(true, true, true);
callback(EYE_LEFT, userdata);
lovrGraphicsPop();
}

View File

@ -754,7 +754,7 @@ static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
lovrGraphicsPush();
lovrGraphicsMatrixTransform(MATRIX_VIEW, transform);
lovrGraphicsSetProjection(projection);
lovrGraphicsClear(true, true);
lovrGraphicsClear(true, true, false);
callback(eye, userdata);
lovrGraphicsPop();
lovrCanvasResolveMSAA(state.canvas);