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