diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index bd1f823e4..2482c25b4 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -252,7 +252,8 @@ namespace PICA { enum : u32 { LUT_D0 = 0, LUT_D1, - LUT_FR, + // LUT 2 is not used, the emulator internally uses it for referring to the current source's spotlight in shaders + LUT_FR = 0x3, LUT_RB, LUT_RG, LUT_RR, diff --git a/include/PICA/shader_gen.hpp b/include/PICA/shader_gen.hpp index c74e69530..1d4d07c55 100644 --- a/include/PICA/shader_gen.hpp +++ b/include/PICA/shader_gen.hpp @@ -27,7 +27,8 @@ namespace PICA::ShaderGen { void applyAlphaTest(std::string& shader, const PICARegs& regs); void compileLights(std::string& shader, const PICA::FragmentConfig& config); - void compileLUTLookup(std::string& shader, u32 lightIndex, u32 lutIndex, bool abs); + void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs, u32 lightIndex, u32 lutID, bool abs); + bool isSamplerEnabled(u32 environmentID, u32 lutID); u32 textureConfig = 0; diff --git a/src/core/PICA/shader_gen_glsl.cpp b/src/core/PICA/shader_gen_glsl.cpp index 96c44ec22..cc01fad1d 100644 --- a/src/core/PICA/shader_gen_glsl.cpp +++ b/src/core/PICA/shader_gen_glsl.cpp @@ -29,6 +29,11 @@ static constexpr const char* uniformDefinition = R"( }; )"; +// There's actually 8 different LUTs (SP0-SP7), one for each light with different indices (8-15) +// We use an unused LUT value for "this light source's spotlight" instead and figure out which light source to use in compileLutLookup +// This is particularly intuitive in several places, such as checking if a LUT is enabled +static constexpr int spotlightLutIndex = 2; + std::string FragmentGenerator::getVertexShader(const PICARegs& regs) { std::string ret = ""; @@ -546,6 +551,46 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC )"; } -void FragmentGenerator::compileLUTLookup(std::string& shader, u32 lightIndex, u32 lutIndex, bool abs) { +bool FragmentGenerator::isSamplerEnabled(u32 environmentID, u32 lutID) { + static constexpr bool samplerEnabled[9 * 7] = { + // D0 D1 SP FR RB RG RR + true, false, true, false, false, false, true, // Configuration 0: D0, SP, RR + false, false, true, true, false, false, true, // Configuration 1: FR, SP, RR + true, true, false, false, false, false, true, // Configuration 2: D0, D1, RR + true, true, false, true, false, false, false, // Configuration 3: D0, D1, FR + true, true, true, false, true, true, true, // Configuration 4: All except for FR + true, false, true, true, true, true, true, // Configuration 5: All except for D1 + true, true, true, true, false, false, true, // Configuration 6: All except for RB and RG + false, false, false, false, false, false, false, // Configuration 7: Unused + true, true, true, true, true, true, true, // Configuration 8: All + }; + + return samplerEnabled[environmentID * 7 + lutID]; +} + +void FragmentGenerator::compileLUTLookup( + std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs, u32 lightIndex, u32 lutID, bool abs +) { + uint lutIndex = 0; + int bitInConfig1 = 0; + + if (lutID == spotlightLutIndex) { + // These are the spotlight attenuation LUTs + bitInConfig1 = 8 + (lightIndex & 0x7); + lutIndex = 8u + lightIndex; + } else if (lutID <= 6) { + bitInConfig1 = 16 + lutID; + lutIndex = lutID; + } else { + Helpers::warn("Shadergen: Unimplemented LUT value"); + } + + const bool samplerEnabled = isSamplerEnabled(config.lighting.config, lutID); + const u32 config1 = regs[InternalRegs::LightConfig1]; + + if (!samplerEnabled || ((config1 >> bitInConfig1) != 0)) { + // 1.0 + } + // TODO } \ No newline at end of file