diff --git a/hecl/extern/boo b/hecl/extern/boo index 2ec943f0b..21548bada 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 2ec943f0b2f5af6c74c0b8a2f852c484c3235d8e +Subproject commit 21548bada8e0806adfc3fc36fa748f7355dfecbb diff --git a/hecl/include/hecl/Backend/GLSL.hpp b/hecl/include/hecl/Backend/GLSL.hpp index 1926a2abb..09fe9d4bc 100644 --- a/hecl/include/hecl/Backend/GLSL.hpp +++ b/hecl/include/hecl/Backend/GLSL.hpp @@ -17,9 +17,9 @@ struct GLSL : ProgrammableCommon std::string makeVert(const char* glslVer, unsigned col, unsigned uv, unsigned w, unsigned skinSlots, unsigned texMtxs, size_t extTexCount, const TextureInfo* extTexs) const; - std::string makeFrag(const char* glslVer, + std::string makeFrag(const char* glslVer, bool alphaTest, const ShaderFunction& lighting=ShaderFunction()) const; - std::string makeFrag(const char* glslVer, + std::string makeFrag(const char* glslVer, bool alphaTest, const ShaderFunction& lighting, const ShaderFunction& post, size_t extTexCount, const TextureInfo* extTexs) const; @@ -28,6 +28,7 @@ private: std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; std::string GenerateVertToFragStruct(size_t extTexCount) const; std::string GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const; + std::string GenerateAlphaTest() const; std::string EmitVec3(const atVec4f& vec) const { diff --git a/hecl/include/hecl/Backend/Metal.hpp b/hecl/include/hecl/Backend/Metal.hpp index 4c7602536..c4adfe9bb 100644 --- a/hecl/include/hecl/Backend/Metal.hpp +++ b/hecl/include/hecl/Backend/Metal.hpp @@ -16,9 +16,9 @@ struct Metal : ProgrammableCommon std::string makeVert(unsigned col, unsigned uv, unsigned w, unsigned skinSlots, unsigned texMtxs, size_t extTexCount, const TextureInfo* extTexs) const; - std::string makeFrag(size_t blockCount, const char** blockNames, + std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, const ShaderFunction& lighting=ShaderFunction()) const; - std::string makeFrag(size_t blockCount, const char** blockNames, + std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, const ShaderFunction& lighting, const ShaderFunction& post, size_t extTexCount, const TextureInfo* extTexs) const; @@ -27,6 +27,8 @@ private: std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; std::string GenerateVertToFragStruct(size_t extTexCount) const; std::string GenerateVertUniformStruct(unsigned skinSlots) const; + std::string GenerateFragOutStruct() const; + std::string GenerateAlphaTest() const; std::string EmitVec3(const atVec4f& vec) const { diff --git a/hecl/lib/Backend/GLSL.cpp b/hecl/lib/Backend/GLSL.cpp index 6a5fe2939..a65732c70 100644 --- a/hecl/lib/Backend/GLSL.cpp +++ b/hecl/lib/Backend/GLSL.cpp @@ -112,6 +112,14 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs return retval; } +std::string GLSL::GenerateAlphaTest() const +{ + return " if (colorOut.a < 0.01)\n" + " {\n" + " discard;\n" + " }\n"; +} + void GLSL::reset(const IR& ir, Diagnostics& diag) { /* Common programmable interpretation */ @@ -182,7 +190,7 @@ std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsig return retval + "}\n"; } -std::string GLSL::makeFrag(const char* glslVer, +std::string GLSL::makeFrag(const char* glslVer, bool alphaTest, const ShaderFunction& lighting) const { std::string lightingSrc; @@ -220,10 +228,10 @@ std::string GLSL::makeFrag(const char* glslVer, else retval += " colorOut = vec4(" + m_colorExpr + ", 1.0);\n"; - return retval + "}\n"; + return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n"; } -std::string GLSL::makeFrag(const char* glslVer, +std::string GLSL::makeFrag(const char* glslVer, bool alphaTest, const ShaderFunction& lighting, const ShaderFunction& post, size_t extTexCount, const TextureInfo* extTexs) const @@ -278,7 +286,7 @@ std::string GLSL::makeFrag(const char* glslVer, else retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + ", 1.0));\n"; - return retval + "}\n"; + return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n"; } } @@ -319,7 +327,8 @@ struct GLSLBackendFactory : IShaderBackendFactory tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr); cachedSz += vertSource.size() + 1; - std::string fragSource = m_backend.makeFrag("#version 330"); + std::string fragSource = m_backend.makeFrag("#version 330", + tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha); cachedSz += fragSource.size() + 1; if (m_backend.m_texMapEnd > 8) @@ -404,7 +413,9 @@ struct GLSLBackendFactory : IShaderBackendFactory tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), tag.getSkinSlotCount(), tag.getTexMtxCount(), slot.texCount, slot.texs), - m_backend.makeFrag("#version 330", slot.lighting, slot.post, slot.texCount, slot.texs)); + m_backend.makeFrag("#version 330", + tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha, + slot.lighting, slot.post, slot.texCount, slot.texs)); cachedSz += sources.back().first.size() + 1; cachedSz += sources.back().second.size() + 1; boo::IShaderPipeline* ret = diff --git a/hecl/lib/Backend/Metal.cpp b/hecl/lib/Backend/Metal.cpp index 97f5931c5..5a453c757 100644 --- a/hecl/lib/Backend/Metal.cpp +++ b/hecl/lib/Backend/Metal.cpp @@ -110,6 +110,23 @@ std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const return retval; } +std::string Metal::GenerateFragOutStruct() const +{ + return "struct FragOut\n" + "{\n" + " float4 color [[ color(0) ]];\n" + " //float depth [[ depth(less) ]];\n" + "};\n"; +} + +std::string Metal::GenerateAlphaTest() const +{ + return " if (out.color.a < 0.01)\n" + " {\n" + " discard_fragment();\n" + " }\n"; +} + void Metal::reset(const IR& ir, Diagnostics& diag) { /* Common programmable interpretation */ @@ -180,7 +197,7 @@ std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w, return retval + " return vtf;\n}\n"; } -std::string Metal::makeFrag(size_t blockCount, const char** blockNames, +std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, const ShaderFunction& lighting) const { std::string lightingSrc; @@ -206,8 +223,11 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, std::string retval = "#include \nusing namespace metal;\n" "constexpr sampler samp(address::repeat, filter::linear, mip_filter::linear);\n" + GenerateVertToFragStruct(0) + "\n" + + GenerateFragOutStruct() + "\n" + lightingSrc + "\n" + - "fragment float4 fmain(VertToFrag vtf [[ stage_in ]]" + texMapDecl + ")\n{\n"; + "fragment FragOut fmain(VertToFrag vtf [[ stage_in ]]" + texMapDecl + ")\n" + "{\n" + " FragOut out;\n"; if (m_lighting) @@ -224,14 +244,17 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, sampIdx++, sampling.mapIdx, sampling.tcgIdx); if (m_alphaExpr.size()) - retval += " return float4(" + m_colorExpr + ", " + m_alphaExpr + ");\n"; + retval += " out.color = float4(" + m_colorExpr + ", " + m_alphaExpr + ");\n"; else - retval += " return float4(" + m_colorExpr + ", 1.0);\n"; + retval += " out.color = float4(" + m_colorExpr + ", 1.0);\n"; - return retval + "}\n"; + return retval + (alphaTest ? GenerateAlphaTest() : "") + + " //out.depth = 1.0 - float(int((1.0 - vtf.mvpPos.z) * 16777216.0)) / 16777216.0;\n" + " return out;\n" + "}\n"; } -std::string Metal::makeFrag(size_t blockCount, const char** blockNames, +std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, const ShaderFunction& lighting, const ShaderFunction& post, size_t extTexCount, const TextureInfo* extTexs) const @@ -277,9 +300,12 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, std::string retval = "#include \nusing namespace metal;\n" "constexpr sampler samp(address::repeat, filter::linear, mip_filter::linear);\n" + GenerateVertToFragStruct(extTexCount) + "\n" + + GenerateFragOutStruct() + "\n" + lightingSrc + "\n" + postSrc + "\n" + - "fragment float4 fmain(VertToFrag vtf [[ stage_in ]]" + texMapDecl + ")\n{\n"; + "fragment FragOut fmain(VertToFrag vtf [[ stage_in ]]" + texMapDecl + ")\n" + "{\n" + " FragOut out;\n"; if (m_lighting) { @@ -295,13 +321,16 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, sampIdx++, sampling.mapIdx, sampling.tcgIdx); if (m_alphaExpr.size()) - retval += " return " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") + + retval += " out.color = " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") + "float4(" + m_colorExpr + ", " + m_alphaExpr + "));\n"; else - retval += " return " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") + + retval += " out.color = " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") + "float4(" + m_colorExpr + ", 1.0));\n"; - return retval + "}\n"; + return retval + (alphaTest ? GenerateAlphaTest() : "") + + " //out.depth = 1.0 - float(int((1.0 - vtf.mvpPos.z) * 16777216.0)) / 16777216.0;\n" + " return out;\n" + "}\n"; } } @@ -330,7 +359,8 @@ struct MetalBackendFactory : IShaderBackendFactory tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr); cachedSz += vertSource.size() + 1; - std::string fragSource = m_backend.makeFrag(0, nullptr); + std::string fragSource = m_backend.makeFrag(0, nullptr, + tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha); cachedSz += fragSource.size() + 1; objOut = static_cast(ctx). @@ -399,7 +429,9 @@ struct MetalBackendFactory : IShaderBackendFactory { sources.emplace_back(m_backend.makeVert(tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), tag.getSkinSlotCount(), tag.getTexMtxCount(), slot.texCount, slot.texs), - m_backend.makeFrag(slot.blockCount, slot.blockNames, slot.lighting, slot.post, slot.texCount, slot.texs)); + m_backend.makeFrag(slot.blockCount, slot.blockNames, + tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha, + slot.lighting, slot.post, slot.texCount, slot.texs)); cachedSz += sources.back().first.size() + 1; cachedSz += sources.back().second.size() + 1; boo::IShaderPipeline* ret =