diff options
| author | 2016-06-15 17:55:36 -0400 | |
|---|---|---|
| committer | 2016-06-15 17:55:36 -0400 | |
| commit | 7d2d6e5f7864973c9d945d76887ff7e1209be205 (patch) | |
| tree | ab6addc2f62eadc637c6aad42625d99d925bca69 /src/video_core/rasterizer.cpp | |
| parent | Merge pull request #1842 from Subv/ports (diff) | |
| parent | OpenGL: Implement fog (diff) | |
| download | yuzu-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.cpp | 73 |
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)); |