forked from suyu/suyu
Merge pull request #2776 from wwylele/geo-factor
Fragment lighting: implement geometric factor
This commit is contained in:
commit
d0888f8548
3 changed files with 26 additions and 7 deletions
|
@ -168,6 +168,8 @@ struct LightingRegs {
|
||||||
union {
|
union {
|
||||||
BitField<0, 1, u32> directional;
|
BitField<0, 1, u32> directional;
|
||||||
BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0
|
BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0
|
||||||
|
BitField<2, 1, u32> geometric_factor_0;
|
||||||
|
BitField<3, 1, u32> geometric_factor_1;
|
||||||
} config;
|
} config;
|
||||||
|
|
||||||
BitField<0, 20, u32> dist_atten_bias;
|
BitField<0, 20, u32> dist_atten_bias;
|
||||||
|
|
|
@ -73,6 +73,8 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) {
|
||||||
state.lighting.light[light_index].num = num;
|
state.lighting.light[light_index].num = num;
|
||||||
state.lighting.light[light_index].directional = light.config.directional != 0;
|
state.lighting.light[light_index].directional = light.config.directional != 0;
|
||||||
state.lighting.light[light_index].two_sided_diffuse = light.config.two_sided_diffuse != 0;
|
state.lighting.light[light_index].two_sided_diffuse = light.config.two_sided_diffuse != 0;
|
||||||
|
state.lighting.light[light_index].geometric_factor_0 = light.config.geometric_factor_0 != 0;
|
||||||
|
state.lighting.light[light_index].geometric_factor_1 = light.config.geometric_factor_1 != 0;
|
||||||
state.lighting.light[light_index].dist_atten_enable =
|
state.lighting.light[light_index].dist_atten_enable =
|
||||||
!regs.lighting.IsDistAttenDisabled(num);
|
!regs.lighting.IsDistAttenDisabled(num);
|
||||||
state.lighting.light[light_index].spot_atten_enable =
|
state.lighting.light[light_index].spot_atten_enable =
|
||||||
|
@ -518,7 +520,9 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
"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;";
|
"vec3 spot_dir = vec3(0.0);\n"
|
||||||
|
"vec3 half_vector = vec3(0.0);\n"
|
||||||
|
"float geo_factor = 1.0;\n";
|
||||||
|
|
||||||
// Compute fragment normals and tangents
|
// Compute fragment normals and tangents
|
||||||
const std::string pertubation =
|
const std::string pertubation =
|
||||||
|
@ -561,15 +565,14 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
// Gets the index into the specified lookup table for specular lighting
|
// Gets the index into the specified lookup table for specular lighting
|
||||||
auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input,
|
auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input,
|
||||||
bool abs) {
|
bool abs) {
|
||||||
const std::string half_angle = "normalize(normalize(view) + light_vector)";
|
|
||||||
std::string index;
|
std::string index;
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case LightingRegs::LightingLutInput::NH:
|
case LightingRegs::LightingLutInput::NH:
|
||||||
index = "dot(normal, " + half_angle + ")";
|
index = "dot(normal, normalize(half_vector))";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LightingRegs::LightingLutInput::VH:
|
case LightingRegs::LightingLutInput::VH:
|
||||||
index = std::string("dot(normalize(view), " + half_angle + ")");
|
index = std::string("dot(normalize(view), normalize(half_vector))");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LightingRegs::LightingLutInput::NV:
|
case LightingRegs::LightingLutInput::NV:
|
||||||
|
@ -590,9 +593,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
// Note: even if the normal vector is modified by normal map, which is not the
|
// Note: even if the normal vector is modified by normal map, which is not the
|
||||||
// normal of the tangent plane anymore, the half angle vector is still projected
|
// normal of the tangent plane anymore, the half angle vector is still projected
|
||||||
// using the modified normal vector.
|
// using the modified normal vector.
|
||||||
std::string half_angle_proj = half_angle +
|
std::string half_angle_proj = "normalize(half_vector) - normal / dot(normal, "
|
||||||
" - normal / dot(normal, normal) * dot(normal, " +
|
"normal) * dot(normal, normalize(half_vector))";
|
||||||
half_angle + ")";
|
|
||||||
// Note: the half angle vector projection is confirmed not normalized before the dot
|
// Note: the half angle vector projection is confirmed not normalized before the dot
|
||||||
// product. The result is in fact not cos(phi) as the name suggested.
|
// product. The result is in fact not cos(phi) as the name suggested.
|
||||||
index = "dot(" + half_angle_proj + ", tangent)";
|
index = "dot(" + half_angle_proj + ", tangent)";
|
||||||
|
@ -638,6 +640,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
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";
|
out += "spot_dir = " + light_src + ".spot_direction;\n";
|
||||||
|
out += "half_vector = normalize(view) + light_vector;\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
|
||||||
|
@ -671,6 +674,12 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
std::string clamp_highlights =
|
std::string clamp_highlights =
|
||||||
lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0";
|
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) {
|
||||||
|
out += "geo_factor = dot(half_vector, half_vector);\n"
|
||||||
|
"geo_factor = geo_factor == 0.0 ? 0.0 : min(" +
|
||||||
|
dot_product + " / geo_factor, 1.0);\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Specular 0 component
|
// Specular 0 component
|
||||||
std::string d0_lut_value = "1.0";
|
std::string d0_lut_value = "1.0";
|
||||||
if (lighting.lut_d0.enable &&
|
if (lighting.lut_d0.enable &&
|
||||||
|
@ -683,6 +692,9 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
GetLutValue(LightingRegs::LightingSampler::Distribution0, index) + ")";
|
GetLutValue(LightingRegs::LightingSampler::Distribution0, index) + ")";
|
||||||
}
|
}
|
||||||
std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)";
|
std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)";
|
||||||
|
if (light_config.geometric_factor_0) {
|
||||||
|
specular_0 = "(" + specular_0 + " * geo_factor)";
|
||||||
|
}
|
||||||
|
|
||||||
// If enabled, lookup ReflectRed value, otherwise, 1.0 is used
|
// If enabled, lookup ReflectRed value, otherwise, 1.0 is used
|
||||||
if (lighting.lut_rr.enable &&
|
if (lighting.lut_rr.enable &&
|
||||||
|
@ -738,6 +750,9 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
}
|
}
|
||||||
std::string specular_1 =
|
std::string specular_1 =
|
||||||
"(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)";
|
"(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)";
|
||||||
|
if (light_config.geometric_factor_1) {
|
||||||
|
specular_1 = "(" + specular_1 + " * geo_factor)";
|
||||||
|
}
|
||||||
|
|
||||||
// Fresnel
|
// Fresnel
|
||||||
if (lighting.lut_fr.enable &&
|
if (lighting.lut_fr.enable &&
|
||||||
|
|
|
@ -94,6 +94,8 @@ union PicaShaderConfig {
|
||||||
bool two_sided_diffuse;
|
bool two_sided_diffuse;
|
||||||
bool dist_atten_enable;
|
bool dist_atten_enable;
|
||||||
bool spot_atten_enable;
|
bool spot_atten_enable;
|
||||||
|
bool geometric_factor_0;
|
||||||
|
bool geometric_factor_1;
|
||||||
} light[8];
|
} light[8];
|
||||||
|
|
||||||
bool enable;
|
bool enable;
|
||||||
|
|
Loading…
Reference in a new issue