From b2f472a2b1f36073b0070b81c08a666380ad180d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 13:14:55 -0500 Subject: SwRasterizer: Implement primary fragment color. --- src/video_core/swrasterizer/rasterizer.cpp | 117 ++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 4 deletions(-) (limited to 'src/video_core/swrasterizer') 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: + return primary_color; - // HACK: Until we implement fragment lighting, use primary_color case Source::PrimaryFragmentColor: - return primary_color; + return primary_fragment_color; - // HACK: Until we implement fragment lighting, use zero case Source::SecondaryFragmentColor: - return {0, 0, 0, 0}; + return secondary_fragment_color; case Source::Texture0: return texture_color[0]; -- cgit v1.2.3 From be25e78b07140cb745387f757001dd04b3b4cc64 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:25:41 -0500 Subject: SwRasterizer: Calculate specular_0 for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 107 +++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 13 deletions(-) (limited to 'src/video_core/swrasterizer') 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)); + 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; - float index_f = sample_loc - index_i; + case LightingRegs::LightingLutInput::VH: + result = Math::Dot(norm_view, half_angle); + break; - ASSERT_MSG(lut < g_state.lighting.luts.size(), "Out of range lut"); + case LightingRegs::LightingLutInput::NV: + result = Math::Dot(normal, norm_view); + break; - float lut_value = g_state.lighting.luts[lut][index_i].ToFloat(); - float lut_diff = g_state.lighting.luts[lut][index_i].DiffToFloat(); + case LightingRegs::LightingLutInput::LN: + result = Math::Dot(light_vector, normal); + break; - dist_atten = lut_value + lut_diff * index_f; + 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() }; } -- cgit v1.2.3 From 46b8c8e1da6bc29df2662d63b0e028136fef3636 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:44:02 -0500 Subject: SwRasterizer: Calculate specular_1 for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 62 ++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) (limited to 'src/video_core/swrasterizer') 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); -- cgit v1.2.3 From 10b0bea06008fea89564dc5ef8895c0274f8ef18 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 14:55:54 -0500 Subject: SwRasterizer: Calculate fresnel for fragment lighting. --- src/video_core/swrasterizer/rasterizer.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'src/video_core/swrasterizer') 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); -- cgit v1.2.3 From 80b6fc592e3a2f5821975e84b5df35f5dc4ae51a Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 15:24:28 -0500 Subject: SwRasterizer: Fixed the lighting lut lookup function. --- src/video_core/swrasterizer/rasterizer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/video_core/swrasterizer') 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) { -- cgit v1.2.3 From f2d4d5c2191275bd91f2f42b880f3edf3bccfd63 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 17:33:25 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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); - } else { - if (result < 0.f) - result += 2.f; - result /= 2.f; + u8 lutindex = MathUtil::Clamp(floorf(result * 256.f), 0.0f, 255.0f); + float delta = result * 256 - lutindex; + return { lutindex, delta / 256.f }; + } else { + 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 || -- cgit v1.2.3 From 2a75837bc30ba08e2470f4b91078747a08c5213a Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 9 Jun 2017 18:18:57 -0500 Subject: SwRasterizer: Corrected the light LUT lookups. --- src/video_core/swrasterizer/rasterizer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/video_core/swrasterizer') 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 }; } }; -- cgit v1.2.3 From 73566ff7a990cdfe8d8f023997b57942dc785fc4 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 11 Jun 2017 11:55:35 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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{ -- cgit v1.2.3 From 2d69a9b8bf232fdd9e3bbb2a9c624ee9dd6ec637 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:31:28 -0500 Subject: SwRasterizer: Run clang-format --- src/video_core/swrasterizer/rasterizer.cpp | 128 +++++++++++++++++++---------- 1 file changed, 83 insertions(+), 45 deletions(-) (limited to 'src/video_core/swrasterizer') 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) { -- cgit v1.2.3 From 6250f52e939c714ccb302003502ee78941c8221b Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:36:45 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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}; } -- cgit v1.2.3 From 37ac2b6657002e19d78cbc97841f8d3eee6ac5b8 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 13 Jun 2017 12:53:50 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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)); -- cgit v1.2.3 From 7bc467e8725c6751eb44ea45ff2203af8692cda1 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:34:16 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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 -- cgit v1.2.3 From b8229a768434ab9b47123359669761c05ecdd6b0 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:35:35 -0500 Subject: SwRasterizer/Lighting: Do not use global registers state in ComputeFragmentsColors. --- src/video_core/swrasterizer/rasterizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/video_core/swrasterizer') 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) { -- cgit v1.2.3 From 7526af5e52ac1e24512faa1cd8f1a169407689fb Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:37:14 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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) { -- cgit v1.2.3 From 9906feefbd37ebfd658fecc47e960f23adc6b190 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Jun 2017 12:43:00 -0500 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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); -- cgit v1.2.3 From efc655aec00d43d53c41b55d9a94d17ce81e5942 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 20:06:26 +0300 Subject: SwRasterizer/Lighting: pass lighting state as parameter --- src/video_core/swrasterizer/rasterizer.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/video_core/swrasterizer') 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(); -- cgit v1.2.3 From f13cf506e0b0e42e6c9b00b163aaabc3b63fb7ea Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 20:15:23 +0300 Subject: SwRasterizer: only interpolate quat and view when lighting is enabled --- src/video_core/swrasterizer/rasterizer.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/video_core/swrasterizer') 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(); -- cgit v1.2.3 From c6d1472513394cc55b5d5a852d5f76b5e9a51f2b Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 21:36:19 +0300 Subject: 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(-) (limited to 'src/video_core/swrasterizer') 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 == -- cgit v1.2.3 From e415558a4fc471bc3ac2d22dd8052aeb63769c6e Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 21:47:55 +0300 Subject: SwRasterizer/Lighting: get rid of nested return --- src/video_core/swrasterizer/rasterizer.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/video_core/swrasterizer') 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)); -- cgit v1.2.3 From 56e5425e593e29aecf255c441791f2e24512f418 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 22:07:19 +0300 Subject: SwRasterizer/Lighting: unify float suffix --- src/video_core/swrasterizer/rasterizer.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/video_core/swrasterizer') 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); -- cgit v1.2.3 From 4feff63ffaec4d62d5bdfc85968cc99298907767 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 11 Jul 2017 22:19:00 +0300 Subject: SwRasterizer/Lighting: dist atten lut input need to be clamp --- src/video_core/swrasterizer/rasterizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/swrasterizer') 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)); -- cgit v1.2.3 From c59ed47608367de8cd5e4e6d58da02dee30810a9 Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:05:53 +0300 Subject: SwRasterizer/Lighting: move quaternion normalization to the caller --- src/video_core/swrasterizer/rasterizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/video_core/swrasterizer') 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(), -- cgit v1.2.3 From 48b410587116c92339d936ed3b1fd00aba38d6b5 Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:07:15 +0300 Subject: SwRasterizer/Lighting: reduce confusion --- src/video_core/swrasterizer/rasterizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/swrasterizer') 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]; -- cgit v1.2.3 From eda28266fb1f0eb96a2096cadb41b62db3dc2d2e Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 2 Aug 2017 22:20:40 +0300 Subject: SwRasterizer/Lighting: move to its own file --- src/video_core/CMakeLists.txt | 2 + src/video_core/swrasterizer/fragment_lighting.cpp | 250 ++++++++++++++++++++++ src/video_core/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 (limited to 'src/video_core/swrasterizer') 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)); /** -- cgit v1.2.3 From 2252a63f8036cdf2612243271ce29e6104f82825 Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 3 Aug 2017 12:01:31 +0300 Subject: SwRasterizer/Lighting: shorten file name --- src/video_core/CMakeLists.txt | 4 +- src/video_core/swrasterizer/fragment_lighting.cpp | 250 ---------------------- src/video_core/swrasterizer/fragment_lighting.h | 18 -- src/video_core/swrasterizer/lighting.cpp | 250 ++++++++++++++++++++++ src/video_core/swrasterizer/lighting.h | 18 ++ src/video_core/swrasterizer/rasterizer.cpp | 2 +- 6 files changed, 271 insertions(+), 271 deletions(-) delete mode 100644 src/video_core/swrasterizer/fragment_lighting.cpp delete mode 100644 src/video_core/swrasterizer/fragment_lighting.h create mode 100644 src/video_core/swrasterizer/lighting.cpp create mode 100644 src/video_core/swrasterizer/lighting.h (limited to 'src/video_core/swrasterizer') 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/fragment_lighting.cpp deleted file mode 100644 index 45a86b5cd..000000000 --- a/src/video_core/swrasterizer/fragment_lighting.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// 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 deleted file mode 100644 index 438dca926..000000000 --- a/src/video_core/swrasterizer/fragment_lighting.h +++ /dev/null @@ -1,18 +0,0 @@ -// 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/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp new file mode 100644 index 000000000..63088eee8 --- /dev/null +++ b/src/video_core/swrasterizer/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/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/lighting.h b/src/video_core/swrasterizer/lighting.h new file mode 100644 index 000000000..438dca926 --- /dev/null +++ b/src/video_core/swrasterizer/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 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" -- cgit v1.2.3 From 5d9d42f0d0e0b2619e7412b86699a9b2b9dfa4ea Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 10 Aug 2017 11:56:55 +0300 Subject: SwRasterizer/Lighting: use make_tuple instead of constructor implicit tuple constructor is a c++17 thing, which is not supported by some not-so-old libraries. Play safe for now --- src/video_core/swrasterizer/lighting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index 63088eee8..d61e6d572 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -244,7 +244,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( MathUtil::Clamp(specular_sum.z, 0.0f, 1.0f) * 255, MathUtil::Clamp(specular_sum.w, 0.0f, 1.0f) * 255) .Cast(); - return {diffuse, specular}; + return std::make_tuple(diffuse, specular); } } // namespace Pica -- cgit v1.2.3 From 14ee32c46a6dc97c1c6a0597e72e5284bf4e86e6 Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 11 Aug 2017 01:13:55 +0300 Subject: SwRasterizer/Lighting: implement geometric factor --- src/video_core/swrasterizer/lighting.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index d61e6d572..91683afa4 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -55,6 +55,9 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( light_vector.Normalize(); + Math::Vec3 norm_view = view.Normalized(); + Math::Vec3 half_vector = norm_view + light_vector; + float dist_atten = 1.0f; if (!lighting.IsDistAttenDisabled(num)) { auto distance = (-view - position).Length(); @@ -74,17 +77,15 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( 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); + result = Math::Dot(normal, half_vector.Normalized()); break; case LightingRegs::LightingLutInput::VH: - result = Math::Dot(norm_view, half_angle); + result = Math::Dot(norm_view, half_vector.Normalized()); break; case LightingRegs::LightingLutInput::NV: @@ -224,6 +225,17 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( else dot_product = std::max(dot_product, 0.0f); + if (light_config.config.geometric_factor_0 || light_config.config.geometric_factor_1) { + float geo_factor = half_vector.Length2(); + geo_factor = geo_factor == 0.0f ? 0.0f : std::min(dot_product / geo_factor, 1.0f); + if (light_config.config.geometric_factor_0) { + specular_0 *= geo_factor; + } + if (light_config.config.geometric_factor_1) { + specular_1 *= geo_factor; + } + } + auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); -- cgit v1.2.3 From 945f9a1b04d51aff674e0b7061c29a04211a17bd Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 11 Aug 2017 00:41:37 +0300 Subject: SwRasterizer/Lighting: implement spot light --- src/video_core/swrasterizer/lighting.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index d61e6d572..ffd35792a 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -95,6 +95,12 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( result = Math::Dot(light_vector, normal); break; + case LightingRegs::LightingLutInput::SP: { + Math::Vec3 spot_dir{light_config.spot_x.Value(), light_config.spot_y.Value(), + light_config.spot_z.Value()}; + result = Math::Dot(light_vector, spot_dir.Cast() / 2047.0f); + break; + } default: LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); UNIMPLEMENTED(); @@ -125,6 +131,16 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( LookupLightingLut(lighting_state, static_cast(sampler), index, delta); }; + // If enabled, compute spot light attenuation value + float spot_atten = 1.0f; + if (!lighting.IsSpotAttenDisabled(num) && + LightingRegs::IsLightingSamplerSupported( + lighting.config0.config, LightingRegs::LightingSampler::SpotlightAttenuation)) { + auto lut = LightingRegs::SpotlightAttenuationSampler(num); + spot_atten = GetLutValue(lighting.lut_input.sp, lighting.abs_lut_input.disable_sp == 0, + lighting.lut_scale.sp, lut); + } + // Specular 0 component float d0_lut_value = 1.0f; if (lighting.config1.disable_lut_d0 == 0 && @@ -226,10 +242,10 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f(); - diffuse_sum += Math::MakeVec(diffuse * dist_atten, 0.0f); + diffuse_sum += Math::MakeVec(diffuse * dist_atten * spot_atten, 0.0f); - specular_sum += - Math::MakeVec((specular_0 + specular_1) * clamp_highlights * dist_atten, 0.0f); + specular_sum += Math::MakeVec( + (specular_0 + specular_1) * clamp_highlights * dist_atten * spot_atten, 0.0f); } diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); -- cgit v1.2.3 From 72b26ac32f74457d017e4eb96d83e2a66e713a5a Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 17 Aug 2017 10:57:31 +0300 Subject: swrasterizer/clipper: remove tested TODO hwtested. Current implementation is the correct behavior --- src/video_core/swrasterizer/clipper.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index 7537689b7..cdbc71502 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -125,10 +125,6 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu {Math::MakeVec(f0, f0, f0, -f1), Math::Vec4(f0, f0, f0, EPSILON)}, // w = EPSILON }}; - // TODO: If one vertex lies outside one of the depth clipping planes, some platforms (e.g. Wii) - // drop the whole primitive instead of clipping the primitive properly. We should test if - // this happens on the 3DS, too. - // Simple implementation of the Sutherland-Hodgman clipping algorithm. // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here) for (auto edge : clipping_edges) { -- cgit v1.2.3 From 63b6e802cdffc1464b4a1fe3f5171d71146e8e9a Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 17 Aug 2017 11:02:19 +0300 Subject: swrasterizer: remove invalid TODO This function is called in clipping, before the pespective divide, and is not used in later rasterization. Thus it doesn't need perspective correction. --- src/video_core/swrasterizer/rasterizer.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/rasterizer.h b/src/video_core/swrasterizer/rasterizer.h index 2f0877581..66cd6cfd4 100644 --- a/src/video_core/swrasterizer/rasterizer.h +++ b/src/video_core/swrasterizer/rasterizer.h @@ -19,10 +19,9 @@ struct Vertex : Shader::OutputVertex { // Linear interpolation // factor: 0=this, 1=vtx + // Note: This function cannot be called after perspective divide void Lerp(float24 factor, const Vertex& vtx) { pos = pos * factor + vtx.pos * (float24::FromFloat32(1) - factor); - - // TODO: Should perform perspective correct interpolation here... quat = quat * factor + vtx.quat * (float24::FromFloat32(1) - factor); color = color * factor + vtx.color * (float24::FromFloat32(1) - factor); tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor); @@ -30,12 +29,11 @@ struct Vertex : Shader::OutputVertex { tc0_w = tc0_w * factor + vtx.tc0_w * (float24::FromFloat32(1) - factor); view = view * factor + vtx.view * (float24::FromFloat32(1) - factor); tc2 = tc2 * factor + vtx.tc2 * (float24::FromFloat32(1) - factor); - - screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor); } // Linear interpolation // factor: 0=v0, 1=v1 + // Note: This function cannot be called after perspective divide static Vertex Lerp(float24 factor, const Vertex& v0, const Vertex& v1) { Vertex ret = v0; ret.Lerp(factor, v1); -- cgit v1.2.3 From 3e478ca13110639a67ad95880aae5d7d13e096b7 Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 18 Aug 2017 15:04:56 +0300 Subject: SwRasterizer/Lighting: implement bump mapping --- src/video_core/swrasterizer/lighting.cpp | 28 +++++++++++++++++++++++----- src/video_core/swrasterizer/lighting.h | 3 ++- src/video_core/swrasterizer/rasterizer.cpp | 4 ++-- 3 files changed, 27 insertions(+), 8 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index 39a3e396d..4f16bac07 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -22,14 +22,32 @@ static float LookupLightingLut(const Pica::State::Lighting& lighting, size_t lut std::tuple, Math::Vec4> ComputeFragmentsColors( const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, - const Math::Quaternion& normquat, const Math::Vec3& view) { + const Math::Quaternion& normquat, const Math::Vec3& view, + const Math::Vec4 (&texture_color)[4]) { - // TODO(Subv): Bump mapping - Math::Vec3 surface_normal = {0.0f, 0.0f, 1.0f}; + Math::Vec3 surface_normal; + Math::Vec3 surface_tangent; if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) { - LOG_CRITICAL(HW_GPU, "unimplemented bump mapping"); - UNIMPLEMENTED(); + Math::Vec3 perturbation = + texture_color[lighting.config0.bump_selector].xyz().Cast() / 127.5f - + Math::MakeVec(1.0f, 1.0f, 1.0f); + if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { + if (!lighting.config0.disable_bump_renorm) { + const float z_square = 1 - perturbation.xy().Length2(); + perturbation.z = std::sqrt(std::max(z_square, 0.0f)); + } + surface_normal = perturbation; + surface_tangent = Math::MakeVec(1.0f, 0.0f, 0.0f); + } else if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { + surface_normal = Math::MakeVec(0.0f, 0.0f, 1.0f); + surface_tangent = perturbation; + } else { + LOG_ERROR(HW_GPU, "Unknown bump mode %u", lighting.config0.bump_mode.Value()); + } + } else { + surface_normal = Math::MakeVec(0.0f, 0.0f, 1.0f); + surface_tangent = Math::MakeVec(1.0f, 0.0f, 0.0f); } // Use the normalized the quaternion when performing the rotation diff --git a/src/video_core/swrasterizer/lighting.h b/src/video_core/swrasterizer/lighting.h index 438dca926..d807a3d94 100644 --- a/src/video_core/swrasterizer/lighting.h +++ b/src/video_core/swrasterizer/lighting.h @@ -13,6 +13,7 @@ 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); + const Math::Quaternion& normquat, const Math::Vec3& view, + const Math::Vec4 (&texture_color)[4]); } // namespace Pica diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index fdc1df199..862135614 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -437,8 +437,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve 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); + std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors( + g_state.regs.lighting, g_state.lighting, normquat, view, texture_color); } for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); -- cgit v1.2.3 From b5aa5703540adceb1fc867b577dad50388a47e15 Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 18 Aug 2017 16:35:11 +0300 Subject: SwRasterizer/Lighting: implement LUT input CP --- src/video_core/swrasterizer/lighting.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index 4f16bac07..b38964530 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -52,6 +52,7 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( // Use the normalized the quaternion when performing the rotation auto normal = Math::QuaternionRotate(normquat, surface_normal); + auto tangent = Math::QuaternionRotate(normquat, surface_tangent); Math::Vec4 diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; Math::Vec4 specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; @@ -120,6 +121,16 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( result = Math::Dot(light_vector, spot_dir.Cast() / 2047.0f); break; } + case LightingRegs::LightingLutInput::CP: + if (lighting.config0.config == LightingRegs::LightingConfig::Config7) { + const Math::Vec3 norm_half_vector = half_vector.Normalized(); + const Math::Vec3 half_vector_proj = + norm_half_vector - normal * Math::Dot(normal, norm_half_vector); + result = Math::Dot(half_vector_proj, tangent); + } else { + result = 0.0f; + } + break; default: LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %u\n", static_cast(input)); UNIMPLEMENTED(); -- cgit v1.2.3 From ea51a3af261254e5455f63a0ef41e55ef1dfc471 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 22 Aug 2017 09:49:26 +0300 Subject: SwRasterizer: implement custom clip plane --- src/video_core/regs_rasterizer.h | 14 ++++++++++++-- src/video_core/swrasterizer/clipper.cpp | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/regs_rasterizer.h b/src/video_core/regs_rasterizer.h index 2874fd127..4fef00d76 100644 --- a/src/video_core/regs_rasterizer.h +++ b/src/video_core/regs_rasterizer.h @@ -5,10 +5,10 @@ #pragma once #include - #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "video_core/pica_types.h" namespace Pica { @@ -31,7 +31,17 @@ struct RasterizerRegs { BitField<0, 24, u32> viewport_size_y; - INSERT_PADDING_WORDS(0x9); + INSERT_PADDING_WORDS(0x3); + + BitField<0, 1, u32> clip_enable; + BitField<0, 24, u32> clip_coef[4]; // float24 + + Math::Vec4 GetClipCoef() const { + return {float24::FromRaw(clip_coef[0]), float24::FromRaw(clip_coef[1]), + float24::FromRaw(clip_coef[2]), float24::FromRaw(clip_coef[3])}; + } + + INSERT_PADDING_WORDS(0x1); BitField<0, 24, u32> viewport_depth_range; // float24 BitField<0, 24, u32> viewport_depth_near_plane; // float24 diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index cdbc71502..cc76ba555 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -127,8 +127,7 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu // Simple implementation of the Sutherland-Hodgman clipping algorithm. // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here) - for (auto edge : clipping_edges) { - + auto Clip = [&](const ClippingEdge& edge) { std::swap(input_list, output_list); output_list->clear(); @@ -147,12 +146,24 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu } reference_vertex = &vertex; } + }; + + for (auto edge : clipping_edges) { + Clip(edge); // Need to have at least a full triangle to continue... if (output_list->size() < 3) return; } + if (g_state.regs.rasterizer.clip_enable) { + ClippingEdge custom_edge{-g_state.regs.rasterizer.GetClipCoef()}; + Clip(custom_edge); + + if (output_list->size() < 3) + return; + } + InitScreenCoordinates((*output_list)[0]); InitScreenCoordinates((*output_list)[1]); -- cgit v1.2.3 From 417cb45e3fc20a7529ce5d548ba0fbc36ea0a621 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 22 Aug 2017 09:47:15 +0300 Subject: SwRasterizer/Clipper: flip the sign convention to match PICA and OpenGL --- src/video_core/swrasterizer/clipper.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index cc76ba555..a52129eb7 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -31,7 +31,7 @@ public: : coeffs(coeffs), bias(bias) {} bool IsInside(const Vertex& vertex) const { - return Math::Dot(vertex.pos + bias, coeffs) <= float24::FromFloat32(0); + return Math::Dot(vertex.pos + bias, coeffs) >= float24::FromFloat32(0); } bool IsOutSide(const Vertex& vertex) const { @@ -116,13 +116,13 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu static const float24 f0 = float24::FromFloat32(0.0); static const float24 f1 = float24::FromFloat32(1.0); static const std::array clipping_edges = {{ - {Math::MakeVec(f1, f0, f0, -f1)}, // x = +w - {Math::MakeVec(-f1, f0, f0, -f1)}, // x = -w - {Math::MakeVec(f0, f1, f0, -f1)}, // y = +w - {Math::MakeVec(f0, -f1, f0, -f1)}, // y = -w - {Math::MakeVec(f0, f0, f1, f0)}, // z = 0 - {Math::MakeVec(f0, f0, -f1, -f1)}, // z = -w - {Math::MakeVec(f0, f0, f0, -f1), Math::Vec4(f0, f0, f0, EPSILON)}, // w = EPSILON + {Math::MakeVec(-f1, f0, f0, f1)}, // x = +w + {Math::MakeVec(f1, f0, f0, f1)}, // x = -w + {Math::MakeVec(f0, -f1, f0, f1)}, // y = +w + {Math::MakeVec(f0, f1, f0, f1)}, // y = -w + {Math::MakeVec(f0, f0, -f1, f0)}, // z = 0 + {Math::MakeVec(f0, f0, f1, f1)}, // z = -w + {Math::MakeVec(f0, f0, f0, f1), Math::Vec4(f0, f0, f0, EPSILON)}, // w = EPSILON }}; // Simple implementation of the Sutherland-Hodgman clipping algorithm. @@ -157,7 +157,7 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu } if (g_state.regs.rasterizer.clip_enable) { - ClippingEdge custom_edge{-g_state.regs.rasterizer.GetClipCoef()}; + ClippingEdge custom_edge{g_state.regs.rasterizer.GetClipCoef()}; Clip(custom_edge); if (output_list->size() < 3) -- cgit v1.2.3 From da88f3b8f0f9f1162b7ad41f70e2126195eee999 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 21 Aug 2017 12:18:52 -0500 Subject: Warnings: Fixed a few missing-return warnings in video_core. --- src/video_core/regs_framebuffer.h | 10 ++++------ src/video_core/swrasterizer/framebuffer.cpp | 2 ++ src/video_core/swrasterizer/texturing.cpp | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/regs_framebuffer.h b/src/video_core/regs_framebuffer.h index a50bd4111..7b565f911 100644 --- a/src/video_core/regs_framebuffer.h +++ b/src/video_core/regs_framebuffer.h @@ -256,10 +256,9 @@ struct FramebufferRegs { return 3; case DepthFormat::D24S8: return 4; - default: - LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); - UNIMPLEMENTED(); } + + ASSERT_MSG(false, "Unknown depth format %u", format); } // Returns the number of bits per depth component of the specified depth format @@ -270,10 +269,9 @@ struct FramebufferRegs { case DepthFormat::D24: case DepthFormat::D24S8: return 24; - default: - LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); - UNIMPLEMENTED(); } + + ASSERT_MSG(false, "Unknown depth format %u", format); } INSERT_PADDING_WORDS(0x20); diff --git a/src/video_core/swrasterizer/framebuffer.cpp b/src/video_core/swrasterizer/framebuffer.cpp index 7de3aac75..f34eab6cf 100644 --- a/src/video_core/swrasterizer/framebuffer.cpp +++ b/src/video_core/swrasterizer/framebuffer.cpp @@ -352,6 +352,8 @@ u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op) { case FramebufferRegs::LogicOp::OrInverted: return ~src | dest; } + + UNREACHABLE(); }; } // namespace Rasterizer diff --git a/src/video_core/swrasterizer/texturing.cpp b/src/video_core/swrasterizer/texturing.cpp index 4f02b93f2..79b1ce841 100644 --- a/src/video_core/swrasterizer/texturing.cpp +++ b/src/video_core/swrasterizer/texturing.cpp @@ -89,6 +89,8 @@ Math::Vec3 GetColorModifier(TevStageConfig::ColorModifier factor, case ColorModifier::OneMinusSourceBlue: return (Math::Vec3(255, 255, 255) - values.bbb()).Cast(); } + + UNREACHABLE(); }; u8 GetAlphaModifier(TevStageConfig::AlphaModifier factor, const Math::Vec4& values) { @@ -119,6 +121,8 @@ u8 GetAlphaModifier(TevStageConfig::AlphaModifier factor, const Math::Vec4& case AlphaModifier::OneMinusSourceBlue: return 255 - values.b(); } + + UNREACHABLE(); }; Math::Vec3 ColorCombine(TevStageConfig::Operation op, const Math::Vec3 input[3]) { -- cgit v1.2.3 From 12fbc8c8dff3265b03cffdd5bb5e6dd6537cd824 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 27 Aug 2017 07:33:27 +0300 Subject: pica/lighting: only apply Fresnel factor for the last light --- src/video_core/renderer_opengl/gl_shader_gen.cpp | 9 +++++---- src/video_core/swrasterizer/lighting.cpp | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 3f390491a..b5f359da6 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -750,7 +750,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { } // Fresnel - if (lighting.lut_fr.enable && + // Note: only the last entry in the light slots applies the Fresnel factor + if (light_index == lighting.src_num - 1 && lighting.lut_fr.enable && LightingRegs::IsLightingSamplerSupported(lighting.config, LightingRegs::LightingSampler::Fresnel)) { // Lookup fresnel LUT value @@ -759,17 +760,17 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { lighting.lut_fr.type, lighting.lut_fr.abs_input); value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + value + ")"; - // Enabled for difffuse lighting alpha component + // Enabled for diffuse lighting alpha component if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { - out += "diffuse_sum.a *= " + value + ";\n"; + out += "diffuse_sum.a = " + value + ";\n"; } // Enabled for the specular lighting alpha component if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::SecondaryAlpha || lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { - out += "specular_sum.a *= " + value + ";\n"; + out += "specular_sum.a = " + value + ";\n"; } } diff --git a/src/video_core/swrasterizer/lighting.cpp b/src/video_core/swrasterizer/lighting.cpp index b38964530..5fa748611 100644 --- a/src/video_core/swrasterizer/lighting.cpp +++ b/src/video_core/swrasterizer/lighting.cpp @@ -230,7 +230,8 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); // Fresnel - if (lighting.config1.disable_lut_fr == 0 && + // Note: only the last entry in the light slots applies the Fresnel factor + if (light_index == lighting.max_light_index && lighting.config1.disable_lut_fr == 0 && LightingRegs::IsLightingSamplerSupported(lighting.config0.config, LightingRegs::LightingSampler::Fresnel)) { @@ -242,14 +243,14 @@ std::tuple, Math::Vec4> ComputeFragmentsColors( if (lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || lighting.config0.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { - diffuse_sum.a() *= lut_value; + 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; + specular_sum.a() = lut_value; } } -- cgit v1.2.3 From a321bce37834c1f3034bd87df14fc71c13e6b84a Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 29 Aug 2017 12:59:54 -0500 Subject: Disable unary operator- on Math::Vec2/Vec3/Vec4 for unsigned types. It is unlikely we will ever use this without first doing a Cast to a signed type. Fixes 9 "unary minus operator applied to unsigned type, result still unsigned" warnings on MSVC2017.3 --- src/common/vector_math.h | 12 ++++++++---- src/video_core/swrasterizer/clipper.cpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/video_core/swrasterizer') diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 6e2a5ad60..2b05f66ee 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -31,6 +31,7 @@ #pragma once #include +#include namespace Math { @@ -90,7 +91,8 @@ public: y -= other.y; } - Vec2 operator-() const { + template + Vec2::value, U>> operator-() const { return MakeVec(-x, -y); } Vec2 operator*(const Vec2& other) const { @@ -247,7 +249,8 @@ public: z -= other.z; } - Vec3 operator-() const { + template + Vec3::value, U>> operator-() const { return MakeVec(-x, -y, -z); } Vec3 operator*(const Vec3& other) const { @@ -462,7 +465,8 @@ public: w -= other.w; } - Vec4 operator-() const { + template + Vec4::value, U>> operator-() const { return MakeVec(-x, -y, -z, -w); } Vec4 operator*(const Vec4& other) const { @@ -720,4 +724,4 @@ static inline Vec4 MakeVec(const T& x, const Vec3& yzw) { return MakeVec(x, yzw[0], yzw[1], yzw[2]); } -} // namespace +} // namespace Math diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index a52129eb7..c1ed48398 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -98,7 +98,7 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu auto FlipQuaternionIfOpposite = [](auto& a, const auto& b) { if (Math::Dot(a, b) < float24::Zero()) - a = -a; + a = a * float24::FromFloat32(-1.0f); }; // Flip the quaternions if they are opposite to prevent interpolating them over the wrong -- cgit v1.2.3