mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #3618 from wwylele/shadow-new-1
gl_rasterizer/lighting: implement shadow attenuation
This commit is contained in:
		
						commit
						575099fcfa
					
				
					 4 changed files with 62 additions and 32 deletions
				
			
		|  | @ -59,16 +59,6 @@ struct LightingRegs { | ||||||
|                      ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration
 |                      ///< 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
 |     /// Factor used to scale the output of a lighting LUT
 | ||||||
|     enum class LightingScale : u32 { |     enum class LightingScale : u32 { | ||||||
|         Scale1 = 0, ///< Scale is 1x
 |         Scale1 = 0, ///< Scale is 1x
 | ||||||
|  | @ -188,7 +178,8 @@ struct LightingRegs { | ||||||
| 
 | 
 | ||||||
|     union { |     union { | ||||||
|         BitField<0, 1, u32> enable_shadow; |         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<4, 4, LightingConfig> config; | ||||||
|         BitField<16, 1, u32> shadow_primary; |         BitField<16, 1, u32> shadow_primary; | ||||||
|         BitField<17, 1, u32> shadow_secondary; |         BitField<17, 1, u32> shadow_secondary; | ||||||
|  |  | ||||||
|  | @ -115,6 +115,7 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { | ||||||
|             !regs.lighting.IsDistAttenDisabled(num); |             !regs.lighting.IsDistAttenDisabled(num); | ||||||
|         state.lighting.light[light_index].spot_atten_enable = |         state.lighting.light[light_index].spot_atten_enable = | ||||||
|             !regs.lighting.IsSpotAttenDisabled(num); |             !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; |     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.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); | ||||||
| 
 | 
 | ||||||
|     state.lighting.config = regs.lighting.config0.config; |     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_mode = regs.lighting.config0.bump_mode; | ||||||
|     state.lighting.bump_selector = regs.lighting.config0.bump_selector; |     state.lighting.bump_selector = regs.lighting.config0.bump_selector; | ||||||
|     state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; |     state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; | ||||||
|     state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 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; |     state.proctex.enable = regs.texturing.main_config.texture3_enable; | ||||||
|     if (state.proctex.enable) { |     if (state.proctex.enable) { | ||||||
|         state.proctex.coord = regs.texturing.main_config.texture3_coordinates; |         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))"; |             return "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; | ||||||
|         case TexturingRegs::TextureConfig::TextureCube: |         case TexturingRegs::TextureConfig::TextureCube: | ||||||
|             return "texture(tex_cube, vec3(texcoord[0], texcoord0_w))"; |             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: |         default: | ||||||
|             LOG_CRITICAL(HW_GPU, "Unhandled texture type %x", |             LOG_CRITICAL(HW_GPU, "Unhandled texture type %x", | ||||||
|                          static_cast<int>(state.texture0_type)); |                          static_cast<int>(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 normal = quaternion_rotate(normalized_normquat, surface_normal);\n"; | ||||||
|     out += "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\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
 |     // Samples the specified lookup table for specular lighting
 | ||||||
|     auto GetLutValue = [&lighting](LightingRegs::LightingSampler sampler, unsigned light_num, |     auto GetLutValue = [&lighting](LightingRegs::LightingSampler sampler, unsigned light_num, | ||||||
|                                    LightingRegs::LightingLutInput input, bool abs) { |                                    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 + ")"; |             value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + value + ")"; | ||||||
| 
 | 
 | ||||||
|             // Enabled for diffuse lighting alpha component
 |             // Enabled for diffuse lighting alpha component
 | ||||||
|             if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || |             if (lighting.enable_primary_alpha) { | ||||||
|                 lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|                 out += "diffuse_sum.a = " + value + ";\n"; |                 out += "diffuse_sum.a = " + value + ";\n"; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Enabled for the specular lighting alpha component
 |             // Enabled for the specular lighting alpha component
 | ||||||
|             if (lighting.fresnel_selector == |             if (lighting.enable_secondary_alpha) { | ||||||
|                     LightingRegs::LightingFresnelSelector::SecondaryAlpha || |  | ||||||
|                 lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|                 out += "specular_sum.a = " + value + ";\n"; |                 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
 |         // Compute primary fragment color (diffuse lighting) function
 | ||||||
|         out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * dot_product) + " + light_src + |         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
 |         // Compute secondary fragment color (specular lighting) function
 | ||||||
|         out += "specular_sum.rgb += (" + specular_0 + " + " + specular_1 + |         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
 |     // Sum final lighting result
 | ||||||
|  |  | ||||||
|  | @ -66,6 +66,7 @@ struct PicaShaderConfigState { | ||||||
|             bool spot_atten_enable; |             bool spot_atten_enable; | ||||||
|             bool geometric_factor_0; |             bool geometric_factor_0; | ||||||
|             bool geometric_factor_1; |             bool geometric_factor_1; | ||||||
|  |             bool shadow_enable; | ||||||
|         } light[8]; |         } light[8]; | ||||||
| 
 | 
 | ||||||
|         bool enable; |         bool enable; | ||||||
|  | @ -76,7 +77,15 @@ struct PicaShaderConfigState { | ||||||
|         bool clamp_highlights; |         bool clamp_highlights; | ||||||
| 
 | 
 | ||||||
|         Pica::LightingRegs::LightingConfig config; |         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 { |         struct { | ||||||
|             bool enable; |             bool enable; | ||||||
|  |  | ||||||
|  | @ -251,16 +251,12 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors( | ||||||
|                             lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); |                             lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); | ||||||
| 
 | 
 | ||||||
|             // Enabled for diffuse lighting alpha component
 |             // Enabled for diffuse lighting alpha component
 | ||||||
|             if (lighting.config0.fresnel_selector == |             if (lighting.config0.enable_primary_alpha) { | ||||||
|                     LightingRegs::LightingFresnelSelector::PrimaryAlpha || |  | ||||||
|                 lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|                 diffuse_sum.a() = lut_value; |                 diffuse_sum.a() = lut_value; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Enabled for the specular lighting alpha component
 |             // Enabled for the specular lighting alpha component
 | ||||||
|             if (lighting.config0.fresnel_selector == |             if (lighting.config0.enable_secondary_alpha) { | ||||||
|                     LightingRegs::LightingFresnelSelector::SecondaryAlpha || |  | ||||||
|                 lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|                 specular_sum.a() = lut_value; |                 specular_sum.a() = lut_value; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -308,16 +304,12 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors( | ||||||
|     if (lighting.config0.shadow_alpha) { |     if (lighting.config0.shadow_alpha) { | ||||||
|         // Alpha shadow also uses the Fresnel selecotr to determine which alpha to apply
 |         // Alpha shadow also uses the Fresnel selecotr to determine which alpha to apply
 | ||||||
|         // Enabled for diffuse lighting alpha component
 |         // Enabled for diffuse lighting alpha component
 | ||||||
|         if (lighting.config0.fresnel_selector == |         if (lighting.config0.enable_primary_alpha) { | ||||||
|                 LightingRegs::LightingFresnelSelector::PrimaryAlpha || |  | ||||||
|             lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|             diffuse_sum.a() *= shadow.w; |             diffuse_sum.a() *= shadow.w; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Enabled for the specular lighting alpha component
 |         // Enabled for the specular lighting alpha component
 | ||||||
|         if (lighting.config0.fresnel_selector == |         if (lighting.config0.enable_secondary_alpha) { | ||||||
|                 LightingRegs::LightingFresnelSelector::SecondaryAlpha || |  | ||||||
|             lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |  | ||||||
|             specular_sum.a() *= shadow.w; |             specular_sum.a() *= shadow.w; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue