mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #2822 from wwylele/sw_lighting-2
Implement fragment lighting in the sw renderer (take 2)
This commit is contained in:
		
						commit
						792dee47a7
					
				| @ -30,6 +30,11 @@ public: | |||||||
|         return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), |         return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), | ||||||
|                 w * other.w - Dot(xyz, other.xyz)}; |                 w * other.w - Dot(xyz, other.xyz)}; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     Quaternion<T> Normalized() const { | ||||||
|  |         T length = std::sqrt(xyz.Length2() + w * w); | ||||||
|  |         return {xyz / length, w / length}; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
|  | |||||||
| @ -31,7 +31,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <cmath> | #include <cmath> | ||||||
| #include <type_traits> |  | ||||||
| 
 | 
 | ||||||
| namespace Math { | namespace Math { | ||||||
| 
 | 
 | ||||||
| @ -90,7 +89,7 @@ public: | |||||||
|         x -= other.x; |         x -= other.x; | ||||||
|         y -= other.y; |         y -= other.y; | ||||||
|     } |     } | ||||||
|     template <typename Q = T, class = typename std::enable_if<std::is_signed<Q>::value>::type> | 
 | ||||||
|     Vec2<decltype(-T{})> operator-() const { |     Vec2<decltype(-T{})> operator-() const { | ||||||
|         return MakeVec(-x, -y); |         return MakeVec(-x, -y); | ||||||
|     } |     } | ||||||
| @ -247,7 +246,7 @@ public: | |||||||
|         y -= other.y; |         y -= other.y; | ||||||
|         z -= other.z; |         z -= other.z; | ||||||
|     } |     } | ||||||
|     template <typename Q = T, class = typename std::enable_if<std::is_signed<Q>::value>::type> | 
 | ||||||
|     Vec3<decltype(-T{})> operator-() const { |     Vec3<decltype(-T{})> operator-() const { | ||||||
|         return MakeVec(-x, -y, -z); |         return MakeVec(-x, -y, -z); | ||||||
|     } |     } | ||||||
| @ -462,7 +461,7 @@ public: | |||||||
|         z -= other.z; |         z -= other.z; | ||||||
|         w -= other.w; |         w -= other.w; | ||||||
|     } |     } | ||||||
|     template <typename Q = T, class = typename std::enable_if<std::is_signed<Q>::value>::type> | 
 | ||||||
