From 506644b9d610fb0e8bfb26f8e043a770fba30bfe Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Thu, 30 Mar 2023 05:12:09 -0700
Subject: [PATCH] video_core: Fix distance vector used when calculating
 lighting distance attenuation. (#6366)

---
 src/video_core/renderer_opengl/gl_shader_gen.cpp | 11 +++++++----
 src/video_core/renderer_software/sw_lighting.cpp |  3 +--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index f70a1adea..e7e0953e7 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -626,6 +626,7 @@ static void WriteLighting(std::string& out, const PicaFSConfig& config) {
     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"
            "vec3 light_vector = vec3(0.0);\n"
+           "float light_distance = 0.0;\n"
            "vec3 refl_value = vec3(0.0);\n"
            "vec3 spot_dir = vec3(0.0);\n"
            "vec3 half_vector = vec3(0.0);\n"
@@ -752,10 +753,12 @@ static void WriteLighting(std::string& out, const PicaFSConfig& config) {
 
         // Compute light vector (directional or positional)
         if (light_config.directional) {
-            out += fmt::format("light_vector = normalize({}.position);\n", light_src);
+            out += fmt::format("light_vector = {}.position;\n", light_src);
         } else {
-            out += fmt::format("light_vector = normalize({}.position + view);\n", light_src);
+            out += fmt::format("light_vector = {}.position + view;\n", light_src);
         }
+        out += fmt::format("light_distance = length(light_vector);\n", light_src);
+        out += fmt::format("light_vector = normalize(light_vector);\n", light_src);
 
         out += fmt::format("spot_dir = {}.spot_direction;\n", light_src);
         out += "half_vector = normalize(view) + light_vector;\n";
@@ -785,8 +788,8 @@ static void WriteLighting(std::string& out, const PicaFSConfig& config) {
         // If enabled, compute distance attenuation value
         std::string dist_atten = "1.0";
         if (light_config.dist_atten_enable) {
-            const std::string index = fmt::format("clamp({}.dist_atten_scale * length(-view - "
-                                                  "{}.position) + {}.dist_atten_bias, 0.0, 1.0)",
+            const std::string index = fmt::format("clamp({}.dist_atten_scale * light_distance "
+                                                  "+ {}.dist_atten_bias, 0.0, 1.0)",
                                                   light_src, light_src, light_src);
             const auto sampler = LightingRegs::DistanceAttenuationSampler(light_config.num);
             dist_atten = fmt::format("LookupLightingLUTUnsigned({}, {})", sampler, index);
diff --git a/src/video_core/renderer_software/sw_lighting.cpp b/src/video_core/renderer_software/sw_lighting.cpp
index 83f966635..c1138bcf9 100644
--- a/src/video_core/renderer_software/sw_lighting.cpp
+++ b/src/video_core/renderer_software/sw_lighting.cpp
@@ -90,13 +90,12 @@ std::tuple<Common::Vec4<u8>, Common::Vec4<u8>> ComputeFragmentsColors(
 
         float dist_atten = 1.0f;
         if (!lighting.IsDistAttenDisabled(num)) {
-            auto distance = (-view - position).Length();
             float scale = Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32();
             float bias = Pica::float20::FromRaw(light_config.dist_atten_bias).ToFloat32();
             std::size_t lut =
                 static_cast<std::size_t>(LightingRegs::LightingSampler::DistanceAttenuation) + num;
 
-            float sample_loc = std::clamp(scale * distance + bias, 0.0f, 1.0f);
+            float sample_loc = std::clamp(scale * length + bias, 0.0f, 1.0f);
 
             u8 lutindex =
                 static_cast<u8>(std::clamp(std::floor(sample_loc * 256.0f), 0.0f, 255.0f));