From b5763cb9521e8dc8a6312930f6815774c724b6a3 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 1 Apr 2018 14:31:26 +0300 Subject: [PATCH 1/2] pica/lighting: split FresnelSelector into bitfields The FresnelSelector was already working like a bitfield, so just make it actual bitfield to reduce redundant code. Also, it is already confirmed that this field also affects shadow on alpha. Given that the only two source that can affect alpha components are both controlled by this field, this field should be renamed to a general alpha switch --- src/video_core/regs_lighting.h | 13 ++----------- src/video_core/renderer_opengl/gl_shader_gen.cpp | 10 ++++------ src/video_core/renderer_opengl/gl_shader_gen.h | 3 ++- src/video_core/swrasterizer/lighting.cpp | 16 ++++------------ 4 files changed, 12 insertions(+), 30 deletions(-) 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..8e0964496 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -154,7 +154,8 @@ 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; @@ -803,15 +804,12 @@ 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"; } } diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 7d14d2c71..12bda326f 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -76,7 +76,8 @@ struct PicaShaderConfigState { bool clamp_highlights; Pica::LightingRegs::LightingConfig config; - Pica::LightingRegs::LightingFresnelSelector fresnel_selector; + bool enable_primary_alpha; + bool enable_secondary_alpha; 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; } } From 4256641da483a6a03fded2dffb974243690955a0 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 1 Apr 2018 18:22:14 +0300 Subject: [PATCH 2/2] gl_rasterizer/lighting: implement shadow attenuation --- .../renderer_opengl/gl_shader_gen.cpp | 44 ++++++++++++++++++- .../renderer_opengl/gl_shader_gen.h | 8 ++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 8e0964496..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; @@ -161,6 +162,13 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { 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; @@ -203,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)); @@ -606,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) { @@ -814,13 +838,29 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { } } + 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 12bda326f..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; @@ -79,6 +80,13 @@ struct PicaShaderConfigState { 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; bool abs_input;