mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-15 07:50:07 +00:00
gl_shader_gen: Implement fragment lighting fresnel effect.
This commit is contained in:
parent
0e67c21c9e
commit
c37de30cfc
@ -713,12 +713,15 @@ struct Regs {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Returns true if the specified lighting sampler is supported by the current Pica lighting configuration
|
||||||
static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) {
|
static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) {
|
||||||
switch (sampler) {
|
switch (sampler) {
|
||||||
case LightingSampler::Distribution0:
|
case LightingSampler::Distribution0:
|
||||||
return (config != LightingConfig::Config1);
|
return (config != LightingConfig::Config1);
|
||||||
case LightingSampler::Distribution1:
|
case LightingSampler::Distribution1:
|
||||||
return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && (config != LightingConfig::Config5);
|
return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && (config != LightingConfig::Config5);
|
||||||
|
case LightingSampler::Fresnel:
|
||||||
|
return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && (config != LightingConfig::Config4);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -761,6 +764,7 @@ struct Regs {
|
|||||||
BitField<0, 3, u32> src_num; // number of enabled lights - 1
|
BitField<0, 3, u32> src_num; // number of enabled lights - 1
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
BitField< 2, 2, LightingFresnelSelector> fresnel_selector;
|
||||||
BitField< 4, 4, LightingConfig> config;
|
BitField< 4, 4, LightingConfig> config;
|
||||||
BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE
|
BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE
|
||||||
};
|
};
|
||||||
@ -768,6 +772,7 @@ struct Regs {
|
|||||||
union {
|
union {
|
||||||
BitField<16, 1, u32> lut_enable_d0; // 0: GL_TRUE, 1: GL_FALSE
|
BitField<16, 1, u32> lut_enable_d0; // 0: GL_TRUE, 1: GL_FALSE
|
||||||
BitField<17, 1, u32> lut_enable_d1; // 0: GL_TRUE, 1: GL_FALSE
|
BitField<17, 1, u32> lut_enable_d1; // 0: GL_TRUE, 1: GL_FALSE
|
||||||
|
BitField<19, 1, u32> lut_enable_fr; // 0: GL_TRUE, 1: GL_FALSE
|
||||||
|
|
||||||
// Each bit specifies whether distance attenuation should be applied for the
|
// Each bit specifies whether distance attenuation should be applied for the
|
||||||
// corresponding light
|
// corresponding light
|
||||||
|
@ -97,7 +97,13 @@ struct PicaShaderConfig {
|
|||||||
res.lighting.lut_d1.type = (Pica::Regs::LightingLutInput)regs.lighting.lut_input.d1.Value();
|
res.lighting.lut_d1.type = (Pica::Regs::LightingLutInput)regs.lighting.lut_input.d1.Value();
|
||||||
res.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1);
|
res.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1);
|
||||||
|
|
||||||
|
res.lighting.lut_fr.enable = regs.lighting.lut_enable_fr == 0;
|
||||||
|
res.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.fr == 0;
|
||||||
|
res.lighting.lut_fr.type = (Pica::Regs::LightingLutInput)regs.lighting.lut_input.fr.Value();
|
||||||
|
res.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr);
|
||||||
|
|
||||||
res.lighting.config = regs.lighting.config;
|
res.lighting.config = regs.lighting.config;
|
||||||
|
res.lighting.fresnel_selector = regs.lighting.fresnel_selector;
|
||||||
res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
|
res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -134,6 +140,7 @@ struct PicaShaderConfig {
|
|||||||
unsigned src_num = 0;
|
unsigned src_num = 0;
|
||||||
bool clamp_highlights = false;
|
bool clamp_highlights = false;
|
||||||
Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0;
|
Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0;
|
||||||
|
Pica::Regs::LightingFresnelSelector fresnel_selector = Pica::Regs::LightingFresnelSelector::None;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool enable = false;
|
bool enable = false;
|
||||||
|
@ -321,8 +321,8 @@ static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsi
|
|||||||
/// Writes the code to emulate fragment lighting
|
/// Writes the code to emulate fragment lighting
|
||||||
static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
// Define lighting globals
|
// Define lighting globals
|
||||||
out += "vec3 diffuse_sum = vec3(0.0);\n";
|
out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n";
|
||||||
out += "vec3 specular_sum = vec3(0.0);\n";
|
out += "vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n";
|
||||||
out += "vec3 light_vector = vec3(0.0);\n";
|
out += "vec3 light_vector = vec3(0.0);\n";
|
||||||
|
|
||||||
// Convert interpolated quaternion to a GL fragment normal
|
// Convert interpolated quaternion to a GL fragment normal
|
||||||
@ -402,9 +402,6 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
dist_atten = GetLutValue((Regs::LightingSampler)lut_num, lut_index);
|
dist_atten = GetLutValue((Regs::LightingSampler)lut_num, lut_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute primary fragment color (diffuse lighting) function
|
|
||||||
out += "diffuse_sum += ((" + light_src + ".diffuse * " + dot_product + ") + " + light_src + ".ambient) * " + dist_atten + ";\n";
|
|
||||||
|
|
||||||
// If enabled, clamp specular component if lighting result is negative
|
// If enabled, clamp specular component if lighting result is negative
|
||||||
std::string clamp_highlights = config.lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0";
|
std::string clamp_highlights = config.lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0";
|
||||||
|
|
||||||
@ -426,14 +423,34 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
}
|
}
|
||||||
std::string specular_1 = "(" + d1_lut_value + " * " + light_src + ".specular_1)";
|
std::string specular_1 = "(" + d1_lut_value + " * " + light_src + ".specular_1)";
|
||||||
|
|
||||||
|
// Fresnel
|
||||||
|
if (config.lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Fresnel)) {
|
||||||
|
// Lookup fresnel LUT value
|
||||||
|
std::string fr_lut_index = GetLutIndex(light_config.num, config.lighting.lut_fr.type, config.lighting.lut_fr.abs_input);
|
||||||
|
std::string fr_lut_value = "(" + std::to_string(config.lighting.lut_fr.scale) + " * " + GetLutValue(Regs::LightingSampler::Fresnel, fr_lut_index) + ")";
|
||||||
|
|
||||||
|
// Enabled for difffuse lighting alpha component
|
||||||
|
if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha ||
|
||||||
|
config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::BothAlpha)
|
||||||
|
out += "diffuse_sum.a *= " + fr_lut_value + ";\n";
|
||||||
|
|
||||||
|
// Enabled for the specular lighting alpha component
|
||||||
|
if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha ||
|
||||||
|
config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::BothAlpha)
|
||||||
|
out += "specular_sum.a *= " + fr_lut_value + ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute primary fragment color (diffuse lighting) function
|
||||||
|
out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * " + dot_product + ") + " + light_src + ".ambient) * " + dist_atten + ";\n";
|
||||||
|
|
||||||
// Compute secondary fragment color (specular lighting) function
|
// Compute secondary fragment color (specular lighting) function
|
||||||
out += "specular_sum += (" + specular_0 + " + " + specular_1 + ") * " + clamp_highlights + " * " + dist_atten + ";\n";
|
out += "specular_sum.rgb += (" + specular_0 + " + " + specular_1 + ") * " + clamp_highlights + " * " + dist_atten + ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum final lighting result
|
// Sum final lighting result
|
||||||
out += "diffuse_sum += lighting_global_ambient;\n";
|
out += "diffuse_sum.rgb += lighting_global_ambient;\n";
|
||||||
out += "primary_fragment_color = vec4(clamp(diffuse_sum, vec3(0.0), vec3(1.0)), 1.0);\n";
|
out += "primary_fragment_color = clamp(diffuse_sum, vec4(0.0), vec4(1.0));\n";
|
||||||
out += "secondary_fragment_color = vec4(clamp(specular_sum, vec3(0.0), vec3(1.0)), 1.0);\n";
|
out += "secondary_fragment_color = clamp(specular_sum, vec4(0.0), vec4(1.0));\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateFragmentShader(const PicaShaderConfig& config) {
|
std::string GenerateFragmentShader(const PicaShaderConfig& config) {
|
||||||
|
Loading…
Reference in New Issue
Block a user