From e34fa6365ff87af247b0ae8ed880c4032bcb2ed0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 13 Nov 2015 23:04:19 -0500 Subject: [PATCH] renderer_opengl: Implement HW fragment lighting distance attenuation. --- .../renderer_opengl/gl_rasterizer.h | 34 ++++++++++++------- .../renderer_opengl/gl_shader_gen.cpp | 19 +++++++++-- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index fa4a78cb1..ba0b05802 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -78,9 +78,13 @@ struct PicaShaderConfig { for (unsigned light_index = 0; light_index < res.num_lights; ++light_index) { unsigned num = regs.lighting.light_enable.GetNum(light_index); + const auto& light = regs.lighting.light[num]; res.light_src[light_index].num = num; - res.light_src[light_index].directional = regs.lighting.light[num].w; - res.light_src[light_index].two_sided_diffuse = regs.lighting.light[num].two_sided_diffuse; + res.light_src[light_index].directional = light.w; + res.light_src[light_index].two_sided_diffuse = light.two_sided_diffuse; + res.light_src[light_index].dist_atten_enabled = regs.lighting.dist_atten_enable.IsEnabled(num); + res.light_src[light_index].dist_atten_bias = Pica::float20::FromRawFloat20(light.dist_atten_bias).ToFloat32(); + res.light_src[light_index].dist_atten_scale = Pica::float20::FromRawFloat20(light.dist_atten_scale).ToFloat32(); } return res; @@ -98,19 +102,23 @@ struct PicaShaderConfig { return std::memcmp(this, &o, sizeof(PicaShaderConfig)) == 0; }; - Pica::Regs::CompareFunc alpha_test_func; - std::array tev_stages = {}; - u8 combiner_buffer_input; - struct { - unsigned num; - bool directional; - bool two_sided_diffuse; - bool dist_atten_enabled; - } light_src[8]; + Pica::Regs::CompareFunc alpha_test_func = Pica::Regs::CompareFunc::Never; + std::array tev_stages = {}; + u8 combiner_buffer_input = 0; - bool lighting_enabled; - unsigned num_lights; + struct { + unsigned num = 0; + bool directional = false; + bool two_sided_diffuse = false; + bool dist_atten_enabled = false; + GLfloat dist_atten_scale = 0.0f; + GLfloat dist_atten_bias = 0.0f; + } light_src[8]; + + bool lighting_enabled = false; + unsigned num_lights = 0; + }; }; namespace std { diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 4e02671dd..cf99cff76 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -371,12 +371,13 @@ vec4 primary_fragment_color = vec4(0.0); 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[" + std::to_string(num) + "].position)"; + light_vector = "normalize(-" + light_src + ".position)"; else - light_vector = "normalize(light_src[" + std::to_string(num) + "].position - fragment_position)"; + light_vector = "normalize(" + light_src + ".position - fragment_position)"; std::string dot_product; if (config.light_src[light_index].two_sided_diffuse) @@ -384,7 +385,19 @@ vec4 primary_fragment_color = vec4(0.0); else dot_product = "max(dot(" + light_vector + ", normal), 0.0)"; - out += "diffuse_sum += ((light_src[" + std::to_string(num) + "].diffuse * " + dot_product + ") + light_src[" + std::to_string(num) + "].ambient) * 1.0;\n"; + std::string dist_atten = "1.0"; + 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) + "]"; + } + + out += "diffuse_sum += ((light_src[" + std::to_string(num) + "].diffuse * " + dot_product + ") + light_src[" + std::to_string(num) + "].ambient) * " + dist_atten + ";\n"; } out += "diffuse_sum += lighting_global_ambient;\n";