diff options
Diffstat (limited to 'src/video_core/clipper.cpp')
| -rw-r--r-- | src/video_core/clipper.cpp | 72 |
1 files changed, 33 insertions, 39 deletions
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp index db99ce666..05b5cea73 100644 --- a/src/video_core/clipper.cpp +++ b/src/video_core/clipper.cpp | |||
| @@ -5,15 +5,12 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <cstddef> | 7 | #include <cstddef> |
| 8 | |||
| 9 | #include <boost/container/static_vector.hpp> | 8 | #include <boost/container/static_vector.hpp> |
| 10 | #include <boost/container/vector.hpp> | 9 | #include <boost/container/vector.hpp> |
| 11 | |||
| 12 | #include "common/bit_field.h" | 10 | #include "common/bit_field.h" |
| 13 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 14 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 15 | #include "common/vector_math.h" | 13 | #include "common/vector_math.h" |
| 16 | |||
| 17 | #include "video_core/clipper.h" | 14 | #include "video_core/clipper.h" |
| 18 | #include "video_core/pica.h" | 15 | #include "video_core/pica.h" |
| 19 | #include "video_core/pica_state.h" | 16 | #include "video_core/pica_state.h" |
| @@ -27,15 +24,10 @@ namespace Clipper { | |||
| 27 | 24 | ||
| 28 | struct ClippingEdge { | 25 | struct ClippingEdge { |
| 29 | public: | 26 | public: |
| 30 | ClippingEdge(Math::Vec4<float24> coeffs, | 27 | ClippingEdge(Math::Vec4<float24> coeffs, Math::Vec4<float24> bias = Math::Vec4<float24>( |
| 31 | Math::Vec4<float24> bias = Math::Vec4<float24>(float24::FromFloat32(0), | 28 | float24::FromFloat32(0), float24::FromFloat32(0), |
| 32 | float24::FromFloat32(0), | 29 | float24::FromFloat32(0), float24::FromFloat32(0))) |
| 33 | float24::FromFloat32(0), | 30 | : coeffs(coeffs), bias(bias) {} |
| 34 | float24::FromFloat32(0))) | ||
| 35 | : coeffs(coeffs), | ||
| 36 | bias(bias) | ||
| 37 | { | ||
| 38 | } | ||
| 39 | 31 | ||
| 40 | bool IsInside(const OutputVertex& vertex) const { | 32 | bool IsInside(const OutputVertex& vertex) const { |
| 41 | return Math::Dot(vertex.pos + bias, coeffs) <= float24::FromFloat32(0); | 33 | return Math::Dot(vertex.pos + bias, coeffs) <= float24::FromFloat32(0); |
| @@ -59,8 +51,7 @@ private: | |||
| 59 | Math::Vec4<float24> bias; | 51 | Math::Vec4<float24> bias; |
| 60 | }; | 52 | }; |
| 61 | 53 | ||
| 62 | static void InitScreenCoordinates(OutputVertex& vtx) | 54 | static void InitScreenCoordinates(OutputVertex& vtx) { |
| 63 | { | ||
| 64 | struct { | 55 | struct { |
| 65 | float24 halfsize_x; | 56 | float24 halfsize_x; |
| 66 | float24 offset_x; | 57 | float24 offset_x; |
| @@ -73,8 +64,8 @@ static void InitScreenCoordinates(OutputVertex& vtx) | |||
| 73 | const auto& regs = g_state.regs; | 64 | const auto& regs = g_state.regs; |
| 74 | viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x); | 65 | viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x); |
| 75 | viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y); | 66 | viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y); |
| 76 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); | 67 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); |
| 77 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); | 68 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); |
| 78 | 69 | ||
| 79 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; | 70 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; |
| 80 | vtx.color *= inv_w; | 71 | vtx.color *= inv_w; |
| @@ -85,12 +76,14 @@ static void InitScreenCoordinates(OutputVertex& vtx) | |||
| 85 | vtx.tc2 *= inv_w; | 76 | vtx.tc2 *= inv_w; |
| 86 | vtx.pos.w = inv_w; | 77 | vtx.pos.w = inv_w; |
| 87 | 78 | ||
| 88 | vtx.screenpos[0] = (vtx.pos.x * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; | 79 | vtx.screenpos[0] = |
| 89 | vtx.screenpos[1] = (vtx.pos.y * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; | 80 | (vtx.pos.x * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; |
| 81 | vtx.screenpos[1] = | ||
| 82 | (vtx.pos.y * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; | ||
| 90 | vtx.screenpos[2] = vtx.pos.z * inv_w; | 83 | vtx.screenpos[2] = vtx.pos.z * inv_w; |
| 91 | } | 84 | } |
| 92 | 85 | ||
| 93 | void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const OutputVertex &v2) { | 86 | void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) { |
| 94 | using boost::container::static_vector; | 87 | using boost::container::static_vector; |
| 95 | 88 | ||
| 96 | // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at | 89 | // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at |
| @@ -98,10 +91,10 @@ void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const Outpu | |||
| 98 | // introduces at most 1 new vertex to the polygon. Since we start with a triangle and have a | 91 | // introduces at most 1 new vertex to the polygon. Since we start with a triangle and have a |
| 99 | // fixed 6 clipping planes, the maximum number of vertices of the clipped polygon is 3 + 6 = 9. | 92 | // fixed 6 clipping planes, the maximum number of vertices of the clipped polygon is 3 + 6 = 9. |
| 100 | static const size_t MAX_VERTICES = 9; | 93 | static const size_t MAX_VERTICES = 9; |
| 101 | static_vector<OutputVertex, MAX_VERTICES> buffer_a = { v0, v1, v2 }; | 94 | static_vector<OutputVertex, MAX_VERTICES> buffer_a = {v0, v1, v2}; |
| 102 | static_vector<OutputVertex, MAX_VERTICES> buffer_b; | 95 | static_vector<OutputVertex, MAX_VERTICES> buffer_b; |
| 103 | auto* output_list = &buffer_a; | 96 | auto* output_list = &buffer_a; |
| 104 | auto* input_list = &buffer_b; | 97 | auto* input_list = &buffer_b; |
| 105 | 98 | ||
| 106 | // NOTE: We clip against a w=epsilon plane to guarantee that the output has a positive w value. | 99 | // NOTE: We clip against a w=epsilon plane to guarantee that the output has a positive w value. |
| 107 | // TODO: Not sure if this is a valid approach. Also should probably instead use the smallest | 100 | // TODO: Not sure if this is a valid approach. Also should probably instead use the smallest |
| @@ -110,13 +103,13 @@ void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const Outpu | |||
| 110 | static const float24 f0 = float24::FromFloat32(0.0); | 103 | static const float24 f0 = float24::FromFloat32(0.0); |
| 111 | static const float24 f1 = float24::FromFloat32(1.0); | 104 | static const float24 f1 = float24::FromFloat32(1.0); |
| 112 | static const std::array<ClippingEdge, 7> clipping_edges = {{ | 105 | static const std::array<ClippingEdge, 7> clipping_edges = {{ |
| 113 | { Math::MakeVec( f1, f0, f0, -f1) }, // x = +w | 106 | {Math::MakeVec(f1, f0, f0, -f1)}, // x = +w |
| 114 | { Math::MakeVec(-f1, f0, f0, -f1) }, // x = -w | 107 | {Math::MakeVec(-f1, f0, f0, -f1)}, // x = -w |
| 115 | { Math::MakeVec( f0, f1, f0, -f1) }, // y = +w | 108 | {Math::MakeVec(f0, f1, f0, -f1)}, // y = +w |
| 116 | { Math::MakeVec( f0, -f1, f0, -f1) }, // y = -w | 109 | {Math::MakeVec(f0, -f1, f0, -f1)}, // y = -w |
| 117 | { Math::MakeVec( f0, f0, f1, f0) }, // z = 0 | 110 | {Math::MakeVec(f0, f0, f1, f0)}, // z = 0 |
| 118 | { Math::MakeVec( f0, f0, -f1, -f1) }, // z = -w | 111 | {Math::MakeVec(f0, f0, -f1, -f1)}, // z = -w |
| 119 | { Math::MakeVec( f0, f0, f0, -f1), Math::Vec4<float24>(f0, f0, f0, EPSILON) }, // w = EPSILON | 112 | {Math::MakeVec(f0, f0, f0, -f1), Math::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON |
| 120 | }}; | 113 | }}; |
| 121 | 114 | ||
| 122 | // TODO: If one vertex lies outside one of the depth clipping planes, some platforms (e.g. Wii) | 115 | // TODO: If one vertex lies outside one of the depth clipping planes, some platforms (e.g. Wii) |
| @@ -154,10 +147,10 @@ void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const Outpu | |||
| 154 | InitScreenCoordinates((*output_list)[0]); | 147 | InitScreenCoordinates((*output_list)[0]); |
| 155 | InitScreenCoordinates((*output_list)[1]); | 148 | InitScreenCoordinates((*output_list)[1]); |
| 156 | 149 | ||
| 157 | for (size_t i = 0; i < output_list->size() - 2; i ++) { | 150 | for (size_t i = 0; i < output_list->size() - 2; i++) { |
| 158 | OutputVertex& vtx0 = (*output_list)[0]; | 151 | OutputVertex& vtx0 = (*output_list)[0]; |
| 159 | OutputVertex& vtx1 = (*output_list)[i+1]; | 152 | OutputVertex& vtx1 = (*output_list)[i + 1]; |
| 160 | OutputVertex& vtx2 = (*output_list)[i+2]; | 153 | OutputVertex& vtx2 = (*output_list)[i + 2]; |
| 161 | 154 | ||
| 162 | InitScreenCoordinates(vtx2); | 155 | InitScreenCoordinates(vtx2); |
| 163 | 156 | ||
| @@ -165,19 +158,20 @@ void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const Outpu | |||
| 165 | "Triangle %lu/%lu at position (%.3f, %.3f, %.3f, %.3f), " | 158 | "Triangle %lu/%lu at position (%.3f, %.3f, %.3f, %.3f), " |
| 166 | "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and " | 159 | "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and " |
| 167 | "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)", | 160 | "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)", |
| 168 | i + 1, output_list->size() - 2, | 161 | i + 1, output_list->size() - 2, vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), |
| 169 | vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(), | 162 | vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(), vtx1.pos.x.ToFloat32(), |
| 170 | vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(), | 163 | vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(), |
| 171 | vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(), | 164 | vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), |
| 172 | vtx0.screenpos.x.ToFloat32(), vtx0.screenpos.y.ToFloat32(), vtx0.screenpos.z.ToFloat32(), | 165 | vtx2.pos.w.ToFloat32(), vtx0.screenpos.x.ToFloat32(), |
| 173 | vtx1.screenpos.x.ToFloat32(), vtx1.screenpos.y.ToFloat32(), vtx1.screenpos.z.ToFloat32(), | 166 | vtx0.screenpos.y.ToFloat32(), vtx0.screenpos.z.ToFloat32(), |
| 174 | vtx2.screenpos.x.ToFloat32(), vtx2.screenpos.y.ToFloat32(), vtx2.screenpos.z.ToFloat32()); | 167 | vtx1.screenpos.x.ToFloat32(), vtx1.screenpos.y.ToFloat32(), |
| 168 | vtx1.screenpos.z.ToFloat32(), vtx2.screenpos.x.ToFloat32(), | ||
| 169 | vtx2.screenpos.y.ToFloat32(), vtx2.screenpos.z.ToFloat32()); | ||
| 175 | 170 | ||
| 176 | Rasterizer::ProcessTriangle(vtx0, vtx1, vtx2); | 171 | Rasterizer::ProcessTriangle(vtx0, vtx1, vtx2); |
| 177 | } | 172 | } |
| 178 | } | 173 | } |
| 179 | 174 | ||
| 180 | |||
| 181 | } // namespace | 175 | } // namespace |
| 182 | 176 | ||
| 183 | } // namespace | 177 | } // namespace |