Skip to content

Commit

Permalink
Fixed improper clipping in some models
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuAuahDark committed Jan 12, 2019
1 parent ffb61b7 commit e018faa
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
build
install
include/live2d
lib/live2d
sln/**
Expand Down
14 changes: 9 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ elseif(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/framework/Live2DFramework.cpp")
return()
endif()

set(LIVE2LOVE_SOURCE_FILES
# Live2LOVE files
src/Live2LOVE.cpp
src/RefData.cpp
src/Main.cpp
set(LIVE2LOVE_FRAMEWORK_FILES
# Live2D framework files
framework/L2DBaseModel.cpp
framework/L2DExpressionMotion.cpp
Expand All @@ -32,6 +28,14 @@ set(LIVE2LOVE_SOURCE_FILES
framework/L2DViewMatrix.cpp
framework/Live2DFramework.cpp
)
set(LIVE2LOVE_SOURCE_FILES
# Live2LOVE files
src/Live2LOVE.cpp
src/RefData.cpp
src/Main.cpp
${LIVE2LOVE_FRAMEWORK_FILES}
)
source_group(framework FILES ${LIVE2LOVE_FRAMEWORK_FILES})

# Check Live2D lib files
if(WIN32)
Expand Down
84 changes: 62 additions & 22 deletions src/Live2LOVE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ extern "C" {
// RefData
#include "RefData.h"

// clipping
static const char stencilFragment[] = R"(
vec4 effect(vec4 color, Image tex, vec2 tc, vec2 sc)
{
if (Texel(tex, tc).a > 0.003) return vec4(1.0, 1.0, 1.0, 1.0);
else discard;
}
)";
static int stencilFragRef = LUA_REFNIL;

// Sort operator, for std::sort
static bool compareDrawOrder(const live2love::Live2LOVEMesh *a, const live2love::Live2LOVEMesh *b)
{
Expand Down Expand Up @@ -130,6 +140,22 @@ live2love::Live2LOVE::Live2LOVE(lua_State *L, const std::string& path)
, physics(nullptr)
, eyeBlink(nullptr)
{
// initialize clip fragment shader
if (stencilFragRef == LUA_REFNIL)
{
RefData::getRef(L, "love.graphics.newShader");
lua_pushstring(L, stencilFragment);
lua_pcall(L, 1, 1, 0);
if (lua_toboolean(L, -2) == 0)
{
namedException temp(lua_tostring(L, -1));
lua_pop(L, 2);
throw temp;
}
stencilFragRef = RefData::setRef(L, -1);
lua_pop(L, 1);
}

size_t modelSize;
const void *modelData = loadFileData(L, path, &modelSize);
// Init model
Expand Down Expand Up @@ -261,7 +287,7 @@ void live2love::Live2LOVE::update(double dT)
{
elapsedTime = fmod((elapsedTime + dT), 31536000.0);
live2d::UtSystem::setUserTimeMSec(elapsedTime * 1000.0);
double t = fmod(elapsedTime, 1.0) * 2 * M_PI;
double t = elapsedTime * 2 * M_PI;
// Motion update
if (motion)
{
Expand Down Expand Up @@ -356,10 +382,12 @@ void live2love::Live2LOVE::draw(double x, double y, double r, double sx, double
if (mesh->clipID.size() > 0)
{
// Get stencil function
RefData::getRef(L, "love.graphics.setStencilTest");
RefData::getRef(L, "love.graphics.stencil");
RefData::getRef(L, "love.graphics.setStencilTest");
lua_pushstring(L, "greater");
lua_pushnumber(L, 0);
lua_call(L, 2, 0); // love.graphics.setStencilTest
// Push upvalues
lua_pushvalue(L, -3); // love.graphics.draw
lua_pushlightuserdata(L, mesh);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
Expand All @@ -370,19 +398,16 @@ void live2love::Live2LOVE::draw(double x, double y, double r, double sx, double
lua_pushnumber(L, oy);
lua_pushnumber(L, kx);
lua_pushnumber(L, ky);
lua_pushcclosure(L, Live2LOVE::drawStencil, 11);
lua_call(L, 1, 0); // love.graphics.stencil
lua_pushvalue(L, -1);
lua_pushstring(L, "greater");
lua_pushnumber(L, 0);
lua_call(L, 2, 0); // love.graphics.setStencilTest
lua_pushcclosure(L, Live2LOVE::drawStencil, 10);
lua_pushstring(L, "increment");
lua_call(L, 2, 0); // love.graphics.stencil
stencilSet = true;
}
int meshBlendMode = (mesh->drawData->getOptionFlag() >> 1) & 3;
if (meshBlendMode != blendMode)
{
// Push love.graphics.setBlendMode
lua_pushvalue(L, stencilSet ? -5 : -4);
lua_pushvalue(L, -4);
switch (blendMode = meshBlendMode)
{
default:
Expand Down Expand Up @@ -412,7 +437,7 @@ void live2love::Live2LOVE::draw(double x, double y, double r, double sx, double
// Call it
lua_call(L, 2, 0);
}
lua_pushvalue(L, stencilSet ? -2 : -1);
lua_pushvalue(L, -1);
RefData::getRef(L, mesh->meshRefID);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
Expand All @@ -428,7 +453,10 @@ void live2love::Live2LOVE::draw(double x, double y, double r, double sx, double

// If there's stencil, disable it.
if (stencilSet)
{
RefData::getRef(L, "love.graphics.setStencilTest");
lua_call(L, 0, 0);
}
}

// Remove love.graphics.draw
Expand Down Expand Up @@ -614,23 +642,35 @@ inline void live2love::Live2LOVE::initializeExpression()

int live2love::Live2LOVE::drawStencil(lua_State *L)
{
lua_checkstack(L, lua_gettop(L) + 16);

// Set the shader
RefData::getRef(L, "love.graphics.getShader");
lua_call(L, 0, 1);
RefData::getRef(L, "love.graphics.setShader");
RefData::getRef(L, stencilFragRef);
lua_call(L, 1, 0);
// get love.graphics.draw
RefData::getRef(L, "love.graphics.draw");

// Upvalues:
// 1. love.graphics.draw
// 2. Mesh pointer
// 3,4,5,6,7,8,9,10,11: draw args
lua_checkstack(L, lua_gettop(L) + 15);
Live2LOVEMesh *mesh = (Live2LOVEMesh*)lua_topointer(L, lua_upvalueindex(2));
//for (int i = 0; i < 11; i++)
//lua_pushvalue(L, lua_upvalueindex(i + 1));
//lua_call(L, 10, 0);
// 1. Mesh pointer
// 2-10: draw args
Live2LOVEMesh *mesh = (Live2LOVEMesh*)lua_topointer(L, lua_upvalueindex(1));
for (auto x: mesh->clipID)
{
lua_pushvalue(L, lua_upvalueindex(1)); // love.graphics.draw
lua_pushvalue(L, -1); // love.graphics.draw
RefData::getRef(L, x->meshRefID); // Mesh
for (int i = 2; i < 11; i++)
lua_pushvalue(L, lua_upvalueindex(i + 1)); // the rest
for (int i = 2; i <= 10; i++)
lua_pushvalue(L, lua_upvalueindex(i)); // the rest
lua_call(L, 10, 0);
}

// reset shader
RefData::getRef(L, "love.graphics.setShader");
lua_pushvalue(L, -3);
lua_call(L, 1, 0);
lua_pop(L, 2); // love.graphics.draw and used shader

return 0;
}
2 changes: 1 addition & 1 deletion src/Live2LOVE.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2039 Dark Energy Processor Corporation
* Copyright (c) 2040 Dark Energy Processor Corporation
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand Down
11 changes: 10 additions & 1 deletion src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,15 @@ extern "C" int LUALIB_API luaopen_Live2LOVE(lua_State *L)
lua_pop(L, 1);
lua_getfield(L, -1, "stencil");
RefData::setRef(L, "love.graphics.stencil", -1);
lua_pop(L, 1);
lua_getfield(L, -1, "newShader");
RefData::setRef(L, "love.graphics.newShader", -1);
lua_pop(L, 1);
lua_getfield(L, -1, "setShader");
RefData::setRef(L, "love.graphics.setShader", -1);
lua_pop(L, 1);
lua_getfield(L, -1, "getShader");
RefData::setRef(L, "love.graphics.getShader", -1);
lua_pop(L, 2); // pop the function and the graphics table

// Setup newFileData
Expand Down Expand Up @@ -728,7 +737,7 @@ extern "C" int LUALIB_API luaopen_Live2LOVE(lua_State *L)
lua_pushcfunction(L, Live2LOVE_Live2LOVE_full);
lua_rawset(L, -3);
lua_pushstring(L, "_VERSION");
lua_pushstring(L, "0.4.2");
lua_pushstring(L, "0.4.3");
lua_rawset(L, -3);
lua_pushstring(L, "Live2DVersion");
lua_pushstring(L, live2d::Live2D::getVersionStr());
Expand Down
2 changes: 1 addition & 1 deletion src/RefData.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2039 Dark Energy Processor Corporation
* Copyright (c) 2040 Dark Energy Processor Corporation
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand Down

0 comments on commit e018faa

Please sign in to comment.