From 7ba7422ff843306c9cc02047e69ef8bfb7010db3 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Wed, 30 Aug 2023 19:18:03 -0400 Subject: [PATCH 1/4] improve line polygon check --- src/GPU3D.cpp | 69 +++++++++++++++++++++++++++++++--------------- src/GPU3D_Soft.cpp | 4 +-- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 049ae589..dcec7630 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -869,12 +869,47 @@ int ClipPolygon(GPU3D& gpu, Vertex* vertices, int nverts, int clipstart) return nverts; } -bool ClipCoordsEqual(Vertex* a, Vertex* b) +template +bool ClipCoordsEqual(Vertex a, Vertex b) { - return a->Position[0] == b->Position[0] && - a->Position[1] == b->Position[1] && - a->Position[2] == b->Position[2] && - a->Position[3] == b->Position[3]; + if constexpr (ogl) + return a.Position[0] == b.Position[0] && + a.Position[1] == b.Position[1] && + a.Position[2] == b.Position[2] && + a.Position[3] == b.Position[3]; + else + return a.FinalPosition[0] == b.FinalPosition[0] && + a.FinalPosition[1] == b.FinalPosition[1]; +} + +template +bool LineCheck(Vertex* vertices, int nverts) +{ + // todo: check for more lines (perfectly vertical, horizontal or diagonal) for opengl renderer? + if (nverts == 3) + { + if (ClipCoordsEqual(vertices[0], vertices[1]) || + ClipCoordsEqual(vertices[0], vertices[2]) || + ClipCoordsEqual(vertices[1], vertices[2])) + { + return true; + } + } + else if (nverts == 4) + { + int vertsequal = 0; + + for (int a = 0; a < 3; a++) + for (int b = a+1; b < 4; b++) + if (ClipCoordsEqual(vertices[a], vertices[b])) + { + vertsequal++; + + if (vertsequal == 2) + return true; + } + } + return false; } void GPU3D::SubmitPolygon() noexcept @@ -992,21 +1027,7 @@ void GPU3D::SubmitPolygon() noexcept clippedvertices[i] = TempVertexBuffer[i]; // detect lines, for the OpenGL renderer - - int polytype = 0; - if (nverts == 3) - { - if (ClipCoordsEqual(&clippedvertices[0], &clippedvertices[1]) || - ClipCoordsEqual(&clippedvertices[0], &clippedvertices[2]) || - ClipCoordsEqual(&clippedvertices[1], &clippedvertices[2])) - { - polytype = 1; - } - } - else if (nverts == 4) - { - // TODO - } + int polytype = (GPU3D::CurrentRenderer->Accelerated) ? LineCheck(clippedvertices, nverts) : 0; // clipping @@ -1153,8 +1174,6 @@ void GPU3D::SubmitPolygon() noexcept if (!poly->Translucent) NumOpaquePolygons++; - poly->Type = polytype; - if (LastStripPolygon && clipstart > 0) { if (nverts == lastpolyverts) @@ -1275,6 +1294,12 @@ void GPU3D::SubmitPolygon() noexcept poly->FinalZ[i] = z; poly->FinalW[i] = w; } + + // check for line polygons for the software renderer + // checkme: can a line polygon have more than 4 or less than 3 vertices? + polytype = (!GPU3D::CurrentRenderer->Accelerated) ? LineCheck(*poly->Vertices, nverts) : polytype; + + poly->Type = polytype; if (PolygonMode >= 2) LastStripPolygon = poly; diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 03c6265e..0003c58b 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -786,7 +786,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); + || polygon->Type; r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } @@ -1028,7 +1028,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); + || polygon->Type; r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } From ea4293f40b687612710a77430d7ada931f2929c5 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:19:43 -0400 Subject: [PATCH 2/4] Revert "improve line polygon check" This reverts commit 3405ef165f2dd7ec940a0b23743a639f23852966. --- src/GPU3D.cpp | 69 +++++++++++++++------------------------------- src/GPU3D_Soft.cpp | 4 +-- 2 files changed, 24 insertions(+), 49 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index dcec7630..049ae589 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -869,47 +869,12 @@ int ClipPolygon(GPU3D& gpu, Vertex* vertices, int nverts, int clipstart) return nverts; } -template -bool ClipCoordsEqual(Vertex a, Vertex b) +bool ClipCoordsEqual(Vertex* a, Vertex* b) { - if constexpr (ogl) - return a.Position[0] == b.Position[0] && - a.Position[1] == b.Position[1] && - a.Position[2] == b.Position[2] && - a.Position[3] == b.Position[3]; - else - return a.FinalPosition[0] == b.FinalPosition[0] && - a.FinalPosition[1] == b.FinalPosition[1]; -} - -template -bool LineCheck(Vertex* vertices, int nverts) -{ - // todo: check for more lines (perfectly vertical, horizontal or diagonal) for opengl renderer? - if (nverts == 3) - { - if (ClipCoordsEqual(vertices[0], vertices[1]) || - ClipCoordsEqual(vertices[0], vertices[2]) || - ClipCoordsEqual(vertices[1], vertices[2])) - { - return true; - } - } - else if (nverts == 4) - { - int vertsequal = 0; - - for (int a = 0; a < 3; a++) - for (int b = a+1; b < 4; b++) - if (ClipCoordsEqual(vertices[a], vertices[b])) - { - vertsequal++; - - if (vertsequal == 2) - return true; - } - } - return false; + return a->Position[0] == b->Position[0] && + a->Position[1] == b->Position[1] && + a->Position[2] == b->Position[2] && + a->Position[3] == b->Position[3]; } void GPU3D::SubmitPolygon() noexcept @@ -1027,7 +992,21 @@ void GPU3D::SubmitPolygon() noexcept clippedvertices[i] = TempVertexBuffer[i]; // detect lines, for the OpenGL renderer - int polytype = (GPU3D::CurrentRenderer->Accelerated) ? LineCheck(clippedvertices, nverts) : 0; + + int polytype = 0; + if (nverts == 3) + { + if (ClipCoordsEqual(&clippedvertices[0], &clippedvertices[1]) || + ClipCoordsEqual(&clippedvertices[0], &clippedvertices[2]) || + ClipCoordsEqual(&clippedvertices[1], &clippedvertices[2])) + { + polytype = 1; + } + } + else if (nverts == 4) + { + // TODO + } // clipping @@ -1174,6 +1153,8 @@ void GPU3D::SubmitPolygon() noexcept if (!poly->Translucent) NumOpaquePolygons++; + poly->Type = polytype; + if (LastStripPolygon && clipstart > 0) { if (nverts == lastpolyverts) @@ -1294,12 +1275,6 @@ void GPU3D::SubmitPolygon() noexcept poly->FinalZ[i] = z; poly->FinalW[i] = w; } - - // check for line polygons for the software renderer - // checkme: can a line polygon have more than 4 or less than 3 vertices? - polytype = (!GPU3D::CurrentRenderer->Accelerated) ? LineCheck(*poly->Vertices, nverts) : polytype; - - poly->Type = polytype; if (PolygonMode >= 2) LastStripPolygon = poly; diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 0003c58b..03c6265e 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -786,7 +786,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || polygon->Type; + || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } @@ -1028,7 +1028,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || polygon->Type; + || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } From c33cd1f35f2168eedc8c5eec8e3175d0c36bd971 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:03:12 -0400 Subject: [PATCH 3/4] Check for line polygons using cur/next vl/vr fixes a few cases that weren't handled properly --- src/GPU3D_Soft.cpp | 45 ++++++++++++++++++++++++++++++++++++++------- src/GPU3D_Soft.h | 2 ++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 03c6265e..e0840a65 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -565,6 +565,20 @@ void SoftRenderer::PlotTranslucentPixel(u32 pixeladdr, u32 color, u32 z, u32 pol AttrBuffer[pixeladdr] = attr; } +void SoftRenderer::CheckForLine(RendererPolygon* rp) +{ + Polygon* polygon = rp->PolyData; + + // check for line polygons + if (polygon->Vertices[rp->CurVL]->FinalPosition[0] == polygon->Vertices[rp->CurVR]->FinalPosition[0] + && polygon->Vertices[rp->CurVL]->FinalPosition[1] == polygon->Vertices[rp->CurVR]->FinalPosition[1] + && polygon->Vertices[rp->NextVL]->FinalPosition[0] == polygon->Vertices[rp->NextVR]->FinalPosition[0] + && polygon->Vertices[rp->NextVL]->FinalPosition[1] == polygon->Vertices[rp->NextVR]->FinalPosition[1]) + rp->Line = true; + else + rp->Line = false; +} + void SoftRenderer::SetupPolygonLeftEdge(SoftRenderer::RendererPolygon* rp, s32 y) { Polygon* polygon = rp->PolyData; @@ -669,6 +683,7 @@ void SoftRenderer::SetupPolygon(SoftRenderer::RendererPolygon* rp, Polygon* poly { SetupPolygonLeftEdge(rp, ytop); SetupPolygonRightEdge(rp, ytop); + CheckForLine(rp); } } @@ -697,15 +712,23 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) if (polygon->YTop != polygon->YBottom) { - if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom) + bool updateLeftSlope = (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom); + bool updateRightSlope = (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom); + + if (updateLeftSlope) { SetupPolygonLeftEdge(rp, y); } - if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom) + if (updateRightSlope) { SetupPolygonRightEdge(rp, y); } + + if (updateLeftSlope || updateRightSlope) + { + CheckForLine(rp); + } } Vertex *vlcur, *vlnext, *vrcur, *vrnext; @@ -786,7 +809,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); + || rp->Line; r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } @@ -922,15 +945,23 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y) if (polygon->YTop != polygon->YBottom) { - if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom) + bool updateLeftSlope = (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom); + bool updateRightSlope = (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom); + + if (updateLeftSlope) { SetupPolygonLeftEdge(rp, y); } - if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom) + if (updateRightSlope) { SetupPolygonRightEdge(rp, y); } + + if (updateLeftSlope || updateRightSlope) + { + CheckForLine(rp); + } } Vertex *vlcur, *vlnext, *vrcur, *vrnext; @@ -983,7 +1014,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y) // * the bottom-most pixel of negative x-major slopes are filled if they are next to a flat bottom edge // edges are always filled if antialiasing/edgemarking are enabled, // if the pixels are translucent and alpha blending is enabled, or if the polygon is wireframe - // checkme: do swapped line polygons exist? + // checkme: do swapped line polygons exist? if they do then they likely should also be filled if ((GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (GPU.GPU3D.RenderDispCnt & (1<<3))) || wireframe) { l_filledge = true; @@ -1028,7 +1059,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y) { l_filledge = ((rp->SlopeL.Negative || !rp->SlopeL.XMajor) || (y == polygon->YBottom-1) && rp->SlopeL.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0])) - || (rp->SlopeL.Increment == rp->SlopeR.Increment) && (xstart+l_edgelen == xend+1); + || rp->Line; r_filledge = (!rp->SlopeR.Negative && rp->SlopeR.XMajor) || (rp->SlopeR.Increment==0) || (y == polygon->YBottom-1) && rp->SlopeR.XMajor && (vlnext->FinalPosition[0] != vrnext->FinalPosition[0]); } diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 2f5664e2..d1d7f89c 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -449,6 +449,7 @@ private: s32 XL, XR; u32 CurVL, CurVR; u32 NextVL, NextVR; + bool Line; }; @@ -457,6 +458,7 @@ private: void TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha); u32 RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t); void PlotTranslucentPixel(u32 pixeladdr, u32 color, u32 z, u32 polyattr, u32 shadow); + void CheckForLine(RendererPolygon* rp); void SetupPolygonLeftEdge(RendererPolygon* rp, s32 y); void SetupPolygonRightEdge(RendererPolygon* rp, s32 y); void SetupPolygon(RendererPolygon* rp, Polygon* polygon); From 341f40306152fac754ec74874ab5b3b1f667cb9b Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Tue, 26 Dec 2023 13:50:15 -0500 Subject: [PATCH 4/4] fix build (sorta) --- src/GPU3D_Soft.cpp | 2 +- src/GPU3D_Soft.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 458a4877..90eac90f 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -567,7 +567,7 @@ void SoftRenderer::PlotTranslucentPixel(const GPU3D& gpu3d, u32 pixeladdr, u32 c AttrBuffer[pixeladdr] = attr; } -void SoftRenderer::CheckForLine(RendererPolygon* rp) +void SoftRenderer::CheckForLine(RendererPolygon* rp) const { Polygon* polygon = rp->PolyData; diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 1c4d7735..23661580 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -457,7 +457,7 @@ private: void TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha) const; u32 RenderPixel(const GPU& gpu, const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t) const; void PlotTranslucentPixel(const GPU3D& gpu3d, u32 pixeladdr, u32 color, u32 z, u32 polyattr, u32 shadow); - void CheckForLine(RendererPolygon* rp); + void CheckForLine(RendererPolygon* rp) const; void SetupPolygonLeftEdge(RendererPolygon* rp, s32 y) const; void SetupPolygonRightEdge(RendererPolygon* rp, s32 y) const; void SetupPolygon(RendererPolygon* rp, Polygon* polygon) const;