summaryrefslogtreecommitdiff
path: root/src/video_core/rasterizer.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2016-06-15 17:55:36 -0400
committerGravatar GitHub2016-06-15 17:55:36 -0400
commit7d2d6e5f7864973c9d945d76887ff7e1209be205 (patch)
treeab6addc2f62eadc637c6aad42625d99d925bca69 /src/video_core/rasterizer.cpp
parentMerge pull request #1842 from Subv/ports (diff)
parentOpenGL: Implement fog (diff)
downloadyuzu-7d2d6e5f7864973c9d945d76887ff7e1209be205.tar.gz
yuzu-7d2d6e5f7864973c9d945d76887ff7e1209be205.tar.xz
yuzu-7d2d6e5f7864973c9d945d76887ff7e1209be205.zip
Merge pull request #1875 from JayFoxRox/fog
Implement standard fog (fog mode 5)
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r--src/video_core/rasterizer.cpp73
1 files changed, 52 insertions, 21 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 65168f05a..a84170094 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -398,6 +398,26 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
398 float24::FromFloat32(static_cast<float>(w2))); 398 float24::FromFloat32(static_cast<float>(w2)));
399 float24 interpolated_w_inverse = float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates); 399 float24 interpolated_w_inverse = float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates);
400 400
401 // interpolated_z = z / w
402 float interpolated_z_over_w = (v0.screenpos[2].ToFloat32() * w0 +
403 v1.screenpos[2].ToFloat32() * w1 +
404 v2.screenpos[2].ToFloat32() * w2) / wsum;
405
406 // Not fully accurate. About 3 bits in precision are missing.
407 // Z-Buffer (z / w * scale + offset)
408 float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32();
409 float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32();
410 float depth = interpolated_z_over_w * depth_scale + depth_offset;
411
412 // Potentially switch to W-Buffer
413 if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
414 // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w)
415 depth *= interpolated_w_inverse.ToFloat32() * wsum;
416 }
417
418 // Clamp the result
419 depth = MathUtil::Clamp(depth, 0.0f, 1.0f);
420
401 // Perspective correct attribute interpolation: 421 // Perspective correct attribute interpolation:
402 // Attribute values cannot be calculated by simple linear interpolation since 422 // Attribute values cannot be calculated by simple linear interpolation since
403 // they are not linear in screen space. For example, when interpolating a 423 // they are not linear in screen space. For example, when interpolating a
@@ -833,6 +853,38 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
833 continue; 853 continue;
834 } 854 }
835 855
856 // Apply fog combiner
857 // Not fully accurate. We'd have to know what data type is used to
858 // store the depth etc. Using float for now until we know more
859 // about Pica datatypes
860 if (regs.fog_mode == Regs::FogMode::Fog) {
861 const Math::Vec3<u8> fog_color = {
862 static_cast<u8>(regs.fog_color.r.Value()),
863 static_cast<u8>(regs.fog_color.g.Value()),
864 static_cast<u8>(regs.fog_color.b.Value()),
865 };
866
867 // Get index into fog LUT
868 float fog_index;
869 if (g_state.regs.fog_flip) {
870 fog_index = (1.0f - depth) * 128.0f;
871 } else {
872 fog_index = depth * 128.0f;
873 }
874
875 // Generate clamped fog factor from LUT for given fog index
876 float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
877 float fog_f = fog_index - fog_i;
878 const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
879 float fog_factor = (fog_lut_entry.value + fog_lut_entry.difference * fog_f) / 2047.0f; // This is signed fixed point 1.11
880 fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
881
882 // Blend the fog
883 for (unsigned i = 0; i < 3; i++) {
884 combiner_output[i] = fog_factor * combiner_output[i] + (1.0f - fog_factor) * fog_color[i];
885 }
886 }
887
836 u8 old_stencil = 0; 888 u8 old_stencil = 0;
837 889
838 auto UpdateStencil = [stencil_test, x, y, &old_stencil](Pica::Regs::StencilAction action) { 890 auto UpdateStencil = [stencil_test, x, y, &old_stencil](Pica::Regs::StencilAction action) {
@@ -887,27 +939,6 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
887 } 939 }
888 } 940 }
889 941
890 // interpolated_z = z / w
891 float interpolated_z_over_w = (v0.screenpos[2].ToFloat32() * w0 +
892 v1.screenpos[2].ToFloat32() * w1 +
893 v2.screenpos[2].ToFloat32() * w2) / wsum;
894
895 // Not fully accurate. About 3 bits in precision are missing.
896 // Z-Buffer (z / w * scale + offset)
897 float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32();
898 float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32();
899 float depth = interpolated_z_over_w * depth_scale + depth_offset;
900
901 // Potentially switch to W-Buffer
902 if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
903
904 // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w)
905 depth *= interpolated_w_inverse.ToFloat32() * wsum;
906 }
907
908 // Clamp the result
909 depth = MathUtil::Clamp(depth, 0.0f, 1.0f);
910
911 // Convert float to integer 942 // Convert float to integer
912 unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format); 943 unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format);
913 u32 z = (u32)(depth * ((1 << num_bits) - 1)); 944 u32 z = (u32)(depth * ((1 << num_bits) - 1));