From b90c15919b0334a34c80b7f52d29f060699a54a3 Mon Sep 17 00:00:00 2001 From: offtkp Date: Sun, 21 Jul 2024 16:32:45 +0300 Subject: [PATCH] Shadergen fog --- include/PICA/pica_frag_config.hpp | 21 ++++++++++++++++++++- include/PICA/regs.hpp | 6 ++++++ include/PICA/shader_gen.hpp | 2 ++ src/core/PICA/shader_gen_glsl.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/include/PICA/pica_frag_config.hpp b/include/PICA/pica_frag_config.hpp index f4142ef1..32fa7aa6 100644 --- a/include/PICA/pica_frag_config.hpp +++ b/include/PICA/pica_frag_config.hpp @@ -29,6 +29,18 @@ namespace PICA { std::array tevConfigs; }; + struct FogConfig { + union { + u32 raw{}; + + BitField<0, 3, FogMode> mode; + BitField<3, 1, u32> flipDepth; + BitField<8, 8, u32> fogColorR; + BitField<16, 8, u32> fogColorG; + BitField<24, 8, u32> fogColorB; + }; + }; + struct Light { union { u16 raw; @@ -189,6 +201,7 @@ namespace PICA { struct FragmentConfig { OutputConfig outConfig; TextureConfig texConfig; + FogConfig fogConfig; LightingConfig lighting; bool operator==(const FragmentConfig& config) const { @@ -220,12 +233,18 @@ namespace PICA { setupTevStage(4); setupTevStage(5); #undef setupTevStage + + fogConfig.mode = (FogMode)Helpers::getBits<0, 3>(regs[InternalRegs::TexEnvUpdateBuffer]); + fogConfig.flipDepth = Helpers::getBit<16>(regs[InternalRegs::TexEnvUpdateBuffer]); + fogConfig.fogColorR = Helpers::getBits<0, 8>(regs[InternalRegs::FogColor]); + fogConfig.fogColorG = Helpers::getBits<8, 8>(regs[InternalRegs::FogColor]); + fogConfig.fogColorB = Helpers::getBits<16, 8>(regs[InternalRegs::FogColor]); } }; static_assert( std::has_unique_object_representations() && std::has_unique_object_representations() && - std::has_unique_object_representations() + std::has_unique_object_representations() && std::has_unique_object_representations() ); } // namespace PICA diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index c66c90ca..636e8f7c 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -396,6 +396,12 @@ namespace PICA { GreaterOrEqual = 7, }; + enum class FogMode : u32 { + Disabled = 0, + Fog = 5, + Gas = 7, + }; + struct TexEnvConfig { enum class Source : u8 { PrimaryColor = 0x0, diff --git a/include/PICA/shader_gen.hpp b/include/PICA/shader_gen.hpp index 085d990a..215e5adb 100644 --- a/include/PICA/shader_gen.hpp +++ b/include/PICA/shader_gen.hpp @@ -24,6 +24,8 @@ namespace PICA::ShaderGen { void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, u32 lightIndex, u32 lutID); bool isSamplerEnabled(u32 environmentID, u32 lutID); + void compileFog(std::string& shader, const PICA::FragmentConfig& config); + public: FragmentGenerator(API api, Language language) : api(api), language(language) {} std::string generate(const PICA::FragmentConfig& config); diff --git a/src/core/PICA/shader_gen_glsl.cpp b/src/core/PICA/shader_gen_glsl.cpp index 01210587..9802be90 100644 --- a/src/core/PICA/shader_gen_glsl.cpp +++ b/src/core/PICA/shader_gen_glsl.cpp @@ -194,6 +194,8 @@ std::string FragmentGenerator::generate(const FragmentConfig& config) { compileTEV(ret, i, config); } + compileFog(ret, config); + applyAlphaTest(ret, config); ret += "fragColor = combinerOutput;\n}"; // End of main function @@ -652,4 +654,27 @@ void FragmentGenerator::compileLUTLookup(std::string& shader, const PICA::Fragme shader += "lut_lookup_result *= " + std::to_string(scales[scale]) + ";\n"; } } +} + +void FragmentGenerator::compileFog(std::string& shader, const PICA::FragmentConfig& config) { + if (config.fogConfig.mode != FogMode::Fog) { + return; + } + + float r = config.fogConfig.fogColorR / 255.0f; + float g = config.fogConfig.fogColorG / 255.0f; + float b = config.fogConfig.fogColorB / 255.0f; + + if (config.fogConfig.flipDepth) { + shader += "float fog_index = (1.0 - depth) * 128.0;\n"; + } else { + shader += "float fog_index = depth * 128.0;\n"; + } + + shader += "float clamped_index = clamp(floor(fog_index), 0.0, 127.0);"; + shader += "float delta = fog_index - clamped_index;"; + shader += "vec3 fog_color = vec3(" + std::to_string(r) + ", " + std::to_string(g) + ", " + std::to_string(b) + ");"; + shader += "vec2 value = texelFetch(u_tex_luts, ivec2(int(clamped_index), 24), 0).rg;"; // fog LUT is past the light LUTs + shader += "float fog_factor = clamp(value.r + value.g * delta, 0.0, 1.0);"; + shader += "combinerOutput.rgb = mix(fog_color, combinerOutput.rgb, fog_factor);"; } \ No newline at end of file