|     Vec4<decltype(-T{})> operator-() const { |     Vec4<decltype(-T{})> operator-() const { | ||||||
|         return MakeVec(-x, -y, -z, -w); |         return MakeVec(-x, -y, -z, -w); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ set(SRCS | |||||||
|             shader/shader_interpreter.cpp |             shader/shader_interpreter.cpp | ||||||
|             swrasterizer/clipper.cpp |             swrasterizer/clipper.cpp | ||||||
|             swrasterizer/framebuffer.cpp |             swrasterizer/framebuffer.cpp | ||||||
|  |             swrasterizer/lighting.cpp | ||||||
|             swrasterizer/proctex.cpp |             swrasterizer/proctex.cpp | ||||||
|             swrasterizer/rasterizer.cpp |             swrasterizer/rasterizer.cpp | ||||||
|             swrasterizer/swrasterizer.cpp |             swrasterizer/swrasterizer.cpp | ||||||
| @ -55,6 +56,7 @@ set(HEADERS | |||||||
|             shader/shader_interpreter.h |             shader/shader_interpreter.h | ||||||
|             swrasterizer/clipper.h |             swrasterizer/clipper.h | ||||||
|             swrasterizer/framebuffer.h |             swrasterizer/framebuffer.h | ||||||
|  |             swrasterizer/lighting.h | ||||||
|             swrasterizer/proctex.h |             swrasterizer/proctex.h | ||||||
|             swrasterizer/rasterizer.h |             swrasterizer/rasterizer.h | ||||||
|             swrasterizer/swrasterizer.h |             swrasterizer/swrasterizer.h | ||||||
|  | |||||||
| @ -79,7 +79,7 @@ struct State { | |||||||
|         std::array<ColorDifferenceEntry, 256> color_diff_table; |         std::array<ColorDifferenceEntry, 256> color_diff_table; | ||||||
|     } proctex; |     } proctex; | ||||||
| 
 | 
 | ||||||
|     struct { |     struct Lighting { | ||||||
|         union LutEntry { |         union LutEntry { | ||||||
|             // Used for raw access
 |             // Used for raw access
 | ||||||
|             u32 raw; |             u32 raw; | ||||||
|  | |||||||
| @ -95,6 +95,17 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu | |||||||
|     static const size_t MAX_VERTICES = 9; |     static const size_t MAX_VERTICES = 9; | ||||||
|     static_vector<Vertex, MAX_VERTICES> buffer_a = {v0, v1, v2}; |     static_vector<Vertex, MAX_VERTICES> buffer_a = {v0, v1, v2}; | ||||||
|     static_vector<Vertex, MAX_VERTICES> buffer_b; |     static_vector<Vertex, MAX_VERTICES> 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* output_list = &buffer_a; | ||||||
|     auto* input_list = &buffer_b; |     auto* input_list = &buffer_b; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										250
									
								
								src/video_core/swrasterizer/lighting.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/video_core/swrasterizer/lighting.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -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<u8>, Math::Vec4<u8>> ComputeFragmentsColors( | ||||||
|  |     const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, | ||||||
|  |     const Math::Quaternion<float>& normquat, const Math::Vec3<float>& view) { | ||||||
|  | 
 | ||||||
|  |     // TODO(Subv): Bump mapping
 | ||||||
|  |     Math::Vec3<float> 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<float> diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; | ||||||
|  |     Math::Vec4<float> 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<float> refl_value = {}; | ||||||
|  |         Math::Vec3<float> position = {float16::FromRaw(light_config.x).ToFloat32(), | ||||||
|  |                                       float16::FromRaw(light_config.y).ToFloat32(), | ||||||
|  |                                       float16::FromRaw(light_config.z).ToFloat32()}; | ||||||
|  |         Math::Vec3<float> 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<size_t>(LightingRegs::LightingSampler::DistanceAttenuation) + num; | ||||||
|  | 
 | ||||||
|  |             float sample_loc = MathUtil::Clamp(scale * distance + bias, 0.0f, 1.0f); | ||||||
|  | 
 | ||||||
|  |             u8 lutindex = | ||||||
|  |                 static_cast<u8>(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<float> norm_view = view.Normalized(); | ||||||
|  |             Math::Vec3<float> 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<u32>(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<u8>(MathUtil::Clamp(flr, 0.0f, 255.0f)); | ||||||
|  |                 delta = result * 256 - index; | ||||||
|  |             } else { | ||||||
|  |                 float flr = std::floor(result * 128.0f); | ||||||
|  |                 s8 signed_index = static_cast<s8>(MathUtil::Clamp(flr, -128.0f, 127.0f)); | ||||||
|  |                 delta = result * 128.0f - signed_index; | ||||||
|  |                 index = static_cast<u8>(signed_index); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             float scale = lighting.lut_scale.GetScale(scale_enum); | ||||||
|  |             return scale * | ||||||
|  |                    LookupLightingLut(lighting_state, static_cast<size_t>(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<float> 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<float> 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<float>(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<u8>(); | ||||||
|  |     auto specular = Math::MakeVec<float>(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<u8>(); | ||||||
|  |     return {diffuse, specular}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Pica
 | ||||||
							
								
								
									
										18
									
								
								src/video_core/swrasterizer/lighting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/video_core/swrasterizer/lighting.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 <tuple> | ||||||
|  | #include "common/quaternion.h" | ||||||
|  | #include "common/vector_math.h" | ||||||
|  | #include "video_core/pica_state.h" | ||||||
|  | 
 | ||||||
|  | namespace Pica { | ||||||
|  | 
 | ||||||
|  | std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors( | ||||||
|  |     const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, | ||||||
|  |     const Math::Quaternion<float>& normquat, const Math::Vec3<float>& view); | ||||||
|  | 
 | ||||||
|  | } // namespace Pica
 | ||||||
| @ -13,6 +13,7 @@ | |||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/math_util.h" | #include "common/math_util.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
|  | #include "common/quaternion.h" | ||||||
| #include "common/vector_math.h" | #include "common/vector_math.h" | ||||||
| #include "core/hw/gpu.h" | #include "core/hw/gpu.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| @ -24,6 +25,7 @@ | |||||||
| #include "video_core/regs_texturing.h" | #include "video_core/regs_texturing.h" | ||||||
| #include "video_core/shader/shader.h" | #include "video_core/shader/shader.h" | ||||||
| #include "video_core/swrasterizer/framebuffer.h" | #include "video_core/swrasterizer/framebuffer.h" | ||||||
|  | #include "video_core/swrasterizer/lighting.h" | ||||||
| #include "video_core/swrasterizer/proctex.h" | #include "video_core/swrasterizer/proctex.h" | ||||||
| #include "video_core/swrasterizer/rasterizer.h" | #include "video_core/swrasterizer/rasterizer.h" | ||||||
| #include "video_core/swrasterizer/texturing.h" | #include "video_core/swrasterizer/texturing.h" | ||||||
| @ -419,6 +421,26 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||||||
|                 regs.texturing.tev_combiner_buffer_color.a, |                 regs.texturing.tev_combiner_buffer_color.a, | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|  |             Math::Vec4<u8> primary_fragment_color = {0, 0, 0, 0}; | ||||||
|  |             Math::Vec4<u8> secondary_fragment_color = {0, 0, 0, 0}; | ||||||
|  | 
 | ||||||
|  |             if (!g_state.regs.lighting.disable) { | ||||||
|  |                 Math::Quaternion<float> normquat = Math::Quaternion<float>{ | ||||||
|  |                     {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<float> 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(); |             for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); | ||||||
|                  ++tev_stage_index) { |                  ++tev_stage_index) { | ||||||
|                 const auto& tev_stage = tev_stages[tev_stage_index]; |                 const auto& tev_stage = tev_stages[tev_stage_index]; | ||||||
| @ -427,14 +449,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||||||
|                 auto GetSource = [&](Source source) -> Math::Vec4<u8> { |                 auto GetSource = [&](Source source) -> Math::Vec4<u8> { | ||||||
|                     switch (source) { |                     switch (source) { | ||||||
|                     case Source::PrimaryColor: |                     case Source::PrimaryColor: | ||||||
| 
 |  | ||||||
|                     // HACK: Until we implement fragment lighting, use primary_color
 |  | ||||||
|                     case Source::PrimaryFragmentColor: |  | ||||||
|                         return primary_color; |                         return primary_color; | ||||||
| 
 | 
 | ||||||
|                     // HACK: Until we implement fragment lighting, use zero
 |                     case Source::PrimaryFragmentColor: | ||||||
|  |                         return primary_fragment_color; | ||||||
|  | 
 | ||||||
|                     case Source::SecondaryFragmentColor: |                     case Source::SecondaryFragmentColor: | ||||||
|                         return {0, 0, 0, 0}; |                         return secondary_fragment_color; | ||||||
| 
 | 
 | ||||||
|                     case Source::Texture0: |                     case Source::Texture0: | ||||||
|                         return texture_color[0]; |                         return texture_color[0]; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Weiyi Wang
						Weiyi Wang