citra-emu
/
citra-canary
Archived
1
0
Fork 0

gl_shader_gen: Refactor lighting config to match Pica register naming.

- Also implement D0 LUT enable.
This commit is contained in:
bunnei 2015-11-18 23:40:18 -05:00
parent 6307999116
commit 3d89dacd56
3 changed files with 48 additions and 40 deletions

View File

@ -718,6 +718,8 @@ struct Regs {
}; };
union { union {
BitField<16, 1, u32> lut_enable_d0; // 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

View File

@ -73,23 +73,24 @@ struct PicaShaderConfig {
// Fragment lighting // Fragment lighting
res.lighting_enabled = !regs.lighting.disable; res.lighting.enable = !regs.lighting.disable;
res.num_lights = regs.lighting.src_num + 1; res.lighting.src_num = regs.lighting.src_num + 1;
for (unsigned light_index = 0; light_index < res.num_lights; ++light_index) { for (unsigned light_index = 0; light_index < res.lighting.src_num; ++light_index) {
unsigned num = regs.lighting.light_enable.GetNum(light_index); unsigned num = regs.lighting.light_enable.GetNum(light_index);
const auto& light = regs.lighting.light[num]; const auto& light = regs.lighting.light[num];
res.light_src[light_index].num = num; res.lighting.light[light_index].num = num;
res.light_src[light_index].directional = light.directional != 0; res.lighting.light[light_index].directional = light.directional != 0;
res.light_src[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; res.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0;
res.light_src[light_index].dist_atten_enabled = regs.lighting.IsDistAttenEnabled(num); res.lighting.light[light_index].dist_atten_enable = regs.lighting.IsDistAttenEnabled(num);
res.light_src[light_index].dist_atten_bias = Pica::float20::FromRawFloat20(light.dist_atten_bias).ToFloat32(); res.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRawFloat20(light.dist_atten_bias).ToFloat32();
res.light_src[light_index].dist_atten_scale = Pica::float20::FromRawFloat20(light.dist_atten_scale).ToFloat32(); res.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRawFloat20(light.dist_atten_scale).ToFloat32();
} }
res.lighting_lut.d0_abs = regs.lighting.abs_lut_input.d0 == 0; res.lighting.lut_d0.enable = regs.lighting.lut_enable_d0 == 0;
res.lighting_lut.d0_type = (Pica::Regs::LightingLutInput)regs.lighting.lut_input.d0.Value(); res.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.d0 == 0;
res.clamp_highlights = regs.lighting.clamp_highlights != 0; res.lighting.lut_d0.type = (Pica::Regs::LightingLutInput)regs.lighting.lut_input.d0.Value();
res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
return res; return res;
} }
@ -111,23 +112,26 @@ struct PicaShaderConfig {
std::array<Pica::Regs::TevStageConfig, 6> tev_stages = {}; std::array<Pica::Regs::TevStageConfig, 6> tev_stages = {};
u8 combiner_buffer_input = 0; u8 combiner_buffer_input = 0;
struct {
struct { struct {
unsigned num = 0; unsigned num = 0;
bool directional = false; bool directional = false;
bool two_sided_diffuse = false; bool two_sided_diffuse = false;
bool dist_atten_enabled = false; bool dist_atten_enable = false;
GLfloat dist_atten_scale = 0.0f; GLfloat dist_atten_scale = 0.0f;
GLfloat dist_atten_bias = 0.0f; GLfloat dist_atten_bias = 0.0f;
} light_src[8]; } light[8];
bool lighting_enabled = false; bool enable = false;
unsigned num_lights = 0; unsigned src_num = 0;
bool clamp_highlights = false; bool clamp_highlights = false;
struct { struct {
bool d0_abs = false; bool enable = false;
Pica::Regs::LightingLutInput d0_type = Pica::Regs::LightingLutInput::NH; bool abs_input = false;
} lighting_lut; Pica::Regs::LightingLutInput type = Pica::Regs::LightingLutInput::NH;
} lut_d0;
} lighting;
}; };
}; };

View File

