diff options
author | Tony Wasserka <NeoBrainX@gmail.com> | 2014-12-13 21:39:42 +0100 |
---|---|---|
committer | Tony Wasserka <NeoBrainX@gmail.com> | 2014-12-31 16:32:55 +0100 |
commit | 0f494240228e24e21c88bf9f3178aaa68db4fb45 (patch) | |
tree | b23513ade2000339485bf9585a988aece11c1019 /src/video_core/rasterizer.cpp | |
parent | 3b78af904e5a4f959ab206a207bd26441886c9a8 (diff) |
Pica/Rasterizer: Implement backface culling.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r-- | src/video_core/rasterizer.cpp | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 08b649fb6..9148745dc 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -82,10 +82,31 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) { return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; }; + static auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, + const Math::Vec2<Fix12P4>& vtx2, + const Math::Vec2<Fix12P4>& vtx3) { + const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); + const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); + // TODO: There is a very small chance this will overflow for sizeof(int) == 4 + return Math::Cross(vec1, vec2).z; + }; + Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos), ScreenToRasterizerCoordinates(v1.screenpos), ScreenToRasterizerCoordinates(v2.screenpos) }; + if (registers.cull_mode == Regs::CullMode::KeepClockWise) { + // Reverse vertex order and use the CCW code path. + std::swap(vtxpos[1], vtxpos[2]); + } + + if (registers.cull_mode != Regs::CullMode::KeepAll) { + // Cull away triangles which are wound clockwise. + // TODO: A check for degenerate triangles ("== 0") should be considered for CullMode::KeepAll + if (orient2d(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) + return; + } + // TODO: Proper scissor rect test! u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); @@ -128,15 +149,6 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, for (u16 x = min_x; x < max_x; x += 0x10) { // Calculate the barycentric coordinates w0, w1 and w2 - auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, - const Math::Vec2<Fix12P4>& vtx2, - const Math::Vec2<Fix12P4>& vtx3) { - const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); - const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); - // TODO: There is a very small chance this will overflow for sizeof(int) == 4 - return Math::Cross(vec1, vec2).z; - }; - int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); int w1 = bias1 + orient2d(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); int w2 = bias2 + orient2d(vtxpos[0].xy(), vtxpos[1].xy(), {x, y}); |