Merge pull request #3484 from wwylele/highlight-fix
pica/lighting: compute highlight clamp after one-/two-sided diffuse pass
This commit is contained in:
commit
9e4f670ea9
|
@ -562,6 +562,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
"vec3 refl_value = vec3(0.0);\n"
|
"vec3 refl_value = vec3(0.0);\n"
|
||||||
"vec3 spot_dir = vec3(0.0);\n"
|
"vec3 spot_dir = vec3(0.0);\n"
|
||||||
"vec3 half_vector = vec3(0.0);\n"
|
"vec3 half_vector = vec3(0.0);\n"
|
||||||
|
"float dot_product = 0.0;\n"
|
||||||
|
"float clamp_highlights = 1.0;\n"
|
||||||
"float geo_factor = 1.0;\n";
|
"float geo_factor = 1.0;\n";
|
||||||
|
|
||||||
// Compute fragment normals and tangents
|
// Compute fragment normals and tangents
|
||||||
|
@ -680,9 +682,14 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
|
|
||||||
// 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
|
out += std::string("dot_product = ") + (light_config.two_sided_diffuse
|
||||||
? "abs(dot(light_vector, normal))"
|
? "abs(dot(light_vector, normal));\n"
|
||||||
: "max(dot(light_vector, normal), 0.0)";
|
: "max(dot(light_vector, normal), 0.0);\n");
|
||||||
|
|
||||||
|
// If enabled, clamp specular component if lighting result is zero
|
||||||
|
if (lighting.clamp_highlights) {
|
||||||
|
out += "clamp_highlights = sign(dot_product);\n";
|
||||||
|
}
|
||||||
|
|
||||||
// If enabled, compute spot light attenuation value
|
// If enabled, compute spot light attenuation value
|
||||||
std::string spot_atten = "1.0";
|
std::string spot_atten = "1.0";
|
||||||
|
@ -706,14 +713,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
std::to_string(static_cast<unsigned>(sampler)) + "," + index + ")";
|
std::to_string(static_cast<unsigned>(sampler)) + "," + index + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If enabled, clamp specular component if lighting result is negative
|
|
||||||
std::string clamp_highlights =
|
|
||||||
lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0";
|
|
||||||
|
|
||||||
if (light_config.geometric_factor_0 || light_config.geometric_factor_1) {
|
if (light_config.geometric_factor_0 || light_config.geometric_factor_1) {
|
||||||
out += "geo_factor = dot(half_vector, half_vector);\n"
|
out += "geo_factor = dot(half_vector, half_vector);\n"
|
||||||
"geo_factor = geo_factor == 0.0 ? 0.0 : min(" +
|
"geo_factor = geo_factor == 0.0 ? 0.0 : min("
|
||||||
dot_product + " / geo_factor, 1.0);\n";
|
"dot_product / geo_factor, 1.0);\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specular 0 component
|
// Specular 0 component
|
||||||
|
@ -814,12 +817,12 @@ 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 +
|
||||||
light_src + ".ambient) * " + dist_atten + " * " + spot_atten + ";\n";
|
".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 + " * " + spot_atten + ";\n";
|
") * clamp_highlights * " + dist_atten + " * " + spot_atten + ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum final lighting result
|
// Sum final lighting result
|
||||||
|
|
|
@ -256,22 +256,16 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dot_product = Math::Dot(light_vector, normal);
|
auto dot_product = Math::Dot(light_vector, normal);
|
||||||
|
|
||||||
// Calculate clamp highlights before applying the two-sided diffuse configuration to the dot
|
|
||||||
// product.
|
|
||||||
float clamp_highlights = 1.0f;
|
|
||||||
if (lighting.config0.clamp_highlights) {
|
|
||||||
if (dot_product <= 0.0f)
|
|
||||||
clamp_highlights = 0.0f;
|
|
||||||
else
|
|
||||||
clamp_highlights = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (light_config.config.two_sided_diffuse)
|
if (light_config.config.two_sided_diffuse)
|
||||||
dot_product = std::abs(dot_product);
|
dot_product = std::abs(dot_product);
|
||||||
else
|
else
|
||||||
dot_product = std::max(dot_product, 0.0f);
|
dot_product = std::max(dot_product, 0.0f);
|
||||||
|
|
||||||
|
float clamp_highlights = 1.0f;
|
||||||
|
if (lighting.config0.clamp_highlights) {
|
||||||
|
clamp_highlights = dot_product == 0.0f ? 0.0f : 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if (light_config.config.geometric_factor_0 || light_config.config.geometric_factor_1) {
|
if (light_config.config.geometric_factor_0 || light_config.config.geometric_factor_1) {
|
||||||
float geo_factor = half_vector.Length2();
|
float geo_factor = half_vector.Length2();
|
||||||
geo_factor = geo_factor == 0.0f ? 0.0f : std::min(dot_product / geo_factor, 1.0f);
|
geo_factor = geo_factor == 0.0f ? 0.0f : std::min(dot_product / geo_factor, 1.0f);
|
||||||
|
|
Reference in New Issue