From b2f472a2b1f36073b0070b81c08a666380ad180d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 13:14:55 -0500 Subject: [PATCH 01/27] SwRasterizer: Implement primary fragment color. --- src/video_core/swrasterizer/rasterizer.cpp | 119 ++++++++++++++++++++- 1 file changed, 114 insertions(+), 5 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 512e81c08..1ab41c2df 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -13,6 +13,7 @@ #include "common/logging/log.h" #include "common/math_util.h" #include "common/microprofile.h" +#include "common/quaternion.h" #include "common/vector_math.h" #include "core/hw/gpu.h" #include "core/memory.h" @@ -114,6 +115,86 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v return std::make_tuple(x / z * half + half, y / z * half + half, addr); } +std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Quaternion& normquat, const Math::Vec3& view) { + const auto& lighting = g_state.regs.lighting; + + if (lighting.disable) + return {{}, {}}; + + // TODO(Subv): Bump mapping + Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; + + if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) { + LOG_CRITICAL(HW_GPU, "unimplemented bump mapping"); + UNIMPLEMENTED(); + } + + // TODO(Subv): Do we need to normalize the quaternion here? + auto normal = Math::QuaternionRotate(normquat, surface_normal); + + Math::Vec3 light_vector = {}; + Math::Vec3 diffuse_sum = {}; + // TODO(Subv): Calculate specular + Math::Vec3 specular_sum = {}; + + for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { + unsigned num = lighting.light_enable.GetNum(light_index); + const auto& light_config = g_state.regs.lighting.light[num]; + + Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), float16::FromRaw(light_config.y).ToFloat32(), float16::FromRaw(light_config.z).ToFloat32()}; + + if (light_config.config.directional) + light_vector = position; + else + light_vector = position + view; + + light_vector.Normalize(); + + auto dot_product = Math::Dot(light_vector, normal); + + if (light_config.config.two_sided_diffuse) + dot_product = std::abs(dot_product); + else + dot_product = std::max(dot_product, 0.0f); + + 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_scale).ToFloat32(); + size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; + + float sample_loc = scale * distance + bias; + unsigned index_i = static_cast(MathUtil::Clamp(floor(sample_loc * 256), 0.0f, 1.0f)); + + float index_f = sample_loc - index_i; + + ASSERT_MSG(lut < g_state.lighting.luts.size(), "Out of range lut"); + + float lut_value = g_state.lighting.luts[lut][index_i].ToFloat(); + float lut_diff = g_state.lighting.luts[lut][index_i].DiffToFloat(); + + dist_atten = lut_value + lut_diff * index_f; + } + + auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); + diffuse_sum += diffuse * dist_atten; + } + + diffuse_sum += lighting.global_ambient.ToVec3f(); + return { + Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, 255).Cast(), + Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, 255).Cast() + }; +} + +static bool AreQuaternionsOpposite(Math::Vec4 qa, Math::Vec4 qb) { + Math::Vec4f a{ qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32() }; + Math::Vec4f b{ qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32() }; + + return (Math::Dot(a, b) < 0.f); +} + MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); /** @@ -207,6 +288,15 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; + // Flip the quaternions if they are opposite to prevent interpolating them over the wrong direction. + auto v1_quat = v1.quat; + auto v2_quat = v2.quat; + + if (AreQuaternionsOpposite(v0.quat, v1.quat)) + v1_quat = v1_quat * float24::FromFloat32(-1.0f); + if (AreQuaternionsOpposite(v0.quat, v2.quat)) + v2_quat = v2_quat * float24::FromFloat32(-1.0f); + auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); auto textures = regs.texturing.GetTextures(); @@ -305,6 +395,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve 255), }; + Math::Quaternion normquat{ + { + GetInterpolatedAttribute(v0.quat.x, v1_quat.x, v2_quat.x).ToFloat32(), + GetInterpolatedAttribute(v0.quat.y, v1_quat.y, v2_quat.y).ToFloat32(), + GetInterpolatedAttribute(v0.quat.z, v1_quat.z, v2_quat.z).ToFloat32() + }, + GetInterpolatedAttribute(v0.quat.w, v1_quat.w, v2_quat.w).ToFloat32(), + }; + + Math::Vec3 fragment_position{ + GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), + GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(), + GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32() + }; + Math::Vec2 uv[3]; uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); @@ -419,6 +524,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve regs.texturing.tev_combiner_buffer_color.a, }; + Math::Vec4 primary_fragment_color; + Math::Vec4 secondary_fragment_color; + + std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors(normquat, fragment_position); + for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) { const auto& tev_stage = tev_stages[tev_stage_index]; @@ -427,14 +537,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve auto GetSource = [&](Source source) -> Math::Vec4 { switch (source) { case Source::PrimaryColor: - - // HACK: Until we implement fragment lighting, use primary_color - case Source::PrimaryFragmentColor: return primary_color; - // HACK: Until we implement fragment lighting, use zero + case Source::PrimaryFragmentColor: + return primary_fragment_color; + case Source::SecondaryFragmentColor: - return {0, 0, 0, 0}; + return secondary_fragment_color; case Source::Texture0: return texture_color[0]; From be25e78b07140cb745387f757001dd04b3b4cc64 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:25:41 -0500 Subject: [PATCH 02/27] SwRasterizer: Calculate specular_0 for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 115 ++++++++++++++++++--- 1 file changed, 98 insertions(+), 17 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 1ab41c2df..34b84b0af 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -115,6 +115,20 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v return std::make_tuple(x / z * half + half, y / z * half + half, addr); } + +float LookupLightingLut(size_t lut_index, float index) { + unsigned index_i = static_cast(MathUtil::Clamp(floor(index * 256), 0.0f, 1.0f)); + + float index_f = index - index_i; + + ASSERT_MSG(lut_index < g_state.lighting.luts.size(), "Out of range lut"); + + float lut_value = g_state.lighting.luts[lut_index][index_i].ToFloat(); + float lut_diff = g_state.lighting.luts[lut_index][index_i].DiffToFloat(); + + return lut_value + lut_diff * index_f; +} + std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Quaternion& normquat, const Math::Vec3& view) { const auto& lighting = g_state.regs.lighting; @@ -133,9 +147,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu auto normal = Math::QuaternionRotate(normquat, surface_normal); Math::Vec3 light_vector = {}; - Math::Vec3 diffuse_sum = {}; + Math::Vec4 diffuse_sum = {0.f, 0.f, 0.f, 1.f}; // TODO(Subv): Calculate specular - Math::Vec3 specular_sum = {}; + Math::Vec4 specular_sum = {0.f, 0.f, 0.f, 1.f}; for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { unsigned num = lighting.light_enable.GetNum(light_index); @@ -150,7 +164,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu light_vector.Normalize(); - auto dot_product = Math::Dot(light_vector, normal); + auto LV_N = Math::Dot(light_vector, normal); + auto dot_product = LV_N; if (light_config.config.two_sided_diffuse) dot_product = std::abs(dot_product); @@ -165,26 +180,92 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; float sample_loc = scale * distance + bias; - unsigned index_i = static_cast(MathUtil::Clamp(floor(sample_loc * 256), 0.0f, 1.0f)); - - float index_f = sample_loc - index_i; - - ASSERT_MSG(lut < g_state.lighting.luts.size(), "Out of range lut"); - - float lut_value = g_state.lighting.luts[lut][index_i].ToFloat(); - float lut_diff = g_state.lighting.luts[lut][index_i].DiffToFloat(); - - dist_atten = lut_value + lut_diff * index_f; + dist_atten = LookupLightingLut(lut, sample_loc); } + float clamp_highlights = 1.0f; + + if (lighting.config0.clamp_highlights) { + if (LV_N <= 0.f) + clamp_highlights = 0.f; + else + clamp_highlights = 1.f; + } + + auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, + bool abs) -> float { + + Math::Vec3 norm_view = view.Normalized(); + Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); + float result = 0.0f; + + switch (input) { + case LightingRegs::LightingLutInput::NH: + result = Math::Dot(normal, half_angle); + break; + + case LightingRegs::LightingLutInput::VH: + result = Math::Dot(norm_view, half_angle); + break; + + case LightingRegs::LightingLutInput::NV: + result = Math::Dot(normal, norm_view); + break; + + case LightingRegs::LightingLutInput::LN: + result = Math::Dot(light_vector, normal); + break; + + default: + LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input); + UNIMPLEMENTED(); + result = 0.f; + } + + if (abs) { + if (light_config.config.two_sided_diffuse) + result = std::abs(result); + else + result = std::max(result, 0.0f); + } else { + if (result < 0.f) + result += 2.f; + + result /= 2.f; + } + + return MathUtil::Clamp(result, 0.0f, 1.0f); + }; + + // Specular 0 component + float d0_lut_value = 1.0f; + if (lighting.config1.disable_lut_d0 == 0 && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::Distribution0)) { + + // Lookup specular "distribution 0" LUT value + float index = GetLutIndex(num, lighting.lut_input.d0.Value(), lighting.abs_lut_input.disable_d0 == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d0); + + d0_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), index); + } + + Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); + + // TODO(Subv): Specular 1 + Math::Vec3 specular_1 = {}; + auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); - diffuse_sum += diffuse * dist_atten; + diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); + + specular_sum += Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.f); } - diffuse_sum += lighting.global_ambient.ToVec3f(); + diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); return { - Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, 255).Cast(), - Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, 255).Cast() + Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255).Cast(), + Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255).Cast() }; } From 46b8c8e1da6bc29df2662d63b0e028136fef3636 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:44:02 -0500 Subject: [PATCH 03/27] SwRasterizer: Calculate specular_1 for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 62 ++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 34b84b0af..e0c326a4a 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -148,8 +148,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu Math::Vec3 light_vector = {}; Math::Vec4 diffuse_sum = {0.f, 0.f, 0.f, 1.f}; - // TODO(Subv): Calculate specular Math::Vec4 specular_sum = {0.f, 0.f, 0.f, 1.f}; + Math::Vec3 refl_value = {}; for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { unsigned num = lighting.light_enable.GetNum(light_index); @@ -253,8 +253,64 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); - // TODO(Subv): Specular 1 - Math::Vec3 specular_1 = {}; + // If enabled, lookup ReflectRed value, otherwise, 1.0 is used + if (lighting.config1.disable_lut_rr == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectRed)) { + + float index = GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rr); + + refl_value.x = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), index); + } else { + refl_value.x = 1.0f; + } + + // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used + if (lighting.config1.disable_lut_rg == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectGreen)) { + + float index = GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rg); + + refl_value.y = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), index); + } else { + refl_value.y = refl_value.x; + } + + // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used + if (lighting.config1.disable_lut_rb == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectBlue)) { + + float index = GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rb); + + refl_value.z = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), index); + } else { + refl_value.z = refl_value.x; + } + + float d1_lut_value = 1.0f; + if (lighting.config1.disable_lut_d1 == 0 && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::Distribution1)) { + + // Lookup specular "distribution 1" LUT value + float index = GetLutIndex(num, lighting.lut_input.d1.Value(), lighting.abs_lut_input.disable_d1 == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d1); + + d1_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), index); + } + + Math::Vec3 specular_1 = d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); + + // TODO(Subv): Fresnel auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); From 10b0bea06008fea89564dc5ef8895c0274f8ef18 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:55:54 -0500 Subject: [PATCH 04/27] SwRasterizer: Calculate fresnel for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index e0c326a4a..2d1daa24a 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -310,7 +310,31 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu Math::Vec3 specular_1 = d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); - // TODO(Subv): Fresnel + if (lighting.config1.disable_lut_fr == 0 && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { + + // Lookup fresnel LUT value + float index = GetLutIndex(num, lighting.lut_input.fr.Value(), lighting.abs_lut_input.disable_fr == 0); + + float scale = lighting.lut_scale.GetScale(lighting.lut_scale.fr); + + float lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), index); + + // Enabled for difffuse lighting alpha component + if (lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || + lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + diffuse_sum.a() *= lut_value; + } + + // Enabled for the specular lighting alpha component + if (lighting.config0.fresnel_selector == + LightingRegs::LightingFresnelSelector::SecondaryAlpha || + lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + specular_sum.a() *= lut_value; + } + } + auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); From 80b6fc592e3a2f5821975e84b5df35f5dc4ae51a Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 15:24:28 -0500 Subject: [PATCH 05/27] SwRasterizer: Fixed the lighting lut lookup function. --- src/video_core/swrasterizer/rasterizer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 2d1daa24a..2b85ac86c 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -117,7 +117,9 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v float LookupLightingLut(size_t lut_index, float index) { - unsigned index_i = static_cast(MathUtil::Clamp(floor(index * 256), 0.0f, 1.0f)); + index *= 256; + + unsigned index_i = static_cast(MathUtil::Clamp(floor(index), 0.0f, 255.0f)); float index_f = index - index_i; @@ -126,7 +128,7 @@ float LookupLightingLut(size_t lut_index, float index) { float lut_value = g_state.lighting.luts[lut_index][index_i].ToFloat(); float lut_diff = g_state.lighting.luts[lut_index][index_i].DiffToFloat(); - return lut_value + lut_diff * index_f; + return lut_value + lut_diff * index_f / 256.f; } std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Quaternion& normquat, const Math::Vec3& view) { From f2d4d5c2191275bd91f2f42b880f3edf3bccfd63 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 17:33:25 -0500 Subject: [PATCH 06/27] SwRasterizer: Corrected the light LUT lookups. --- src/common/quaternion.h | 5 ++ src/video_core/swrasterizer/rasterizer.cpp | 76 ++++++++++++---------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/common/quaternion.h b/src/common/quaternion.h index 84ac82ed3..77f626bcb 100644 --- a/src/common/quaternion.h +++ b/src/common/quaternion.h @@ -30,6 +30,11 @@ public: return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), w * other.w - Dot(xyz, other.xyz)}; } + + Quaternion Normalized() const { + T length = std::sqrt(xyz.Length2() + w * w); + return {xyz / length, w / length}; + } }; template diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 2b85ac86c..a9098e1f0 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -115,20 +115,14 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v return std::make_tuple(x / z * half + half, y / z * half + half, addr); } - -float LookupLightingLut(size_t lut_index, float index) { - index *= 256; - - unsigned index_i = static_cast(MathUtil::Clamp(floor(index), 0.0f, 255.0f)); - - float index_f = index - index_i; - +float LookupLightingLut(size_t lut_index, u8 index, float delta) { ASSERT_MSG(lut_index < g_state.lighting.luts.size(), "Out of range lut"); + ASSERT_MSG(index < g_state.lighting.luts[0].size(), "Out of range index"); - float lut_value = g_state.lighting.luts[lut_index][index_i].ToFloat(); - float lut_diff = g_state.lighting.luts[lut_index][index_i].DiffToFloat(); + float lut_value = g_state.lighting.luts[lut_index][index].ToFloat(); + float lut_diff = g_state.lighting.luts[lut_index][index].DiffToFloat(); - return lut_value + lut_diff * index_f / 256.f; + return lut_value + lut_diff * delta; } std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Quaternion& normquat, const Math::Vec3& view) { @@ -145,8 +139,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu UNIMPLEMENTED(); } - // TODO(Subv): Do we need to normalize the quaternion here? - auto normal = Math::QuaternionRotate(normquat, surface_normal); + // Use the normalized the quaternion when performing the rotation + auto normal = Math::QuaternionRotate(normquat.Normalized(), surface_normal); Math::Vec3 light_vector = {}; Math::Vec4 diffuse_sum = {0.f, 0.f, 0.f, 1.f}; @@ -182,7 +176,10 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; float sample_loc = scale * distance + bias; - dist_atten = LookupLightingLut(lut, sample_loc); + + u8 lutindex = MathUtil::Clamp(floorf(sample_loc * 256.f), 0.0f, 255.0f); + float delta = sample_loc * 256 - lutindex; + dist_atten = LookupLightingLut(lut, lutindex, delta / 256.f); } float clamp_highlights = 1.0f; @@ -195,7 +192,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu } auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, - bool abs) -> float { + bool abs) -> std::tuple { Math::Vec3 norm_view = view.Normalized(); Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); @@ -229,14 +226,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu result = std::abs(result); else result = std::max(result, 0.0f); + + u8 lutindex = MathUtil::Clamp(floorf(result * 256.f), 0.0f, 255.0f); + float delta = result * 256 - lutindex; + return { lutindex, delta / 256.f }; } else { - if (result < 0.f) - result += 2.f; - - result /= 2.f; + u8 tmpi = MathUtil::Clamp(floorf(result * 128.f), 0.0f, 127.0f); + float delta = result * 128.f - tmpi; + return { tmpi & 0xFF, delta / 128.f }; } - - return MathUtil::Clamp(result, 0.0f, 1.0f); }; // Specular 0 component @@ -246,11 +244,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu lighting.config0.config, LightingRegs::LightingSampler::Distribution0)) { // Lookup specular "distribution 0" LUT value - float index = GetLutIndex(num, lighting.lut_input.d0.Value(), lighting.abs_lut_input.disable_d0 == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d0.Value(), lighting.abs_lut_input.disable_d0 == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d0); - d0_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), index); + d0_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), index, delta); } Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); @@ -260,11 +260,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectRed)) { - float index = GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rr); - refl_value.x = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), index); + refl_value.x = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), index, delta); } else { refl_value.x = 1.0f; } @@ -274,11 +276,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectGreen)) { - float index = GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rg); - refl_value.y = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), index); + refl_value.y = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), index, delta); } else { refl_value.y = refl_value.x; } @@ -288,11 +292,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectBlue)) { - float index = GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rb); - refl_value.z = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), index); + refl_value.z = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), index, delta); } else { refl_value.z = refl_value.x; } @@ -303,11 +309,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu lighting.config0.config, LightingRegs::LightingSampler::Distribution1)) { // Lookup specular "distribution 1" LUT value - float index = GetLutIndex(num, lighting.lut_input.d1.Value(), lighting.abs_lut_input.disable_d1 == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d1.Value(), lighting.abs_lut_input.disable_d1 == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d1); - d1_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), index); + d1_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), index, delta); } Math::Vec3 specular_1 = d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); @@ -317,11 +325,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { // Lookup fresnel LUT value - float index = GetLutIndex(num, lighting.lut_input.fr.Value(), lighting.abs_lut_input.disable_fr == 0); + u8 index; + float delta; + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.fr.Value(), lighting.abs_lut_input.disable_fr == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.fr); - float lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), index); + float lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), index, delta); // Enabled for difffuse lighting alpha component if (lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || From 2a75837bc30ba08e2470f4b91078747a08c5213a Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 18:18:57 -0500 Subject: [PATCH 07/27] SwRasterizer: Corrected the light LUT lookups. --- src/video_core/swrasterizer/rasterizer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index a9098e1f0..2c804b6e7 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -177,9 +177,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu float sample_loc = scale * distance + bias; - u8 lutindex = MathUtil::Clamp(floorf(sample_loc * 256.f), 0.0f, 255.0f); + u8 lutindex = MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f); float delta = sample_loc * 256 - lutindex; - dist_atten = LookupLightingLut(lut, lutindex, delta / 256.f); + dist_atten = LookupLightingLut(lut, lutindex, delta); } float clamp_highlights = 1.0f; @@ -227,13 +227,14 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu else result = std::max(result, 0.0f); - u8 lutindex = MathUtil::Clamp(floorf(result * 256.f), 0.0f, 255.0f); + u8 lutindex = MathUtil::Clamp(std::floor(result * 256.f), 0.0f, 255.0f); float delta = result * 256 - lutindex; - return { lutindex, delta / 256.f }; + return { lutindex, delta }; } else { - u8 tmpi = MathUtil::Clamp(floorf(result * 128.f), 0.0f, 127.0f); + float flr = std::floor(result * 128.f); + s8 tmpi = MathUtil::Clamp(flr, -128.0f, 127.0f); float delta = result * 128.f - tmpi; - return { tmpi & 0xFF, delta / 128.f }; + return { tmpi & 0xFF, delta }; } }; From 73566ff7a990cdfe8d8f023997b57942dc785fc4 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 11 Jun 2017 11:55:35 -0500 Subject: [PATCH 08/27] SwRasterizer: Flip the vertex quaternions before clipping (if necessary). --- src/common/vector_math.h | 2 +- src/video_core/swrasterizer/clipper.cpp | 11 ++++++++++ src/video_core/swrasterizer/rasterizer.cpp | 24 ++++------------------ 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/common/vector_math.h b/src/common/vector_math.h index c7a461a1e..d0fe0e405 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -462,7 +462,7 @@ public: z -= other.z; w -= other.w; } - template ::value>::type> + template Vec4 operator-() const { return MakeVec(-x, -y, -z, -w); } diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index 6fb923756..7537689b7 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -95,6 +95,17 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu static const size_t MAX_VERTICES = 9; static_vector buffer_a = {v0, v1, v2}; static_vector buffer_b; + + auto FlipQuaternionIfOpposite = [](auto& a, const auto& b) { + if (Math::Dot(a, b) < float24::Zero()) + a = -a; + }; + + // Flip the quaternions if they are opposite to prevent interpolating them over the wrong + // direction. + FlipQuaternionIfOpposite(buffer_a[1].quat, buffer_a[0].quat); + FlipQuaternionIfOpposite(buffer_a[2].quat, buffer_a[0].quat); + auto* output_list = &buffer_a; auto* input_list = &buffer_b; diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 2c804b6e7..76f793c86 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -362,13 +362,6 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu }; } -static bool AreQuaternionsOpposite(Math::Vec4 qa, Math::Vec4 qb) { - Math::Vec4f a{ qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32() }; - Math::Vec4f b{ qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32() }; - - return (Math::Dot(a, b) < 0.f); -} - MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); /** @@ -462,15 +455,6 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; - // Flip the quaternions if they are opposite to prevent interpolating them over the wrong direction. - auto v1_quat = v1.quat; - auto v2_quat = v2.quat; - - if (AreQuaternionsOpposite(v0.quat, v1.quat)) - v1_quat = v1_quat * float24::FromFloat32(-1.0f); - if (AreQuaternionsOpposite(v0.quat, v2.quat)) - v2_quat = v2_quat * float24::FromFloat32(-1.0f); - auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); auto textures = regs.texturing.GetTextures(); @@ -571,11 +555,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Quaternion normquat{ { - GetInterpolatedAttribute(v0.quat.x, v1_quat.x, v2_quat.x).ToFloat32(), - GetInterpolatedAttribute(v0.quat.y, v1_quat.y, v2_quat.y).ToFloat32(), - GetInterpolatedAttribute(v0.quat.z, v1_quat.z, v2_quat.z).ToFloat32() + GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), + GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), + GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32() }, - GetInterpolatedAttribute(v0.quat.w, v1_quat.w, v2_quat.w).ToFloat32(), + GetInterpolatedAttribute(v0.quat.w, v1.quat.w, v2.quat.w).ToFloat32(), }; Math::Vec3 fragment_position{ From 2d69a9b8bf232fdd9e3bbb2a9c624ee9dd6ec637 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:31:28 -0500 Subject: [PATCH 09/27] SwRasterizer: Run clang-format --- src/video_core/swrasterizer/rasterizer.cpp | 128 +++++++++++++-------- 1 file changed, 83 insertions(+), 45 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 76f793c86..382b5927b 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -125,11 +125,12 @@ float LookupLightingLut(size_t lut_index, u8 index, float delta) { return lut_value + lut_diff * delta; } -std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Quaternion& normquat, const Math::Vec3& view) { +std::tuple, Math::Vec4> ComputeFragmentsColors( + const Math::Quaternion& normquat, const Math::Vec3& view) { const auto& lighting = g_state.regs.lighting; if (lighting.disable) - return {{}, {}}; + return {Math::MakeVec(0, 0, 0, 0), Math::MakeVec(0, 0, 0, 0)}; // TODO(Subv): Bump mapping Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; @@ -151,7 +152,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu unsigned num = lighting.light_enable.GetNum(light_index); const auto& light_config = g_state.regs.lighting.light[num]; - Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), float16::FromRaw(light_config.y).ToFloat32(), float16::FromRaw(light_config.z).ToFloat32()}; + Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), + float16::FromRaw(light_config.y).ToFloat32(), + float16::FromRaw(light_config.z).ToFloat32()}; if (light_config.config.directional) light_vector = position; @@ -173,11 +176,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu 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_scale).ToFloat32(); - size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; + size_t lut = + static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; float sample_loc = scale * distance + bias; - u8 lutindex = MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f); + u8 lutindex = + static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); float delta = sample_loc * 256 - lutindex; dist_atten = LookupLightingLut(lut, lutindex, delta); } @@ -192,7 +197,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu } auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, - bool abs) -> std::tuple { + bool abs) -> std::tuple { Math::Vec3 norm_view = view.Normalized(); Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); @@ -216,7 +221,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu break; default: - LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input); + LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); UNIMPLEMENTED(); result = 0.f; } @@ -227,14 +232,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu else result = std::max(result, 0.0f); - u8 lutindex = MathUtil::Clamp(std::floor(result * 256.f), 0.0f, 255.0f); + float flr = std::floor(result * 256.f); + u8 lutindex = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); float delta = result * 256 - lutindex; - return { lutindex, delta }; + return {lutindex, delta}; } else { float flr = std::floor(result * 128.f); - s8 tmpi = MathUtil::Clamp(flr, -128.0f, 127.0f); - float delta = result * 128.f - tmpi; - return { tmpi & 0xFF, delta }; + s8 lutindex = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); + float delta = result * 128.f - lutindex; + return {static_cast(lutindex), delta}; } }; @@ -247,11 +253,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu // Lookup specular "distribution 0" LUT value u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d0.Value(), lighting.abs_lut_input.disable_d0 == 0); + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d0.Value(), + lighting.abs_lut_input.disable_d0 == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d0); - d0_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), index, delta); + d0_lut_value = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), + index, delta); } Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); @@ -263,11 +273,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); + std::tie(index, delta) = + GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rr); - refl_value.x = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), index, delta); + refl_value.x = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), + index, delta); } else { refl_value.x = 1.0f; } @@ -279,11 +293,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); + std::tie(index, delta) = + GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rg); - refl_value.y = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), index, delta); + refl_value.y = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), + index, delta); } else { refl_value.y = refl_value.x; } @@ -295,11 +313,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); + std::tie(index, delta) = + GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rb); - refl_value.z = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), index, delta); + refl_value.z = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), + index, delta); } else { refl_value.z = refl_value.x; } @@ -312,54 +334,72 @@ std::tuple, Math::Vec4> ComputeFragmentsColors(const Math::Qu // Lookup specular "distribution 1" LUT value u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d1.Value(), lighting.abs_lut_input.disable_d1 == 0); + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d1.Value(), + lighting.abs_lut_input.disable_d1 == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d1); - d1_lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), index, delta); + d1_lut_value = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), + index, delta); } - Math::Vec3 specular_1 = d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); + Math::Vec3 specular_1 = + d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); if (lighting.config1.disable_lut_fr == 0 && - LightingRegs::IsLightingSamplerSupported( - lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::Fresnel)) { // Lookup fresnel LUT value u8 index; float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.fr.Value(), lighting.abs_lut_input.disable_fr == 0); + std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.fr.Value(), + lighting.abs_lut_input.disable_fr == 0); float scale = lighting.lut_scale.GetScale(lighting.lut_scale.fr); - float lut_value = scale * LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), index, delta); + float lut_value = + scale * + LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), + index, delta); - // Enabled for difffuse lighting alpha component - if (lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || + // Enabled for diffuse lighting alpha component + if (lighting.config0.fresnel_selector == + LightingRegs::LightingFresnelSelector::PrimaryAlpha || lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { diffuse_sum.a() *= lut_value; } // Enabled for the specular lighting alpha component if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::SecondaryAlpha || + LightingRegs::LightingFresnelSelector::SecondaryAlpha || lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { specular_sum.a() *= lut_value; } } - - auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); + auto diffuse = + light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); - specular_sum += Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.f); + specular_sum += + Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.f); } diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); - return { - Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255).Cast(), - Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255).Cast() - }; + + return {Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) + .Cast(), + Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) + .Cast()}; } MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); @@ -554,19 +594,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve }; Math::Quaternion normquat{ - { - GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), - GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), - GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32() - }, + {GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), + GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), + GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()}, GetInterpolatedAttribute(v0.quat.w, v1.quat.w, v2.quat.w).ToFloat32(), }; Math::Vec3 fragment_position{ GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(), - GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32() - }; + GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32()}; Math::Vec2 uv[3]; uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); @@ -685,7 +722,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 primary_fragment_color; Math::Vec4 secondary_fragment_color; - std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors(normquat, fragment_position); + std::tie(primary_fragment_color, secondary_fragment_color) = + ComputeFragmentsColors(normquat, fragment_position); for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) { From 6250f52e939c714ccb302003502ee78941c8221b Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:36:45 -0500 Subject: [PATCH 10/27] SwRasterizer: Fixed a few conversion warnings and moved per-light values into the per-light loop. --- src/video_core/swrasterizer/rasterizer.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 382b5927b..54af53bbd 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -143,18 +143,18 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( // Use the normalized the quaternion when performing the rotation auto normal = Math::QuaternionRotate(normquat.Normalized(), surface_normal); - Math::Vec3 light_vector = {}; Math::Vec4 diffuse_sum = {0.f, 0.f, 0.f, 1.f}; Math::Vec4 specular_sum = {0.f, 0.f, 0.f, 1.f}; - Math::Vec3 refl_value = {}; for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { unsigned num = lighting.light_enable.GetNum(light_index); const auto& light_config = g_state.regs.lighting.light[num]; + Math::Vec3 refl_value = {}; Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), float16::FromRaw(light_config.y).ToFloat32(), float16::FromRaw(light_config.z).ToFloat32()}; + Math::Vec3 light_vector; if (light_config.config.directional) light_vector = position; @@ -175,11 +175,12 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( 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_scale).ToFloat32(); + float dist_aten_bias = + Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32(); size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; - float sample_loc = scale * distance + bias; + float sample_loc = scale * distance + dist_aten_bias; u8 lutindex = static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); @@ -238,7 +239,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( return {lutindex, delta}; } else { float flr = std::floor(result * 128.f); - s8 lutindex = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); + s8 lutindex = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); float delta = result * 128.f - lutindex; return {static_cast(lutindex), delta}; } From 37ac2b6657002e19d78cbc97841f8d3eee6ac5b8 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:53:50 -0500 Subject: [PATCH 11/27] SwRasterizer/Lighting: Fixed a bug where the distance attenuation bias was being set to the dist atten scale. --- src/video_core/swrasterizer/rasterizer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 54af53bbd..48ed8ccbf 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -175,12 +175,11 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (!lighting.IsDistAttenDisabled(num)) { auto distance = (-view - position).Length(); float scale = Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32(); - float dist_aten_bias = - Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32(); + float bias = Pica::float20::FromRaw(light_config.dist_atten_bias).ToFloat32(); size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; - float sample_loc = scale * distance + dist_aten_bias; + float sample_loc = scale * distance + bias; u8 lutindex = static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); From 7bc467e8725c6751eb44ea45ff2203af8692cda1 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:34:16 -0500 Subject: [PATCH 12/27] SwRasterizer/Lighting: Do not use global state in LookupLightingLut. --- src/video_core/pica_state.h | 2 +- src/video_core/swrasterizer/rasterizer.cpp | 33 ++++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h index 2d23d34e6..864a2c9e6 100644 --- a/src/video_core/pica_state.h +++ b/src/video_core/pica_state.h @@ -79,7 +79,7 @@ struct State { std::array color_diff_table; } proctex; - struct { + struct Lighting { union LutEntry { // Used for raw access u32 raw; diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 48ed8ccbf..b69f7b692 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -115,12 +115,15 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v return std::make_tuple(x / z * half + half, y / z * half + half, addr); } -float LookupLightingLut(size_t lut_index, u8 index, float delta) { - ASSERT_MSG(lut_index < g_state.lighting.luts.size(), "Out of range lut"); - ASSERT_MSG(index < g_state.lighting.luts[0].size(), "Out of range index"); +static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut_index, u8 index, + float delta) { + ASSERT_MSG(lut_index < lighting.luts.size(), "Out of range lut"); + ASSERT_MSG(index < lighting.luts[0].size(), "Out of range index"); - float lut_value = g_state.lighting.luts[lut_index][index].ToFloat(); - float lut_diff = g_state.lighting.luts[lut_index][index].DiffToFloat(); + const auto& lut = lighting.luts[lut_index][index]; + + float lut_value = lut.ToFloat(); + float lut_diff = lut.DiffToFloat(); return lut_value + lut_diff * delta; } @@ -184,7 +187,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( u8 lutindex = static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); float delta = sample_loc * 256 - lutindex; - dist_atten = LookupLightingLut(lut, lutindex, delta); + dist_atten = LookupLightingLut(g_state.lighting, lut, lutindex, delta); } float clamp_highlights = 1.0f; @@ -260,7 +263,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( d0_lut_value = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution0), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::Distribution0), index, delta); } @@ -280,7 +284,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.x = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectRed), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::ReflectRed), index, delta); } else { refl_value.x = 1.0f; @@ -300,7 +305,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.y = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectGreen), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::ReflectGreen), index, delta); } else { refl_value.y = refl_value.x; @@ -320,7 +326,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.z = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::ReflectBlue), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::ReflectBlue), index, delta); } else { refl_value.z = refl_value.x; @@ -341,7 +348,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( d1_lut_value = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::Distribution1), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::Distribution1), index, delta); } @@ -362,7 +370,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( float lut_value = scale * - LookupLightingLut(static_cast(LightingRegs::LightingSampler::Fresnel), + LookupLightingLut(g_state.lighting, + static_cast(LightingRegs::LightingSampler::Fresnel), index, delta); // Enabled for diffuse lighting alpha component From b8229a768434ab9b47123359669761c05ecdd6b0 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:35:35 -0500 Subject: [PATCH 13/27] SwRasterizer/Lighting: Do not use global registers state in ComputeFragmentsColors. --- src/video_core/swrasterizer/rasterizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index b69f7b692..d2d77e8b0 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -129,8 +129,8 @@ static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut } std::tuple, Math::Vec4> ComputeFragmentsColors( - const Math::Quaternion& normquat, const Math::Vec3& view) { - const auto& lighting = g_state.regs.lighting; + const Pica::LightingRegs& lighting, const Math::Quaternion& normquat, + const Math::Vec3& view) { if (lighting.disable) return {Math::MakeVec(0, 0, 0, 0), Math::MakeVec(0, 0, 0, 0)}; @@ -732,7 +732,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 secondary_fragment_color; std::tie(primary_fragment_color, secondary_fragment_color) = - ComputeFragmentsColors(normquat, fragment_position); + ComputeFragmentsColors(g_state.regs.lighting, normquat, fragment_position); for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) { From 7526af5e52ac1e24512faa1cd8f1a169407689fb Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:37:14 -0500 Subject: [PATCH 14/27] SwRasterizer/Lighting: Move the lighting enable check outside the ComputeFragmentsColors function. --- src/video_core/swrasterizer/rasterizer.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index d2d77e8b0..b2d2b6ef2 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -132,9 +132,6 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( const Pica::LightingRegs& lighting, const Math::Quaternion& normquat, const Math::Vec3& view) { - if (lighting.disable) - return {Math::MakeVec(0, 0, 0, 0), Math::MakeVec(0, 0, 0, 0)}; - // TODO(Subv): Bump mapping Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; @@ -728,11 +725,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve regs.texturing.tev_combiner_buffer_color.a, }; - Math::Vec4 primary_fragment_color; - Math::Vec4 secondary_fragment_color; + Math::Vec4 primary_fragment_color = {0, 0, 0, 0}; + Math::Vec4 secondary_fragment_color = {0, 0, 0, 0}; - std::tie(primary_fragment_color, secondary_fragment_color) = - ComputeFragmentsColors(g_state.regs.lighting, normquat, fragment_position); + if (!g_state.regs.lighting.disable) { + std::tie(primary_fragment_color, secondary_fragment_color) = + ComputeFragmentsColors(g_state.regs.lighting, normquat, fragment_position); + } for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) { From 9906feefbd37ebfd658fecc47e960f23adc6b190 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:43:00 -0500 Subject: [PATCH 15/27] SwRasterizer/Lighting: Move the clamp highlight calculation to the end of the per-light loop body. --- src/video_core/swrasterizer/rasterizer.cpp | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index b2d2b6ef2..2c7a1a815 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -163,14 +163,6 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( light_vector.Normalize(); - auto LV_N = Math::Dot(light_vector, normal); - auto dot_product = LV_N; - - if (light_config.config.two_sided_diffuse) - dot_product = std::abs(dot_product); - else - dot_product = std::max(dot_product, 0.0f); - float dist_atten = 1.0f; if (!lighting.IsDistAttenDisabled(num)) { auto distance = (-view - position).Length(); @@ -187,15 +179,6 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( dist_atten = LookupLightingLut(g_state.lighting, lut, lutindex, delta); } - float clamp_highlights = 1.0f; - - if (lighting.config0.clamp_highlights) { - if (LV_N <= 0.f) - clamp_highlights = 0.f; - else - clamp_highlights = 1.f; - } - auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, bool abs) -> std::tuple { @@ -386,6 +369,23 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( } } + 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.f) + clamp_highlights = 0.f; + else + clamp_highlights = 1.f; + } + + if (light_config.config.two_sided_diffuse) + dot_product = std::abs(dot_product); + else + dot_product = std::max(dot_product, 0.0f); + auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); From f3660ba9dd13f342c591aaa9901e94b6caee8d9a Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 19:51:29 +0300 Subject: [PATCH 16/27] vector_math: remove broken SFINAE stuff this was originally added to eliminate warnings on MSVC, but it doesn't work for custom types. --- src/common/vector_math.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/common/vector_math.h b/src/common/vector_math.h index d0fe0e405..49ae87f6d 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -31,7 +31,6 @@ #pragma once #include -#include namespace Math { @@ -90,7 +89,7 @@ public: x -= other.x; y -= other.y; } - template ::value>::type> + Vec2 operator-() const { return MakeVec(-x, -y); } @@ -247,7 +246,7 @@ public: y -= other.y; z -= other.z; } - template ::value>::type> + Vec3 operator-() const { return MakeVec(-x, -y, -z); } From efc655aec00d43d53c41b55d9a94d17ce81e5942 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 20:06:26 +0300 Subject: [PATCH 17/27] SwRasterizer/Lighting: pass lighting state as parameter --- src/video_core/swrasterizer/rasterizer.cpp | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 2c7a1a815..b108a0f86 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -116,7 +116,7 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v } static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut_index, u8 index, - float delta) { + float delta) { ASSERT_MSG(lut_index < lighting.luts.size(), "Out of range lut"); ASSERT_MSG(index < lighting.luts[0].size(), "Out of range index"); @@ -129,8 +129,8 @@ static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut } std::tuple, Math::Vec4> ComputeFragmentsColors( - const Pica::LightingRegs& lighting, const Math::Quaternion& normquat, - const Math::Vec3& view) { + const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, + const Math::Quaternion& normquat, const Math::Vec3& view) { // TODO(Subv): Bump mapping Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; @@ -148,7 +148,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { unsigned num = lighting.light_enable.GetNum(light_index); - const auto& light_config = g_state.regs.lighting.light[num]; + const auto& light_config = lighting.light[num]; Math::Vec3 refl_value = {}; Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), @@ -176,7 +176,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( u8 lutindex = static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); float delta = sample_loc * 256 - lutindex; - dist_atten = LookupLightingLut(g_state.lighting, lut, lutindex, delta); + dist_atten = LookupLightingLut(lighting_state, lut, lutindex, delta); } auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, @@ -243,7 +243,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( d0_lut_value = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::Distribution0), index, delta); } @@ -264,7 +264,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.x = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::ReflectRed), index, delta); } else { @@ -285,7 +285,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.y = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::ReflectGreen), index, delta); } else { @@ -306,7 +306,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.z = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::ReflectBlue), index, delta); } else { @@ -328,7 +328,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( d1_lut_value = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::Distribution1), index, delta); } @@ -350,7 +350,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( float lut_value = scale * - LookupLightingLut(g_state.lighting, + LookupLightingLut(lighting_state, static_cast(LightingRegs::LightingSampler::Fresnel), index, delta); @@ -729,8 +729,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 secondary_fragment_color = {0, 0, 0, 0}; if (!g_state.regs.lighting.disable) { - std::tie(primary_fragment_color, secondary_fragment_color) = - ComputeFragmentsColors(g_state.regs.lighting, normquat, fragment_position); + std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors( + g_state.regs.lighting, g_state.lighting, normquat, fragment_position); } for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); From fe44e843fe1e300491d3bcd9072948407a86e7e1 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 20:08:56 +0300 Subject: [PATCH 18/27] vector_math: remove dead template parameter --- src/common/vector_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 49ae87f6d..6e2a5ad60 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -461,7 +461,7 @@ public: z -= other.z; w -= other.w; } - template + Vec4 operator-() const { return MakeVec(-x, -y, -z, -w); } From f13cf506e0b0e42e6c9b00b163aaabc3b63fb7ea Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 20:15:23 +0300 Subject: [PATCH 19/27] SwRasterizer: only interpolate quat and view when lighting is enabled --- src/video_core/swrasterizer/rasterizer.cpp | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index b108a0f86..5844c401c 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -599,18 +599,6 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve 255), }; - Math::Quaternion normquat{ - {GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), - GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), - GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()}, - GetInterpolatedAttribute(v0.quat.w, v1.quat.w, v2.quat.w).ToFloat32(), - }; - - Math::Vec3 fragment_position{ - GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), - GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(), - GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32()}; - Math::Vec2 uv[3]; uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); @@ -729,8 +717,20 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 secondary_fragment_color = {0, 0, 0, 0}; if (!g_state.regs.lighting.disable) { - std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors( - g_state.regs.lighting, g_state.lighting, normquat, fragment_position); + Math::Quaternion normquat{ + {GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), + GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), + GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()}, + GetInterpolatedAttribute(v0.quat.w, v1.quat.w, v2.quat.w).ToFloat32(), + }; + + Math::Vec3 view{ + GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), + GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(), + GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32(), + }; + std::tie(primary_fragment_color, secondary_fragment_color) = + ComputeFragmentsColors(g_state.regs.lighting, g_state.lighting, normquat, view); } for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); From c6d1472513394cc55b5d5a852d5f76b5e9a51f2b Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 21:36:19 +0300 Subject: [PATCH 20/27] SwRasterizer/Lighting: refactor GetLutValue into a function. merging similar pattern. Also makes the code more similar to the gl one --- src/video_core/swrasterizer/rasterizer.cpp | 110 +++++---------------- 1 file changed, 27 insertions(+), 83 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 5844c401c..53c3bb585 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -179,9 +179,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( dist_atten = LookupLightingLut(lighting_state, lut, lutindex, delta); } - auto GetLutIndex = [&](unsigned num, LightingRegs::LightingLutInput input, - bool abs) -> std::tuple { - + auto GetLutValue = [&](LightingRegs::LightingLutInput input, bool abs, + LightingRegs::LightingScale scale_enum, + LightingRegs::LightingSampler sampler) { Math::Vec3 norm_view = view.Normalized(); Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); float result = 0.0f; @@ -209,6 +209,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( result = 0.f; } + u8 index; + float delta; + if (abs) { if (light_config.config.two_sided_diffuse) result = std::abs(result); @@ -216,15 +219,18 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( result = std::max(result, 0.0f); float flr = std::floor(result * 256.f); - u8 lutindex = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); - float delta = result * 256 - lutindex; - return {lutindex, delta}; + index = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); + delta = result * 256 - index; } else { float flr = std::floor(result * 128.f); - s8 lutindex = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); - float delta = result * 128.f - lutindex; - return {static_cast(lutindex), delta}; + s8 signed_index = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); + delta = result * 128.f - signed_index; + index = static_cast(signed_index); } + + float scale = lighting.lut_scale.GetScale(scale_enum); + return scale * + LookupLightingLut(lighting_state, static_cast(sampler), index, delta); }; // Specular 0 component @@ -232,20 +238,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config1.disable_lut_d0 == 0 && LightingRegs::IsLightingSamplerSupported( lighting.config0.config, LightingRegs::LightingSampler::Distribution0)) { - - // Lookup specular "distribution 0" LUT value - u8 index; - float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d0.Value(), - lighting.abs_lut_input.disable_d0 == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d0); - d0_lut_value = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::Distribution0), - index, delta); + GetLutValue(lighting.lut_input.d0, lighting.abs_lut_input.disable_d0 == 0, + lighting.lut_scale.d0, LightingRegs::LightingSampler::Distribution0); } Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); @@ -254,19 +249,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config1.disable_lut_rr == 0 && LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectRed)) { - - u8 index; - float delta; - std::tie(index, delta) = - GetLutIndex(num, lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rr); - refl_value.x = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::ReflectRed), - index, delta); + GetLutValue(lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0, + lighting.lut_scale.rr, LightingRegs::LightingSampler::ReflectRed); } else { refl_value.x = 1.0f; } @@ -275,19 +260,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config1.disable_lut_rg == 0 && LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectGreen)) { - - u8 index; - float delta; - std::tie(index, delta) = - GetLutIndex(num, lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rg); - refl_value.y = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::ReflectGreen), - index, delta); + GetLutValue(lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0, + lighting.lut_scale.rg, LightingRegs::LightingSampler::ReflectGreen); } else { refl_value.y = refl_value.x; } @@ -296,19 +271,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config1.disable_lut_rb == 0 && LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::ReflectBlue)) { - - u8 index; - float delta; - std::tie(index, delta) = - GetLutIndex(num, lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.rb); - refl_value.z = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::ReflectBlue), - index, delta); + GetLutValue(lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0, + lighting.lut_scale.rb, LightingRegs::LightingSampler::ReflectBlue); } else { refl_value.z = refl_value.x; } @@ -317,20 +282,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config1.disable_lut_d1 == 0 && LightingRegs::IsLightingSamplerSupported( lighting.config0.config, LightingRegs::LightingSampler::Distribution1)) { - - // Lookup specular "distribution 1" LUT value - u8 index; - float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.d1.Value(), - lighting.abs_lut_input.disable_d1 == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.d1); - d1_lut_value = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::Distribution1), - index, delta); + GetLutValue(lighting.lut_input.d1, lighting.abs_lut_input.disable_d1 == 0, + lighting.lut_scale.d1, LightingRegs::LightingSampler::Distribution1); } Math::Vec3 specular_1 = @@ -340,19 +294,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { - // Lookup fresnel LUT value - u8 index; - float delta; - std::tie(index, delta) = GetLutIndex(num, lighting.lut_input.fr.Value(), - lighting.abs_lut_input.disable_fr == 0); - - float scale = lighting.lut_scale.GetScale(lighting.lut_scale.fr); - float lut_value = - scale * - LookupLightingLut(lighting_state, - static_cast(LightingRegs::LightingSampler::Fresnel), - index, delta); + GetLutValue(lighting.lut_input.fr, lighting.abs_lut_input.disable_fr == 0, + lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); // Enabled for diffuse lighting alpha component if (lighting.config0.fresnel_selector == From e415558a4fc471bc3ac2d22dd8052aeb63769c6e Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 21:47:55 +0300 Subject: [PATCH 21/27] SwRasterizer/Lighting: get rid of nested return --- src/video_core/swrasterizer/rasterizer.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 53c3bb585..e46790f85 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -340,16 +340,17 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); - return {Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) - .Cast(), - Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) - .Cast()}; + auto diffuse = Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) + .Cast(); + auto specular = Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) + .Cast(); + return {diffuse, specular}; } MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); From 56e5425e593e29aecf255c441791f2e24512f418 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 22:07:19 +0300 Subject: [PATCH 22/27] SwRasterizer/Lighting: unify float suffix --- src/video_core/swrasterizer/rasterizer.cpp | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index e46790f85..c83680629 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -143,8 +143,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( // Use the normalized the quaternion when performing the rotation auto normal = Math::QuaternionRotate(normquat.Normalized(), surface_normal); - Math::Vec4 diffuse_sum = {0.f, 0.f, 0.f, 1.f}; - Math::Vec4 specular_sum = {0.f, 0.f, 0.f, 1.f}; + Math::Vec4 diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; + Math::Vec4 specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { unsigned num = lighting.light_enable.GetNum(light_index); @@ -174,7 +174,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( float sample_loc = scale * distance + bias; u8 lutindex = - static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.f), 0.0f, 255.0f)); + static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.0f), 0.0f, 255.0f)); float delta = sample_loc * 256 - lutindex; dist_atten = LookupLightingLut(lighting_state, lut, lutindex, delta); } @@ -206,7 +206,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( default: LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); UNIMPLEMENTED(); - result = 0.f; + result = 0.0f; } u8 index; @@ -218,13 +218,13 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( else result = std::max(result, 0.0f); - float flr = std::floor(result * 256.f); + float flr = std::floor(result * 256.0f); index = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); delta = result * 256 - index; } else { - float flr = std::floor(result * 128.f); + float flr = std::floor(result * 128.0f); s8 signed_index = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); - delta = result * 128.f - signed_index; + delta = result * 128.0f - signed_index; index = static_cast(signed_index); } @@ -278,6 +278,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( refl_value.z = refl_value.x; } + // Specular 1 component float d1_lut_value = 1.0f; if (lighting.config1.disable_lut_d1 == 0 && LightingRegs::IsLightingSamplerSupported( @@ -290,6 +291,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( Math::Vec3 specular_1 = d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); + // Fresnel if (lighting.config1.disable_lut_fr == 0 && LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { @@ -319,10 +321,10 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( // product. float clamp_highlights = 1.0f; if (lighting.config0.clamp_highlights) { - if (dot_product <= 0.f) - clamp_highlights = 0.f; + if (dot_product <= 0.0f) + clamp_highlights = 0.0f; else - clamp_highlights = 1.f; + clamp_highlights = 1.0f; } if (light_config.config.two_sided_diffuse) @@ -335,7 +337,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); specular_sum += - Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.f); + Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.0f); } diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); From 4feff63ffaec4d62d5bdfc85968cc99298907767 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 22:19:00 +0300 Subject: [PATCH 23/27] SwRasterizer/Lighting: dist atten lut input need to be clamp --- src/video_core/swrasterizer/rasterizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index c83680629..37d1313cf 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -171,7 +171,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( size_t lut = static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; - float sample_loc = scale * distance + bias; + float sample_loc = MathUtil::Clamp(scale * distance + bias, 0.0f, 1.0f); u8 lutindex = static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.0f), 0.0f, 255.0f)); From c59ed47608367de8cd5e4e6d58da02dee30810a9 Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:05:53 +0300 Subject: [PATCH 24/27] SwRasterizer/Lighting: move quaternion normalization to the caller --- src/video_core/swrasterizer/rasterizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 37d1313cf..80ecf72ec 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -141,7 +141,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( } // Use the normalized the quaternion when performing the rotation - auto normal = Math::QuaternionRotate(normquat.Normalized(), surface_normal); + auto normal = Math::QuaternionRotate(normquat, surface_normal); Math::Vec4 diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; Math::Vec4 specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; @@ -664,12 +664,12 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 secondary_fragment_color = {0, 0, 0, 0}; if (!g_state.regs.lighting.disable) { - Math::Quaternion normquat{ + Math::Quaternion normquat = Math::Quaternion{ {GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()}, GetInterpolatedAttribute(v0.quat.w, v1.quat.w, v2.quat.w).ToFloat32(), - }; + }.Normalized(); Math::Vec3 view{ GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), From 48b410587116c92339d936ed3b1fd00aba38d6b5 Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:07:15 +0300 Subject: [PATCH 25/27] SwRasterizer/Lighting: reduce confusion --- src/video_core/swrasterizer/rasterizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 80ecf72ec..aee630954 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -118,7 +118,7 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut_index, u8 index, float delta) { ASSERT_MSG(lut_index < lighting.luts.size(), "Out of range lut"); - ASSERT_MSG(index < lighting.luts[0].size(), "Out of range index"); + ASSERT_MSG(index < lighting.luts[lut_index].size(), "Out of range index"); const auto& lut = lighting.luts[lut_index][index]; From eda28266fb1f0eb96a2096cadb41b62db3dc2d2e Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:20:40 +0300 Subject: [PATCH 26/27] SwRasterizer/Lighting: move to its own file --- src/video_core/CMakeLists.txt | 2 + .../swrasterizer/fragment_lighting.cpp | 250 ++++++++++++++++++ .../swrasterizer/fragment_lighting.h | 18 ++ src/video_core/swrasterizer/rasterizer.cpp | 241 +---------------- 4 files changed, 271 insertions(+), 240 deletions(-) create mode 100644 src/video_core/swrasterizer/fragment_lighting.cpp create mode 100644 src/video_core/swrasterizer/fragment_lighting.h diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 0961a3251..b2280f2ef 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -14,6 +14,7 @@ set(SRCS shader/shader.cpp shader/shader_interpreter.cpp swrasterizer/clipper.cpp + swrasterizer/fragment_lighting.cpp swrasterizer/framebuffer.cpp swrasterizer/proctex.cpp swrasterizer/rasterizer.cpp @@ -54,6 +55,7 @@ set(HEADERS shader/shader.h shader/shader_interpreter.h swrasterizer/clipper.h + swrasterizer/fragment_lighting.h swrasterizer/framebuffer.h swrasterizer/proctex.h swrasterizer/rasterizer.h diff --git a/src/video_core/swrasterizer/fragment_lighting.cpp b/src/video_core/swrasterizer/fragment_lighting.cpp new file mode 100644 index 000000000..45a86b5cd --- /dev/null +++ b/src/video_core/swrasterizer/fragment_lighting.cpp @@ -0,0 +1,250 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/math_util.h" +#include "video_core/swrasterizer/fragment_lighting.h" + +namespace Pica { + +static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut_index, u8 index, + float delta) { + ASSERT_MSG(lut_index < lighting.luts.size(), "Out of range lut"); + ASSERT_MSG(index < lighting.luts[lut_index].size(), "Out of range index"); + + const auto& lut = lighting.luts[lut_index][index]; + + float lut_value = lut.ToFloat(); + float lut_diff = lut.DiffToFloat(); + + return lut_value + lut_diff * delta; +} + +std::tuple, Math::Vec4> ComputeFragmentsColors( + const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, + const Math::Quaternion& normquat, const Math::Vec3& view) { + + // TODO(Subv): Bump mapping + Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; + + if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) { + LOG_CRITICAL(HW_GPU, "unimplemented bump mapping"); + UNIMPLEMENTED(); + } + + // Use the normalized the quaternion when performing the rotation + auto normal = Math::QuaternionRotate(normquat, surface_normal); + + Math::Vec4 diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; + Math::Vec4 specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; + + for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { + unsigned num = lighting.light_enable.GetNum(light_index); + const auto& light_config = lighting.light[num]; + + Math::Vec3 refl_value = {}; + Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), + float16::FromRaw(light_config.y).ToFloat32(), + float16::FromRaw(light_config.z).ToFloat32()}; + Math::Vec3 light_vector; + + if (light_config.config.directional) + light_vector = position; + else + light_vector = position + view; + + light_vector.Normalize(); + + 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(); + size_t lut = + static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; + + float sample_loc = MathUtil::Clamp(scale * distance + bias, 0.0f, 1.0f); + + u8 lutindex = + static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.0f), 0.0f, 255.0f)); + float delta = sample_loc * 256 - lutindex; + dist_atten = LookupLightingLut(lighting_state, lut, lutindex, delta); + } + + auto GetLutValue = [&](LightingRegs::LightingLutInput input, bool abs, + LightingRegs::LightingScale scale_enum, + LightingRegs::LightingSampler sampler) { + Math::Vec3 norm_view = view.Normalized(); + Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); + float result = 0.0f; + + switch (input) { + case LightingRegs::LightingLutInput::NH: + result = Math::Dot(normal, half_angle); + break; + + case LightingRegs::LightingLutInput::VH: + result = Math::Dot(norm_view, half_angle); + break; + + case LightingRegs::LightingLutInput::NV: + result = Math::Dot(normal, norm_view); + break; + + case LightingRegs::LightingLutInput::LN: + result = Math::Dot(light_vector, normal); + break; + + default: + LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); + UNIMPLEMENTED(); + result = 0.0f; + } + + u8 index; + float delta; + + if (abs) { + if (light_config.config.two_sided_diffuse) + result = std::abs(result); + else + result = std::max(result, 0.0f); + + float flr = std::floor(result * 256.0f); + index = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); + delta = result * 256 - index; + } else { + float flr = std::floor(result * 128.0f); + s8 signed_index = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); + delta = result * 128.0f - signed_index; + index = static_cast(signed_index); + } + + float scale = lighting.lut_scale.GetScale(scale_enum); + return scale * + LookupLightingLut(lighting_state, static_cast(sampler), index, delta); + }; + + // Specular 0 component + float d0_lut_value = 1.0f; + if (lighting.config1.disable_lut_d0 == 0 && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::Distribution0)) { + d0_lut_value = + GetLutValue(lighting.lut_input.d0, lighting.abs_lut_input.disable_d0 == 0, + lighting.lut_scale.d0, LightingRegs::LightingSampler::Distribution0); + } + + Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); + + // If enabled, lookup ReflectRed value, otherwise, 1.0 is used + if (lighting.config1.disable_lut_rr == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectRed)) { + refl_value.x = + GetLutValue(lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0, + lighting.lut_scale.rr, LightingRegs::LightingSampler::ReflectRed); + } else { + refl_value.x = 1.0f; + } + + // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used + if (lighting.config1.disable_lut_rg == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectGreen)) { + refl_value.y = + GetLutValue(lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0, + lighting.lut_scale.rg, LightingRegs::LightingSampler::ReflectGreen); + } else { + refl_value.y = refl_value.x; + } + + // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used + if (lighting.config1.disable_lut_rb == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::ReflectBlue)) { + refl_value.z = + GetLutValue(lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0, + lighting.lut_scale.rb, LightingRegs::LightingSampler::ReflectBlue); + } else { + refl_value.z = refl_value.x; + } + + // Specular 1 component + float d1_lut_value = 1.0f; + if (lighting.config1.disable_lut_d1 == 0 && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::Distribution1)) { + d1_lut_value = + GetLutValue(lighting.lut_input.d1, lighting.abs_lut_input.disable_d1 == 0, + lighting.lut_scale.d1, LightingRegs::LightingSampler::Distribution1); + } + + Math::Vec3 specular_1 = + d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); + + // Fresnel + if (lighting.config1.disable_lut_fr == 0 && + LightingRegs::IsLightingSamplerSupported(lighting.config0.config, + LightingRegs::LightingSampler::Fresnel)) { + + float lut_value = + GetLutValue(lighting.lut_input.fr, lighting.abs_lut_input.disable_fr == 0, + lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); + + // Enabled for diffuse lighting alpha component + if (lighting.config0.fresnel_selector == + LightingRegs::LightingFresnelSelector::PrimaryAlpha || + lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + diffuse_sum.a() *= lut_value; + } + + // Enabled for the specular lighting alpha component + if (lighting.config0.fresnel_selector == + LightingRegs::LightingFresnelSelector::SecondaryAlpha || + lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { + specular_sum.a() *= lut_value; + } + } + + 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) + dot_product = std::abs(dot_product); + else + dot_product = std::max(dot_product, 0.0f); + + auto diffuse = + light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); + diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); + + specular_sum += + Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.0f); + } + + diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); + + auto diffuse = Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) + .Cast(); + auto specular = Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, + MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) + .Cast(); + return {diffuse, specular}; +} + +} // namespace Pica diff --git a/src/video_core/swrasterizer/fragment_lighting.h b/src/video_core/swrasterizer/fragment_lighting.h new file mode 100644 index 000000000..438dca926 --- /dev/null +++ b/src/video_core/swrasterizer/fragment_lighting.h @@ -0,0 +1,18 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/quaternion.h" +#include "common/vector_math.h" +#include "video_core/pica_state.h" + +namespace Pica { + +std::tuple, Math::Vec4> ComputeFragmentsColors( + const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, + const Math::Quaternion& normquat, const Math::Vec3& view); + +} // namespace Pica diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index aee630954..bc7e1c56c 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -24,6 +24,7 @@ #include "video_core/regs_rasterizer.h" #include "video_core/regs_texturing.h" #include "video_core/shader/shader.h" +#include "video_core/swrasterizer/fragment_lighting.h" #include "video_core/swrasterizer/framebuffer.h" #include "video_core/swrasterizer/proctex.h" #include "video_core/swrasterizer/rasterizer.h" @@ -115,246 +116,6 @@ static std::tuple ConvertCubeCoord(float24 u, float24 v return std::make_tuple(x / z * half + half, y / z * half + half, addr); } -static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut_index, u8 index, - float delta) { - ASSERT_MSG(lut_index < lighting.luts.size(), "Out of range lut"); - ASSERT_MSG(index < lighting.luts[lut_index].size(), "Out of range index"); - - const auto& lut = lighting.luts[lut_index][index]; - - float lut_value = lut.ToFloat(); - float lut_diff = lut.DiffToFloat(); - - return lut_value + lut_diff * delta; -} - -std::tuple, Math::Vec4> ComputeFragmentsColors( - const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, - const Math::Quaternion& normquat, const Math::Vec3& view) { - - // TODO(Subv): Bump mapping - Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; - - if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) { - LOG_CRITICAL(HW_GPU, "unimplemented bump mapping"); - UNIMPLEMENTED(); - } - - // Use the normalized the quaternion when performing the rotation - auto normal = Math::QuaternionRotate(normquat, surface_normal); - - Math::Vec4 diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; - Math::Vec4 specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; - - for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { - unsigned num = lighting.light_enable.GetNum(light_index); - const auto& light_config = lighting.light[num]; - - Math::Vec3 refl_value = {}; - Math::Vec3 position = {float16::FromRaw(light_config.x).ToFloat32(), - float16::FromRaw(light_config.y).ToFloat32(), - float16::FromRaw(light_config.z).ToFloat32()}; - Math::Vec3 light_vector; - - if (light_config.config.directional) - light_vector = position; - else - light_vector = position + view; - - light_vector.Normalize(); - - 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(); - size_t lut = - static_cast(LightingRegs::LightingSampler::DistanceAttenuation) + num; - - float sample_loc = MathUtil::Clamp(scale * distance + bias, 0.0f, 1.0f); - - u8 lutindex = - static_cast(MathUtil::Clamp(std::floor(sample_loc * 256.0f), 0.0f, 255.0f)); - float delta = sample_loc * 256 - lutindex; - dist_atten = LookupLightingLut(lighting_state, lut, lutindex, delta); - } - - auto GetLutValue = [&](LightingRegs::LightingLutInput input, bool abs, - LightingRegs::LightingScale scale_enum, - LightingRegs::LightingSampler sampler) { - Math::Vec3 norm_view = view.Normalized(); - Math::Vec3 half_angle = (norm_view + light_vector).Normalized(); - float result = 0.0f; - - switch (input) { - case LightingRegs::LightingLutInput::NH: - result = Math::Dot(normal, half_angle); - break; - - case LightingRegs::LightingLutInput::VH: - result = Math::Dot(norm_view, half_angle); - break; - - case LightingRegs::LightingLutInput::NV: - result = Math::Dot(normal, norm_view); - break; - - case LightingRegs::LightingLutInput::LN: - result = Math::Dot(light_vector, normal); - break; - - default: - LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); - UNIMPLEMENTED(); - result = 0.0f; - } - - u8 index; - float delta; - - if (abs) { - if (light_config.config.two_sided_diffuse) - result = std::abs(result); - else - result = std::max(result, 0.0f); - - float flr = std::floor(result * 256.0f); - index = static_cast(MathUtil::Clamp(flr, 0.0f, 255.0f)); - delta = result * 256 - index; - } else { - float flr = std::floor(result * 128.0f); - s8 signed_index = static_cast(MathUtil::Clamp(flr, -128.0f, 127.0f)); - delta = result * 128.0f - signed_index; - index = static_cast(signed_index); - } - - float scale = lighting.lut_scale.GetScale(scale_enum); - return scale * - LookupLightingLut(lighting_state, static_cast(sampler), index, delta); - }; - - // Specular 0 component - float d0_lut_value = 1.0f; - if (lighting.config1.disable_lut_d0 == 0 && - LightingRegs::IsLightingSamplerSupported( - lighting.config0.config, LightingRegs::LightingSampler::Distribution0)) { - d0_lut_value = - GetLutValue(lighting.lut_input.d0, lighting.abs_lut_input.disable_d0 == 0, - lighting.lut_scale.d0, LightingRegs::LightingSampler::Distribution0); - } - - Math::Vec3 specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); - - // If enabled, lookup ReflectRed value, otherwise, 1.0 is used - if (lighting.config1.disable_lut_rr == 0 && - LightingRegs::IsLightingSamplerSupported(lighting.config0.config, - LightingRegs::LightingSampler::ReflectRed)) { - refl_value.x = - GetLutValue(lighting.lut_input.rr, lighting.abs_lut_input.disable_rr == 0, - lighting.lut_scale.rr, LightingRegs::LightingSampler::ReflectRed); - } else { - refl_value.x = 1.0f; - } - - // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used - if (lighting.config1.disable_lut_rg == 0 && - LightingRegs::IsLightingSamplerSupported(lighting.config0.config, - LightingRegs::LightingSampler::ReflectGreen)) { - refl_value.y = - GetLutValue(lighting.lut_input.rg, lighting.abs_lut_input.disable_rg == 0, - lighting.lut_scale.rg, LightingRegs::LightingSampler::ReflectGreen); - } else { - refl_value.y = refl_value.x; - } - - // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used - if (lighting.config1.disable_lut_rb == 0 && - LightingRegs::IsLightingSamplerSupported(lighting.config0.config, - LightingRegs::LightingSampler::ReflectBlue)) { - refl_value.z = - GetLutValue(lighting.lut_input.rb, lighting.abs_lut_input.disable_rb == 0, - lighting.lut_scale.rb, LightingRegs::LightingSampler::ReflectBlue); - } else { - refl_value.z = refl_value.x; - } - - // Specular 1 component - float d1_lut_value = 1.0f; - if (lighting.config1.disable_lut_d1 == 0 && - LightingRegs::IsLightingSamplerSupported( - lighting.config0.config, LightingRegs::LightingSampler::Distribution1)) { - d1_lut_value = - GetLutValue(lighting.lut_input.d1, lighting.abs_lut_input.disable_d1 == 0, - lighting.lut_scale.d1, LightingRegs::LightingSampler::Distribution1); - } - - Math::Vec3 specular_1 = - d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); - - // Fresnel - if (lighting.config1.disable_lut_fr == 0 && - LightingRegs::IsLightingSamplerSupported(lighting.config0.config, - LightingRegs::LightingSampler::Fresnel)) { - - float lut_value = - GetLutValue(lighting.lut_input.fr, lighting.abs_lut_input.disable_fr == 0, - lighting.lut_scale.fr, LightingRegs::LightingSampler::Fresnel); - - // Enabled for diffuse lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::PrimaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { - diffuse_sum.a() *= lut_value; - } - - // Enabled for the specular lighting alpha component - if (lighting.config0.fresnel_selector == - LightingRegs::LightingFresnelSelector::SecondaryAlpha || - lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { - specular_sum.a() *= lut_value; - } - } - - 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) - dot_product = std::abs(dot_product); - else - dot_product = std::max(dot_product, 0.0f); - - auto diffuse = - light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); - diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); - - specular_sum += - Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.0f); - } - - diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); - - auto diffuse = Math::MakeVec(MathUtil::Clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, - MathUtil::Clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) - .Cast(); - auto specular = Math::MakeVec(MathUtil::Clamp(specular_sum.x, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.y, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, - MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) - .Cast(); - return {diffuse, specular}; -} - MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); /** From 2252a63f8036cdf2612243271ce29e6104f82825 Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 3 Aug 2017 12:01:31 +0300 Subject: [PATCH 27/27] SwRasterizer/Lighting: shorten file name --- src/video_core/CMakeLists.txt | 4 ++-- .../swrasterizer/{fragment_lighting.cpp => lighting.cpp} | 2 +- .../swrasterizer/{fragment_lighting.h => lighting.h} | 0 src/video_core/swrasterizer/rasterizer.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/video_core/swrasterizer/{fragment_lighting.cpp => lighting.cpp} (99%) rename src/video_core/swrasterizer/{fragment_lighting.h => lighting.h} (100%) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index b2280f2ef..cffa4c952 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -14,8 +14,8 @@ set(SRCS shader/shader.cpp shader/shader_interpreter.cpp swrasterizer/clipper.cpp - swrasterizer/fragment_lighting.cpp swrasterizer/framebuffer.cpp + swrasterizer/lighting.cpp swrasterizer/proctex.cpp swrasterizer/rasterizer.cpp swrasterizer/swrasterizer.cpp @@ -55,8 +55,8 @@ set(HEADERS shader/shader.h shader/shader_interpreter.h swrasterizer/clipper.h - swrasterizer/fragment_lighting.h swrasterizer/framebuffer.h + swrasterizer/lighting.h swrasterizer/proctex.h swrasterizer/rasterizer.h swrasterizer/swrasterizer.h diff --git a/src/video_core/swrasterizer/fragment_lighting.cpp b/src/video_core/swrasterizer/lighting.cpp similarity index 99% rename from src/video_core/swrasterizer/fragment_lighting.cpp rename to src/video_core/swrasterizer/lighting.cpp index 45a86b5cd..63088eee8 100644 --- a/src/video_core/swrasterizer/fragment_lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include "common/math_util.h" -#include "video_core/swrasterizer/fragment_lighting.h" +#include "video_core/swrasterizer/lighting.h" namespace Pica { diff --git a/src/video_core/swrasterizer/fragment_lighting.h b/src/video_core/swrasterizer/lighting.h similarity index 100% rename from src/video_core/swrasterizer/fragment_lighting.h rename to src/video_core/swrasterizer/lighting.h diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index bc7e1c56c..fdc1df199 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -24,8 +24,8 @@ #include "video_core/regs_rasterizer.h" #include "video_core/regs_texturing.h" #include "video_core/shader/shader.h" -#include "video_core/swrasterizer/fragment_lighting.h" #include "video_core/swrasterizer/framebuffer.h" +#include "video_core/swrasterizer/lighting.h" #include "video_core/swrasterizer/proctex.h" #include "video_core/swrasterizer/rasterizer.h" #include "video_core/swrasterizer/texturing.h"