summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2017-06-09 13:14:55 -0500
committerGravatar wwylele2017-07-11 19:39:15 +0300
commitb2f472a2b1f36073b0070b81c08a666380ad180d (patch)
tree4357008f1dbc5644d31406e89e646e93c4724ded /src
parentMerge pull request #2815 from mailwl/bossp (diff)
downloadyuzu-b2f472a2b1f36073b0070b81c08a666380ad180d.tar.gz
yuzu-b2f472a2b1f36073b0070b81c08a666380ad180d.tar.xz
yuzu-b2f472a2b1f36073b0070b81c08a666380ad180d.zip
SwRasterizer: Implement primary fragment color.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/swrasterizer/rasterizer.cpp117
1 files changed, 113 insertions, 4 deletions
diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp
index 512e81c08..1ab41c2df 100644
--- a/src/video_core/swrasterizer/rasterizer.cpp
+++ b/src/video_core/swrasterizer/rasterizer.cpp
@@ -13,6 +13,7 @@
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/math_util.h" 14#include "common/math_util.h"
15#include "common/microprofile.h" 15#include "common/microprofile.h"
16#include "common/quaternion.h"
16#include "common/vector_math.h" 17#include "common/vector_math.h"
17#include "core/hw/gpu.h" 18#include "core/hw/gpu.h"
18#include "core/memory.h" 19#include "core/memory.h"
@@ -114,6 +115,86 @@ static std::tuple<float24, float24, PAddr> ConvertCubeCoord(float24 u, float24 v
114 return std::make_tuple(x / z * half + half, y / z * half + half, addr); 115 return std::make_tuple(x / z * half + half, y / z * half + half, addr);
115} 116}
116 117
118std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(const Math::Quaternion<float>& normquat, const Math::Vec3<float>& view) {
119 const auto& lighting = g_state.regs.lighting;
120
121 if (lighting.disable)
122 return {{}, {}};
123
124 // TODO(Subv): Bump mapping
125 Math::Vec3<float> surface_normal = {0.0f, 0.0f, 1.0f};
126
127 if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) {
128 LOG_CRITICAL(HW_GPU, "unimplemented bump mapping");
129 UNIMPLEMENTED();
130 }
131
132 // TODO(Subv): Do we need to normalize the quaternion here?
133 auto normal = Math::QuaternionRotate(normquat, surface_normal);
134
135 Math::Vec3<float> light_vector = {};
136 Math::Vec3<float> diffuse_sum = {};
137 // TODO(Subv): Calculate specular
138 Math::Vec3<float> specular_sum = {};
139
140 for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) {
141 unsigned num = lighting.light_enable.GetNum(light_index);
142 const auto& light_config = g_state.regs.lighting.light[num];
143
144 Math::Vec3<float> position = {float16::FromRaw(light_config.x).ToFloat32(), float16::FromRaw(light_config.y).ToFloat32(), float16::FromRaw(light_config.z).ToFloat32()};
145
146 if (light_config.config.directional)
147 light_vector = position;
148 else
149 light_vector = position + view;
150
151 light_vector.Normalize();
152
153 auto dot_product = Math::Dot(light_vector, normal);
154
155 if (light_config.config.two_sided_diffuse)
156 dot_product = std::abs(dot_product);
157 else
158 dot_product = std::max(dot_product, 0.0f);
159
160 float dist_atten = 1.0f;
161 if (!lighting.IsDistAttenDisabled(num)) {
162 auto distance = (-view - position).Length();
163 float scale = Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32();
164 float bias = Pica::float20::FromRaw(light_config.dist_atten_scale).ToFloat32();
165 size_t lut = static_cast<size_t>(LightingRegs::LightingSampler::DistanceAttenuation) + num;
166
167 float sample_loc = scale * distance + bias;
168 unsigned index_i = static_cast<unsigned>(MathUtil::Clamp(floor(sample_loc * 256), 0.0f, 1.0f));
169
170 float index_f = sample_loc - index_i;
171
172 ASSERT_MSG(lut < g_state.lighting.luts.size(), "Out of range lut");
173
174 float lut_value = g_state.lighting.luts[lut][index_i].ToFloat();
175 float lut_diff = g_state.lighting.luts[lut][index_i].DiffToFloat();
176
177 dist_atten = lut_value + lut_diff * index_f;
178 }
179
180 auto diffuse = light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f();
181 diffuse_sum += diffuse * dist_atten;
182 }
183
184 diffuse_sum += lighting.global_ambient.ToVec3f();
185 return {
186 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, 255).Cast<u8>(),
187 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, 255).Cast<u8>()
188 };
189}
190
191static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) {
192 Math::Vec4f a{ qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32() };
193 Math::Vec4f b{ qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32() };
194
195 return (Math::Dot(a, b) < 0.f);
196}
197
117MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240)); 198MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240));
118 199
119/** 200/**
@@ -207,6 +288,15 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
207 int bias2 = 288 int bias2 =
208 IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; 289 IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0;
209 290
291 // Flip the quaternions if they are opposite to prevent interpolating them over the wrong direction.
292 auto v1_quat = v1.quat;
293 auto v2_quat = v2.quat;
294
295 if (AreQuaternionsOpposite(v0.quat, v1.quat))
296 v1_quat = v1_quat * float24::FromFloat32(-1.0f);
297 if (AreQuaternionsOpposite(v0.quat, v2.quat))
298 v2_quat = v2_quat * float24::FromFloat32(-1.0f);
299
210 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); 300 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
211 301
212 auto textures = regs.texturing.GetTextures(); 302 auto textures = regs.texturing.GetTextures();
@@ -305,6 +395,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
305 255), 395 255),
306 }; 396 };
307 397
398 Math::Quaternion<float> normquat{
399 {
400 GetInterpolatedAttribute(v0.quat.x, v1_quat.x, v2_quat.x).ToFloat32(),
401 GetInterpolatedAttribute(v0.quat.y, v1_quat.y, v2_quat.y).ToFloat32(),
402 GetInterpolatedAttribute(v0.quat.z, v1_quat.z, v2_quat.z).ToFloat32()
403 },
404 GetInterpolatedAttribute(v0.quat.w, v1_quat.w, v2_quat.w).ToFloat32(),
405 };
406
407 Math::Vec3<float> fragment_position{
408 GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(),
409 GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(),
410 GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32()
411 };
412
308 Math::Vec2<float24> uv[3]; 413 Math::Vec2<float24> uv[3];
309 uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); 414 uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u());
310 uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); 415 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
419 regs.texturing.tev_combiner_buffer_color.a, 524 regs.texturing.tev_combiner_buffer_color.a,
420 }; 525 };
421 526
527 Math::Vec4<u8> primary_fragment_color;
528 Math::Vec4<u8> secondary_fragment_color;
529
530 std::tie(primary_fragment_color, secondary_fragment_color) = ComputeFragmentsColors(normquat, fragment_position);
531
422 for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); 532 for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size();
423 ++tev_stage_index) { 533 ++tev_stage_index) {
424 const auto& tev_stage = tev_stages[tev_stage_index]; 534 const auto& tev_stage = tev_stages[tev_stage_index];
@@ -427,14 +537,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
427 auto GetSource = [&](Source source) -> Math::Vec4<u8> { 537 auto GetSource = [&](Source source) -> Math::Vec4<u8> {
428 switch (source) { 538 switch (source) {
429 case Source::PrimaryColor: 539 case Source::PrimaryColor:
540 return primary_color;
430 541
431 // HACK: Until we implement fragment lighting, use primary_color
432 case Source::PrimaryFragmentColor: 542 case Source::PrimaryFragmentColor:
433 return primary_color; 543 return primary_fragment_color;
434 544
435 // HACK: Until we implement fragment lighting, use zero
436 case Source::SecondaryFragmentColor: 545 case Source::SecondaryFragmentColor:
437 return {0, 0, 0, 0}; 546 return secondary_fragment_color;
438 547
439 case Source::Texture0: 548 case Source::Texture0:
440 return texture_color[0]; 549 return texture_color[0];