aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaklyy <102590697+Jaklyy@users.noreply.github.com>2023-08-27 07:28:44 -0400
committerGitHub <noreply@github.com>2023-08-27 13:28:44 +0200
commitdc8efb62b8895b88bad95d2291af402c80806f01 (patch)
tree2b0a396d9ed71bb3ccc8e597f082efa13d876fe9
parentd7369857c3884cc618c59e9bfde866431c4e1a92 (diff)
Fix aa being upside down on swapped y-major slopes (#1803)
* fix aa being upside down on swapped y-major slopes * further improvements to swapped aa in addition to fixing swapped y-major slope aa, now fixes: swapped x-major slope aa swapped vertical slope aa * use templates instead + style/comment tweaks should force the compiler to precompile if statements like i want it to do, instead of just hoping it does so on its own
-rw-r--r--src/GPU3D_Soft.cpp22
-rw-r--r--src/GPU3D_Soft.h42
2 files changed, 42 insertions, 22 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 1bd72a0..10ad1d6 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -753,8 +753,8 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp;
- rp->SlopeR.EdgeParams_YMajor(&l_edgelen, &l_edgecov);
- rp->SlopeL.EdgeParams_YMajor(&r_edgelen, &r_edgecov);
+ rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov);
+ rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov);
std::swap(xstart, xend);
std::swap(wl, wr);
@@ -771,8 +771,8 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp;
- rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov);
- rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov);
+ rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov);
+ rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
}
// color/texcoord attributes aren't needed for shadow masks
@@ -958,10 +958,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
// if the left and right edges are swapped, render backwards.
// on hardware, swapped edges seem to break edge length calculation,
- // causing X-major edges to be rendered wrong when
- // wireframe/edgemarking/antialiasing are used
- // it also causes bad antialiasing, but not sure what's going on (TODO)
- // most probable explanation is that such slopes are considered to be Y-major
+ // causing X-major edges to be rendered wrong when filled,
+ // and resulting in buggy looking anti-aliasing on X-major edges
if (xstart > xend)
{
@@ -973,8 +971,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp;
- rp->SlopeR.EdgeParams_YMajor(&l_edgelen, &l_edgecov);
- rp->SlopeL.EdgeParams_YMajor(&r_edgelen, &r_edgecov);
+ rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov);
+ rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov);
std::swap(xstart, xend);
std::swap(wl, wr);
@@ -991,8 +989,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp;
- rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov);
- rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov);
+ rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov);
+ rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
}
// interpolate attributes along Y
diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h
index d9a6028..9bbbb21 100644
--- a/src/GPU3D_Soft.h
+++ b/src/GPU3D_Soft.h
@@ -354,13 +354,19 @@ private:
else if (ret > xmax) ret = xmax;
return ret;
}
-
+
+ template<bool swapped>
void EdgeParams_XMajor(s32* length, s32* coverage)
{
- if (side ^ Negative)
- *length = (dx >> 18) - ((dx-Increment) >> 18);
- else
- *length = ((dx+Increment) >> 18) - (dx >> 18);
+ // only do length calc for right side when swapped as it's
+ // only needed for aa calcs, as actual line spans are broken
+ if constexpr (!swapped || side)
+ {
+ if (side ^ Negative)
+ *length = (dx >> 18) - ((dx-Increment) >> 18);
+ else
+ *length = ((dx+Increment) >> 18) - (dx >> 18);
+ }
// for X-major edges, we return the coverage
// for the first pixel, and the increment for
@@ -371,33 +377,49 @@ private:
s32 startcov = (((startx << 10) + 0x1FF) * ylen) / xlen;
*coverage = (1<<31) | ((startcov & 0x3FF) << 12) | (xcov_incr & 0x3FF);
+
+ if constexpr (swapped) *length = 1;
}
+ template<bool swapped>
void EdgeParams_YMajor(s32* length, s32* coverage)
{
*length = 1;
if (Increment == 0)
{
- *coverage = 31;
+ // for some reason vertical edges' aa values
+ // are inverted too when the edges are swapped
+ if constexpr (swapped)
+ *coverage = 0;
+ else
+ *coverage = 31;
}
else
{
s32 cov = ((dx >> 9) + (Increment >> 10)) >> 4;
if ((cov >> 5) != (dx >> 18)) cov = 31;
cov &= 0x1F;
- if (!(side ^ Negative)) cov = 0x1F - cov;
+ if constexpr (swapped)
+ {
+ if (side ^ Negative) cov = 0x1F - cov;
+ }
+ else
+ {
+ if (!(side ^ Negative)) cov = 0x1F - cov;
+ }
*coverage = cov;
}
}
-
+
+ template<bool swapped>
void EdgeParams(s32* length, s32* coverage)
{
if (XMajor)
- return EdgeParams_XMajor(length, coverage);
+ return EdgeParams_XMajor<swapped>(length, coverage);
else
- return EdgeParams_YMajor(length, coverage);
+ return EdgeParams_YMajor<swapped>(length, coverage);
}
s32 Increment;