diff --git a/src/video_core/regs_lighting.h b/src/video_core/regs_lighting.h index 8ef1d2136..3c5499a9f 100644 --- a/src/video_core/regs_lighting.h +++ b/src/video_core/regs_lighting.h @@ -59,16 +59,6 @@ struct LightingRegs { ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration }; - /// Selects which lighting components are affected by fresnel - enum class LightingFresnelSelector : u32 { - None = 0, ///< Fresnel is disabled - PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel - SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel - Both = - PrimaryAlpha | - SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel - }; - /// Factor used to scale the output of a lighting LUT enum class LightingScale : u32 { Scale1 = 0, ///< Scale is 1x @@ -188,7 +178,8 @@ struct LightingRegs { union { BitField<0, 1, u32> enable_shadow; - BitField<2, 2, LightingFresnelSelector> fresnel_selector; + BitField<2, 1, u32> enable_primary_alpha; + BitField<3, 1, u32> enable_secondary_alpha; BitField<4, 4, LightingConfig> config; BitField<16, 1, u32> shadow_primary; BitField<17, 1, u32> shadow_secondary; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index af5be62d7..9c0f10a41 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -115,6 +115,7 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { !regs.lighting.IsDistAttenDisabled(num); state.lighting.light[light_index].spot_atten_enable = !regs.lighting.IsSpotAttenDisabled(num); + state.lighting.light[light_index].shadow_enable = !regs.lighting.IsShadowDisabled(num); } state.lighting.lut_d0.enable = regs.lighting.config1.disable_lut_d0 == 0; @@ -154,12 +155,20 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); state.lighting.config = regs.lighting.config0.config; - state.lighting.fresnel_selector = regs.lighting.config0.fresnel_selector; + state.lighting.enable_primary_alpha = regs.lighting.config0.enable_primary_alpha; + state.lighting.enable_secondary_alpha = regs.lighting.config0.enable_secondary_alpha; state.lighting.bump_mode = regs.lighting.config0.bump_mode; state.lighting.bump_selector = regs.lighting.config0.bump_selector; state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 0; + state.lighting.enable_shadow = regs.lighting.config0.enable_shadow != 0; + state.lighting.shadow_primary = regs.lighting.config0.shadow_primary != 0; + state.lighting.shadow_secondary = regs.lighting.config0.shadow_secondary != 0; + state.lighting.shadow_invert = regs.lighting.config0.shadow_invert != 0; + state.lighting.shadow_alpha = regs.lighting.config0.shadow_alpha != 0; + state.lighting.shadow_selector = regs.lighting.config0.shadow_selector; + state.proctex.enable = regs.texturing.main_config.texture3_enable; if (state.proctex.enable) { state.proctex.coord = regs.texturing.main_config.texture3_coordinates; @@ -202,6 +211,11 @@ static std::string SampleTexture(const PicaShaderConfig& config, unsigned textur return "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; case TexturingRegs::TextureConfig::TextureCube: return "texture(tex_cube, vec3(texcoord[0], texcoord0_w))"; + case TexturingRegs::TextureConfig::Shadow2D: + case TexturingRegs::TextureConfig::ShadowCube: + NGLOG_CRITICAL(HW_GPU, "Unhandled shadow texture"); + UNIMPLEMENTED(); + return "vec4(1.0)"; // stubbed to avoid rendering with wrong shadow default: LOG_CRITICAL(HW_GPU, "Unhandled texture type %x", static_cast(state.texture0_type)); @@ -605,6 +619,17 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { out += "vec3 normal = quaternion_rotate(normalized_normquat, surface_normal);\n"; out += "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\n"; + if (lighting.enable_shadow) { + std::string shadow_texture = SampleTexture(config, lighting.shadow_selector); + if (lighting.shadow_invert) { + out += "vec4 shadow = vec4(1.0) - " + shadow_texture + ";\n"; + } else { + out += "vec4 shadow = " + shadow_texture + ";\n"; + } + } else { + out += "vec4 shadow = vec4(1.0);\n"; + } + // Samples the specified lookup table for specular lighting auto GetLutValue = [&lighting](LightingRegs::LightingSampler sampler, unsigned light_num, LightingRegs::LightingLutInput input, bool abs) { @@ -803,26 +828,39 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + value + ")"; // Enabled for diffuse lighting alpha component - if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || - lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.enable_primary_alpha) { out += "diffuse_sum.a = " + value + ";\n"; } // Enabled for the specular lighting alpha component - if (lighting.fresnel_selector == - LightingRegs::LightingFresnelSelector::SecondaryAlpha || - lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.enable_secondary_alpha) { out += "specular_sum.a = " + value + ";\n"; } } + bool shadow_primary_enable = lighting.shadow_primary && light_config.shadow_enable; + bool shadow_secondary_enable = lighting.shadow_secondary && light_config.shadow_enable; + std::string shadow_primary = shadow_primary_enable ? " * shadow.rgb" : ""; + std::string shadow_secondary = shadow_secondary_enable ? " * shadow.rgb" : ""; + // Compute primary fragment color (diffuse lighting) function out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * dot_product) + " + light_src + - ".ambient) * " + dist_atten + " * " + spot_atten + ";\n"; + ".ambient) * " + dist_atten + " * " + spot_atten + shadow_primary + ";\n"; // Compute secondary fragment color (specular lighting) function out += "specular_sum.rgb += (" + specular_0 + " + " + specular_1 + - ") * clamp_highlights * " + dist_atten + " * " + spot_atten + ";\n"; + ") * clamp_highlights * " + dist_atten + " * " + spot_atten + shadow_secondary + + ";\n"; + } + + // Apply shadow attenuation to alpha components if enabled + if (lighting.shadow_alpha) { + if (lighting.enable_primary_alpha) { + out += "diffuse_sum.a *= shadow.a;\n"; + } + if (lighting.enable_secondary_alpha) { + out += "specular_sum.a *= shadow.a;\n"; + } } // Sum final lighting result diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 7d14d2c71..929c3c015 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -66,6 +66,7 @@ struct PicaShaderConfigState { bool spot_atten_enable; bool geometric_factor_0; bool geometric_factor_1; + bool shadow_enable; } light[8]; bool enable; @@ -76,7 +77,15 @@ struct PicaShaderConfigState { bool clamp_highlights; Pica::LightingRegs::LightingConfig config; - Pica::LightingRegs::LightingFresnelSelector fresnel_selector; + bool enable_primary_alpha; + bool enable_secondary_alpha; + + bool enable_shadow; + bool shadow_primary; + bool shadow_secondary; + bool shadow_invert; + bool shadow_alpha; + unsigned shadow_selector; struct { bool enable; diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index fb345e077..130e1b5d5 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -251,16 +251,12 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); // Enabled for diffuse lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::PrimaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.config0.enable_primary_alpha) { diffuse_sum.a() = lut_value; } // Enabled for the specular lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::SecondaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.config0.enable_secondary_alpha) { specular_sum.a() = lut_value; } } @@ -308,16 +304,12 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config0.shadow_alpha) { // Alpha shadow also uses the Fresnel selecotr to determine which alpha to apply // Enabled for diffuse lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::PrimaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.config0.enable_primary_alpha) { diffuse_sum.a() *= shadow.w; } // Enabled for the specular lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::SecondaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + if (lighting.config0.enable_secondary_alpha) { specular_sum.a() *= shadow.w; } }