mirror of https://github.com/bjornbytes/lovr.git
lovr.graphics.stencil;
This commit is contained in:
parent
8acd7444af
commit
77d8b96cfd
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue