mirror of
https://github.com/PabloMK7/citra
synced 2024-11-15 05:08:23 +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…
Reference in a new issue