From a090b5853fedede163f18bd16211769630f80c90 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 10 May 2015 14:17:20 -0700 Subject: [PATCH 1/3] Process UV rotation even in full transform. --- GPU/Common/SoftwareTransformCommon.cpp | 47 ++++++++++++++++++-------- Windows/GEDebugger/VertexPreview.cpp | 4 +-- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index c69adabed1..b21b37ed76 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -58,18 +58,24 @@ static void SwapUVs(TransformedVertex &a, TransformedVertex &b) { // to to or // 1 0 0 1 1 2 3 0 +// Note: 0 is BR and 2 is TL. -// See comment below where this was called before. -/* -static void RotateUV(TransformedVertex v[4]) { - float x1 = v[2].x; - float x2 = v[0].x; - float y1 = v[2].y; - float y2 = v[0].y; +static void RotateUV(TransformedVertex v[4], float flippedMatrix[16]) { + // Transform these two coordinates to figure out whether they're flipped or not. + Vec4f tl; + Vec3ByMatrix44(tl.AsArray(), v[2].pos, flippedMatrix); + + Vec4f br; + Vec3ByMatrix44(br.AsArray(), v[0].pos, flippedMatrix); + + float x1 = tl.x / tl.w; + float x2 = br.x / br.w; + float y1 = tl.y / tl.w; + float y2 = br.y / br.w; if ((x1 < x2 && y1 < y2) || (x1 > x2 && y1 > y2)) SwapUVs(v[1], v[3]); -}*/ +} static void RotateUVThrough(TransformedVertex v[4]) { float x1 = v[2].x; @@ -476,6 +482,22 @@ void SoftwareTransform( numTrans = vertexCount; drawIndexed = true; } else { + float flippedMatrix[16]; + if (!throughmode) { + memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float)); + + const bool invertedY = gstate_c.vpHeight < 0; + if (invertedY) { + flippedMatrix[5] = -flippedMatrix[5]; + flippedMatrix[13] = -flippedMatrix[13]; + } + const bool invertedX = gstate_c.vpWidth < 0; + if (invertedX) { + flippedMatrix[0] = -flippedMatrix[0]; + flippedMatrix[12] = -flippedMatrix[12]; + } + } + //rectangles always need 2 vertices, disregard the last one if there's an odd number vertexCount = vertexCount & ~1; numTrans = 0; @@ -515,13 +537,8 @@ void SoftwareTransform( // That's the four corners. Now process UV rotation. if (throughmode) RotateUVThrough(trans); - - // Apparently, non-through RotateUV just breaks things. - // If we find a game where it helps, we'll just have to figure out how they differ. - // Possibly, it has something to do with flipped viewport Y axis, which a few games use. - // One game might be one of the Metal Gear ones, can't find the issue right now though. - // else - // RotateUV(trans); + else + RotateUV(trans, flippedMatrix); // Triangle: BR-TR-TL indsOut[0] = i * 2 + 0; diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index 1c18fd79f5..b76d108169 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -125,8 +125,8 @@ static void ExpandRectangles(std::vector &vertices, std::vector< vert[3].u = orig_tl.u; // That's the four corners. Now process UV rotation. - if (throughMode) - RotateUVThrough(vert); + // This is the same for through and non-through, since it's already transformed. + RotateUVThrough(vert); // Build the two 3 point triangles from our 4 coordinates. *ind++ = v + 0; From ea36554c6a0576e973973d2a6d381fa60f0f3d9d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 10 May 2015 14:37:14 -0700 Subject: [PATCH 2/3] software: Examine v0/v1 for uv rotation. If we determine tl/br heuristically, it can never rotate correctly. Anyway, this still is not rotating correctly... --- GPU/Software/Clipper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index 522ced9755..c1d6c1b3b8 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -125,7 +125,7 @@ static inline int CalcClipMask(const ClipCoords& v) } \ } -static void RotateUVThrough(VertexData &tl, VertexData &tr, VertexData &bl, VertexData &br) { +static void RotateUVThrough(const VertexData &tl, const VertexData &br, VertexData &tr, VertexData &bl) { const fixed16 x1 = tl.screenpos.x; const fixed16 x2 = br.screenpos.x; const fixed16 y1 = tl.screenpos.y; @@ -211,7 +211,7 @@ void ProcessRect(const VertexData& v0, const VertexData& v1) bottomright = &buf[i]; } - RotateUVThrough(*topleft, *topright, *bottomleft, *bottomright); + RotateUVThrough(v0, v1, *topright, *bottomleft); // Four triangles to do backfaces as well. Two of them will get backface culled. Rasterizer::DrawTriangle(*topleft, *topright, *bottomright); From b782165b6aa587d038bfd0e372937fb9599499f2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 10 May 2015 14:39:38 -0700 Subject: [PATCH 3/3] Avoid some division. --- GPU/Common/SoftwareTransformCommon.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index b21b37ed76..ebbbfac279 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -68,10 +68,12 @@ static void RotateUV(TransformedVertex v[4], float flippedMatrix[16]) { Vec4f br; Vec3ByMatrix44(br.AsArray(), v[0].pos, flippedMatrix); - float x1 = tl.x / tl.w; - float x2 = br.x / br.w; - float y1 = tl.y / tl.w; - float y2 = br.y / br.w; + const float invtlw = 1.0f / tl.w; + const float invbrw = 1.0f / br.w; + const float x1 = tl.x * invtlw; + const float x2 = br.x * invbrw; + const float y1 = tl.y * invtlw; + const float y2 = br.y * invbrw; if ((x1 < x2 && y1 < y2) || (x1 > x2 && y1 > y2)) SwapUVs(v[1], v[3]);