|
|
|
@ -35,8 +35,7 @@ static void AppendSource(std::string& out, TevStageConfig::Source source, |
|
|
|
out += "primary_fragment_color"; |
|
|
|
break; |
|
|
|
case Source::SecondaryFragmentColor: |
|
|
|
// HACK: Until we implement fragment lighting, use zero
|
|
|
|
out += "vec4(0.0)"; |
|
|
|
out += "secondary_fragment_color"; |
|
|
|
break; |
|
|
|
case Source::Texture0: |
|
|
|
out += "texture(tex[0], texcoord[0])"; |
|
|
|
@ -334,6 +333,8 @@ in vec3 view; |
|
|
|
out vec4 color; |
|
|
|
|
|
|
|
struct LightSrc { |
|
|
|
vec3 specular_0; |
|
|
|
vec3 specular_1; |
|
|
|
vec3 diffuse; |
|
|
|
vec3 ambient; |
|
|
|
vec3 position; |
|
|
|
@ -358,6 +359,7 @@ uniform sampler2D tex[3]; |
|
|
|
|
|
|
|
void main() { |
|
|
|
vec4 primary_fragment_color = vec4(0.0); |
|
|
|
vec4 secondary_fragment_color = vec4(0.0); |
|
|
|
)"; |
|
|
|
|
|
|
|
if (config.lighting_enabled) { |
|
|
|
@ -367,41 +369,97 @@ vec4 primary_fragment_color = vec4(0.0); |
|
|
|
out += " 1.f - 2.f*(normquat.x*normquat.x + normquat.y*normquat.y)));\n"; |
|
|
|
out += "vec4 secondary_color = vec4(0.0);\n"; |
|
|
|
out += "vec3 diffuse_sum = vec3(0.0);\n"; |
|
|
|
out += "vec3 specular_sum = vec3(0.0);\n"; |
|
|
|
out += "vec3 fragment_position = -view;\n"; |
|
|
|
out += "vec3 light_vector = vec3(0.0);\n"; |
|
|
|
out += "float dist_atten = 1.0;\n"; |
|
|
|
|
|
|
|
// Gets the index into the specified lookup table for specular lighting
|
|
|
|
auto GetLutIndex = [&](unsigned light_num, Regs::LightingLutInput input, bool abs) { |
|
|
|
const std::string half_angle = "normalize(view + light_vector)"; |
|
|
|
std::string index; |
|
|
|
switch (input) { |
|
|
|
case Regs::LightingLutInput::NH: |
|
|
|
index = "dot(normal, " + half_angle + ")"; |
|
|
|
break; |
|
|
|
|
|
|
|
case Regs::LightingLutInput::VH: |
|
|
|
index = std::string("dot(view, " + half_angle + ")"); |
|
|
|
break; |
|
|
|
|
|
|
|
case Regs::LightingLutInput::NV: |
|
|
|
index = std::string("dot(normal, view)"); |
|
|
|
break; |
|
|
|
|
|
|
|
case Regs::LightingLutInput::LN: |
|
|
|
index = std::string("dot(light_vector, normal)"); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input); |
|
|
|
UNIMPLEMENTED(); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (abs) { |
|
|
|
// In the range of [ 0.f, 1.f]
|
|
|
|
index = config.light_src[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)"; |
|
|
|
return "clamp(int(" + index + " * 256.0), 0, 255)"; |
|
|
|
} else { |
|
|
|
// In the range of [-1.f, 1.f]
|
|
|
|
index = "clamp(" + index + ", -1.0, 1.0)"; |
|
|
|
return std::string("uint(int(" + index + " * 127.f) & 0xff)"); |
|
|
|
} |
|
|
|
|
|
|
|
return std::string(); |
|
|
|
}; |
|
|
|
|
|
|
|
for (unsigned light_index = 0; light_index < config.num_lights; ++light_index) { |
|
|
|
unsigned num = config.light_src[light_index].num; |
|
|
|
std::string light_src = "light_src[" + std::to_string(num) + "]"; |
|
|
|
|
|
|
|
std::string light_vector; |
|
|
|
if (config.light_src[light_index].directional) |
|
|
|
light_vector = "normalize(-" + light_src + ".position)"; |
|
|
|
out += "light_vector = normalize(-" + light_src + ".position);\n"; |
|
|
|
else |
|
|
|
light_vector = "normalize(" + light_src + ".position - fragment_position)"; |
|
|
|
out += "light_vector = normalize(" + light_src + ".position - fragment_position);\n"; |
|
|
|
|
|
|
|
std::string dot_product; |
|
|
|
if (config.light_src[light_index].two_sided_diffuse) |
|
|
|
dot_product = "abs(dot(" + light_vector + ", normal))"; |
|
|
|
dot_product = "abs(dot(light_vector, normal))"; |
|
|
|
else |
|
|
|
dot_product = "max(dot(" + light_vector + ", normal), 0.0)"; |
|
|
|
dot_product = "max(dot(light_vector, normal), 0.0)"; |
|
|
|
|
|
|
|
std::string dist_atten = "1.0"; |
|
|
|
// Compute distance attenuation value
|
|
|
|
out += "dist_atten = 1.0;\n"; |
|
|
|
if (config.light_src[light_index].dist_atten_enabled) { |
|
|
|
std::string scale = std::to_string(config.light_src[light_index].dist_atten_scale); |
|
|
|
std::string bias = std::to_string(config.light_src[light_index].dist_atten_bias); |
|
|
|
std::string lut_index = "(" + scale + " * length(fragment_position - " + light_src + ".position) + " + bias + ")"; |
|
|
|
std::string clamped_lut_index = "((clamp(int(" + lut_index + " * 256.0), 0, 255)))"; |
|
|
|
|
|
|
|
unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + num); |
|
|
|
|
|
|
|
dist_atten = "lighting_lut_" + std::to_string(lut_num /4) + "[" + clamped_lut_index + "][" + std::to_string(lut_num & 3) + "]"; |
|
|
|
const unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + num); |
|
|
|
out += "dist_atten = lighting_lut_" + std::to_string(lut_num / 4) + "[" + clamped_lut_index + "][" + std::to_string(lut_num & 3) + "];\n"; |
|
|
|
} |
|
|
|
|
|
|
|
out += "diffuse_sum += ((light_src[" + std::to_string(num) + "].diffuse * " + dot_product + ") + light_src[" + std::to_string(num) + "].ambient) * " + dist_atten + ";\n"; |
|
|
|
// Compute primary fragment color (diffuse lighting) function
|
|
|
|
out += "diffuse_sum += ((light_src[" + std::to_string(num) + "].diffuse * " + dot_product + ") + light_src[" + std::to_string(num) + "].ambient) * dist_atten;\n"; |
|
|
|
|
|
|
|
// Compute secondary fragment color (specular lighting) function
|
|
|
|
std::string clamped_lut_index = GetLutIndex(num, config.lighting_lut.d0_type, config.lighting_lut.d0_abs); |
|
|
|
const unsigned lut_num = (unsigned)Regs::LightingSampler::Distribution0; |
|
|
|
std::string lut_lookup = "lighting_lut_" + std::to_string(lut_num / 4) + "[" + clamped_lut_index + "][" + std::to_string(lut_num & 3) + "]"; |
|
|
|
|
|
|
|
out += "specular_sum += (" + lut_lookup + " * light_src[" + std::to_string(num) + "].specular_0 * dist_atten);\n"; |
|
|
|
} |
|
|
|
|
|
|
|
out += "float clamp_highlights = 1.0;\n"; |
|
|
|
if (config.clamp_highlights) { |
|
|
|
out += "if (dot(light_vector, normal) <= 0.0) clamp_highlights = 0.0;\n"; |
|
|
|
} |
|
|
|
|
|
|
|
out += "diffuse_sum += lighting_global_ambient;\n"; |
|
|
|
out += "primary_fragment_color = vec4(clamp(diffuse_sum, vec3(0.0), vec3(1.0)), 1.0);\n"; |
|
|
|
out += "secondary_fragment_color = vec4(clamp(clamp_highlights * specular_sum, vec3(0.0), vec3(1.0)), 1.0);\n"; |
|
|
|
} |
|
|
|
|
|
|
|
// Do not do any sort of processing if it's obvious we're not going to pass the alpha test
|
|
|
|
|