From e018faafcf7a5d685399f070f2df04938181df46 Mon Sep 17 00:00:00 2001 From: MikuAuahDark Date: Sat, 12 Jan 2019 14:09:50 +0800 Subject: [PATCH] Fixed improper clipping in some models --- .gitignore | 1 + CMakeLists.txt | 14 +++++--- src/Live2LOVE.cpp | 84 ++++++++++++++++++++++++++++++++++------------- src/Live2LOVE.h | 2 +- src/Main.cpp | 11 ++++++- src/RefData.h | 2 +- 6 files changed, 84 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 8891efe..727af28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build +install include/live2d lib/live2d sln/** diff --git a/CMakeLists.txt b/CMakeLists.txt index b4fdf94..3973239 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 @@ -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) diff --git a/src/Live2LOVE.cpp b/src/Live2LOVE.cpp index 2415f25..ac209b3 100644 --- a/src/Live2LOVE.cpp +++ b/src/Live2LOVE.cpp @@ -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) { @@ -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 @@ -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) { @@ -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); @@ -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: @@ -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); @@ -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 @@ -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; } diff --git a/src/Live2LOVE.h b/src/Live2LOVE.h index 65353de..0e6e753 100644 --- a/src/Live2LOVE.h +++ b/src/Live2LOVE.h @@ -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 diff --git a/src/Main.cpp b/src/Main.cpp index c194ac5..45e401b 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -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 @@ -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()); diff --git a/src/RefData.h b/src/RefData.h index 900cffd..a1b5ccf 100644 --- a/src/RefData.h +++ b/src/RefData.h @@ -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