mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 19:00:06 +00:00
gl_rasterizer: implement spot light
This commit is contained in:
parent
686cbf3ac6
commit
10906dceec
@ -508,7 +508,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||||
"vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
"vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||||
"vec3 light_vector = vec3(0.0);\n"
|
"vec3 light_vector = vec3(0.0);\n"
|
||||||
"vec3 refl_value = vec3(0.0);\n";
|
"vec3 refl_value = vec3(0.0);\n"
|
||||||
|
"vec3 spot_dir = vec3(0.0);\n;";
|
||||||
|
|
||||||
// Compute fragment normals
|
// Compute fragment normals
|
||||||
if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) {
|
if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) {
|
||||||
@ -569,6 +570,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
index = std::string("dot(light_vector, normal)");
|
index = std::string("dot(light_vector, normal)");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LightingRegs::LightingLutInput::SP:
|
||||||
|
index = std::string("dot(light_vector, spot_dir)");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input);
|
LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
@ -605,21 +610,34 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
else
|
else
|
||||||
out += "light_vector = normalize(" + light_src + ".position + view);\n";
|
out += "light_vector = normalize(" + light_src + ".position + view);\n";
|
||||||
|
|
||||||
|
out += "spot_dir = " + light_src + ".spot_direction;\n";
|
||||||
|
|
||||||
// Compute dot product of light_vector and normal, adjust if lighting is one-sided or
|
// Compute dot product of light_vector and normal, adjust if lighting is one-sided or
|
||||||
// two-sided
|
// two-sided
|
||||||
std::string dot_product = light_config.two_sided_diffuse
|
std::string dot_product = light_config.two_sided_diffuse
|
||||||
? "abs(dot(light_vector, normal))"
|
? "abs(dot(light_vector, normal))"
|
||||||
: "max(dot(light_vector, normal), 0.0)";
|
: "max(dot(light_vector, normal), 0.0)";
|
||||||
|
|
||||||
|
// If enabled, compute spot light attenuation value
|
||||||
|
std::string spot_atten = "1.0";
|
||||||
|
if (light_config.spot_atten_enable &&
|
||||||
|
LightingRegs::IsLightingSamplerSupported(
|
||||||
|
lighting.config, LightingRegs::LightingSampler::SpotlightAttenuation)) {
|
||||||
|
std::string index =
|
||||||
|
GetLutIndex(light_config.num, lighting.lut_sp.type, lighting.lut_sp.abs_input);
|
||||||
|
auto sampler = LightingRegs::SpotlightAttenuationSampler(light_config.num);
|
||||||
|
spot_atten = "(" + std::to_string(lighting.lut_sp.scale) + " * " +
|
||||||
|
GetLutValue(sampler, index) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
// 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_enable) {
|
if (light_config.dist_atten_enable) {
|
||||||
std::string index = "(" + light_src + ".dist_atten_scale * length(-view - " +
|
std::string index = "(" + light_src + ".dist_atten_scale * length(-view - " +
|
||||||
light_src + ".position) + " + light_src + ".dist_atten_bias)";
|
light_src + ".position) + " + light_src + ".dist_atten_bias)";
|
||||||
index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))";
|
index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))";
|
||||||
const unsigned lut_num =
|
auto sampler = LightingRegs::DistanceAttenuationSampler(light_config.num);
|
||||||
((unsigned)LightingRegs::LightingSampler::DistanceAttenuation + light_config.num);
|
dist_atten = GetLutValue(sampler, index);
|
||||||
dist_atten = GetLutValue((LightingRegs::LightingSampler)lut_num, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If enabled, clamp specular component if lighting result is negative
|
// If enabled, clamp specular component if lighting result is negative
|
||||||
@ -720,11 +738,11 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
|||||||
|
|
||||||
// Compute primary fragment color (diffuse lighting) function
|
// Compute primary fragment color (diffuse lighting) function
|
||||||
out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * " + dot_product + ") + " +
|
out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * " + dot_product + ") + " +
|
||||||
light_src + ".ambient) * " + dist_atten + ";\n";
|
light_src + ".ambient) * " + dist_atten + " * " + spot_atten + ";\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 + ";\n";
|
clamp_highlights + " * " + dist_atten + " * " + spot_atten + ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum final lighting result
|
// Sum final lighting result
|
||||||
|
Loading…
Reference in New Issue
Block a user