@ -360,7 +360,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
if (abs) { if (abs) {
// LUT index is in the range of (0.0, 1.0) // LUT index is in the range of (0.0, 1.0)
index = config.light_src[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)"; index = config.lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)";
return "clamp(" + index + ", 0.0, FLOAT_255)"; return "clamp(" + index + ", 0.0, FLOAT_255)";
} else { } else {
// LUT index is in the range of (-1.0, 1.0) // LUT index is in the range of (-1.0, 1.0)
@ -378,10 +378,9 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
}; };
// Write the code to emulate each enabled light // Write the code to emulate each enabled light
for (unsigned light_index = 0; light_index < config.num_lights; ++light_index) { for (unsigned light_index = 0; light_index < config.lighting.src_num; ++light_index) {
unsigned num = config.light_src[light_index].num; const auto& light_config = config.lighting.light[light_index];
const auto& light_config = config.light_src[light_index]; std::string light_src = "light_src[" + std::to_string(light_config.num) + "]";
std::string light_src = "light_src[" + std::to_string(num) + "]";
// Compute light vector (directional or positional) // Compute light vector (directional or positional)
if (light_config.directional) if (light_config.directional)
@ -394,12 +393,12 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
// If enabled, compute distance attenuation value // If enabled, compute distance attenuation value
std::string dist_atten = "1.0"; std::string dist_atten = "1.0";
if (light_config.dist_atten_enabled) { if (light_config.dist_atten_enable) {
std::string scale = std::to_string(light_config.dist_atten_scale); std::string scale = std::to_string(light_config.dist_atten_scale);
std::string bias = std::to_string(light_config.dist_atten_bias); std::string bias = std::to_string(light_config.dist_atten_bias);
std::string lut_index = "(" + scale + " * length(-view - " + light_src + ".position) + " + bias + ")"; std::string lut_index = "(" + scale + " * length(-view - " + light_src + ".position) + " + bias + ")";
lut_index = "((clamp(" + lut_index + ", 0.0, FLOAT_255)))"; lut_index = "((clamp(" + lut_index + ", 0.0, FLOAT_255)))";
const unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + num); const unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + light_config.num);
dist_atten = GetLutValue((Regs::LightingSampler)lut_num, lut_index); dist_atten = GetLutValue((Regs::LightingSampler)lut_num, lut_index);
} }
@ -407,11 +406,14 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
out += "diffuse_sum += ((" + light_src + ".diffuse * " + dot_product + ") + " + light_src + ".ambient) * " + dist_atten + ";\n"; 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.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";
// Lookup specular distribution 0 LUT value // Lookup specular "distribution 0" LUT value
std::string d0_lut_index = GetLutIndex(num, config.lighting_lut.d0_type, config.lighting_lut.d0_abs); std::string d0_lut_value = "1.0";
std::string d0_lut_value = GetLutValue(Regs::LightingSampler::Distribution0, d0_lut_index); if (config.lighting.lut_d0.enable) {
std::string d0_lut_index = GetLutIndex(light_config.num, config.lighting.lut_d0.type, config.lighting.lut_d0.abs_input);
d0_lut_value = GetLutValue(Regs::LightingSampler::Distribution0, d0_lut_index);
}
// Compute secondary fragment color (specular lighting) function // Compute secondary fragment color (specular lighting) function
out += "specular_sum += " + clamp_highlights + " * " + d0_lut_value + " * " + light_src + ".specular_0 * " + dist_atten + ";\n"; out += "specular_sum += " + clamp_highlights + " * " + d0_lut_value + " * " + light_src + ".specular_0 * " + dist_atten + ";\n";
@ -463,15 +465,15 @@ vec4 primary_fragment_color = vec4(0.0);
vec4 secondary_fragment_color = vec4(0.0); vec4 secondary_fragment_color = vec4(0.0);
)"; )";
if (config.lighting_enabled)
WriteLighting(out, config);
// Do not do any sort of processing if it's obvious we're not going to pass the alpha test // Do not do any sort of processing if it's obvious we're not going to pass the alpha test
if (config.alpha_test_func == Regs::CompareFunc::Never) { if (config.alpha_test_func == Regs::CompareFunc::Never) {
out += "discard; }"; out += "discard; }";
return out; return out;
} }
if (config.lighting.enable)
WriteLighting(out, config);
out += "vec4 combiner_buffer = vec4(0.0);\n"; out += "vec4 combiner_buffer = vec4(0.0);\n";
out += "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n"; out += "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n";
out += "vec4 last_tex_env_out = vec4(0.0);\n"; out += "vec4 last_tex_env_out = vec4(0.0);\n";