#include "hecl/Backend/GLSL.hpp" #include "hecl/Runtime.hpp" #include "athena/MemoryReader.hpp" #include "athena/MemoryWriter.hpp" #include "boo/graphicsdev/GLSLMacros.hpp" static logvisor::Module Log("hecl::Backend::GLSL"); namespace hecl::Backend { std::string GLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const { switch (src) { case TexGenSrc::Position: return "vtf.mvPos.xy"; case TexGenSrc::Normal: return "vtf.mvNorm.xy"; case TexGenSrc::UV: return hecl::Format("uvIn[%u]", uvIdx); default: break; } return std::string(); } std::string GLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const { switch (src) { case TexGenSrc::Position: return "vec4(vtf.mvPos.xyz, 1.0)"; case TexGenSrc::Normal: return "vec4(vtf.mvNorm.xyz, 1.0)"; case TexGenSrc::UV: return hecl::Format("vec4(uvIn[%u], 0.0, 1.0)", uvIdx); default: break; } return std::string(); } std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const { std::string retval = "layout(location=0) in vec3 posIn;\n" "layout(location=1) in vec3 normIn;\n"; unsigned idx = 2; if (col) { retval += hecl::Format("layout(location=%u) in vec4 colIn[%u];\n", idx, col); idx += col; } if (uv) { retval += hecl::Format("layout(location=%u) in vec2 uvIn[%u];\n", idx, uv); idx += uv; } if (w) { retval += hecl::Format("layout(location=%u) in vec4 weightIn[%u];\n", idx, w); } return retval; } std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const { std::string retval = "struct VertToFrag\n" "{\n" " vec4 mvPos;\n" " vec4 mvNorm;\n"; if (m_tcgs.size()) retval += hecl::Format(" vec2 tcgs[%u];\n", unsigned(m_tcgs.size())); if (extTexCount) retval += hecl::Format(" vec2 extTcgs[%u];\n", unsigned(extTexCount)); if (reflectionCoords) retval += " vec2 reflectTcgs[2];\n" " float reflectAlpha;\n"; return retval + "};\n"; } std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const { if (skinSlots == 0) skinSlots = 1; std::string retval = hecl::Format("UBINDING0 uniform HECLVertUniform\n" "{\n" " mat4 mv[%u];\n" " mat4 mvInv[%u];\n" " mat4 proj;\n" "};\n", skinSlots, skinSlots); retval += "struct HECLTCGMatrix\n" "{\n" " mat4 mtx;\n" " mat4 postMtx;\n" "};\n" "UBINDING1 uniform HECLTexMtxUniform\n" "{\n" " HECLTCGMatrix texMtxs[8];\n" "};\n"; if (reflectionCoords) retval += "UBINDING3 uniform HECLReflectMtx\n" "{\n" " mat4 indMtx;\n" " mat4 reflectMtx;\n" " float reflectAlpha;\n" "};\n" "\n"; return retval; } std::string GLSL::GenerateAlphaTest() const { return " if (colorOut.a < 0.01)\n" " {\n" " discard;\n" " }\n"; } std::string GLSL::GenerateReflectionExpr(ReflectionType type) const { switch (type) { case ReflectionType::None: default: return "vec3(0.0, 0.0, 0.0)"; case ReflectionType::Simple: return "texture(reflectionTex, vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; case ReflectionType::Indirect: return "texture(reflectionTex, (texture(reflectionIndTex, vtf.reflectTcgs[0]).rg - " "vec2(0.5, 0.5)) * vec2(0.5, 0.5) + vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; } } void GLSL::reset(const IR& ir, Diagnostics& diag) { /* Common programmable interpretation */ ProgrammableCommon::reset(ir, diag, "GLSL"); } std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount, const TextureInfo* extTexs, ReflectionType reflectionType) const { extTexCount = std::min(int(extTexCount), BOO_GLSL_MAX_TEXTURE_COUNT - int(m_tcgs.size())); std::string retval = GenerateVertInStruct(col, uv, w) + "\n" + GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + GenerateVertUniformStruct(s, reflectionType != ReflectionType::None) + "SBINDING(0) out VertToFrag vtf;\n\n" "void main()\n{\n"; if (s) { /* skinned */ retval += " vec4 posAccum = vec4(0.0,0.0,0.0,0.0);\n" " vec4 normAccum = vec4(0.0,0.0,0.0,0.0);\n"; for (size_t i=0 ; i