1
0
Fork 0
mirror of https://github.com/melonDS-emu/melonDS.git synced 2025-03-06 21:00:31 +01:00
This commit is contained in:
Jakly 2025-02-16 03:39:27 +00:00 committed by GitHub
commit 40d621fd2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 57 deletions

View file

@ -757,6 +757,12 @@ void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon*
s32 zl = rp->SlopeL.Interp.InterpolateZ(polygon->FinalZ[rp->CurVL], polygon->FinalZ[rp->NextVL], polygon->WBuffer);
s32 zr = rp->SlopeR.Interp.InterpolateZ(polygon->FinalZ[rp->CurVR], polygon->FinalZ[rp->NextVR], polygon->WBuffer);
rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov);
rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov);
if (rp->SlopeL.XMajor && rp->SlopeL.Negative) xstart -= l_edgelen;
if (rp->SlopeR.XMajor && !rp->SlopeR.Negative) xend += r_edgelen;
// right vertical edges are pushed 1px to the left as long as either:
// the left edge slope is not 0, or the span is not 0 pixels wide, and it is not at the leftmost pixel of the screen
@ -773,11 +779,14 @@ void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon*
interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp;
rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov);
rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov);
std::swap(xstart, xend);
l_edgelen = 1;
r_edgelen = 1;
// ignore fixing coverage, shadow masks don't use it
std::swap(wl, wr);
std::swap(zl, zr);
@ -806,9 +815,6 @@ void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon*
interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp;
rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov);
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
// CHECKME: edge fill rules for unswapped opaque shadow mask polygons
if ((gpu3d.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu3d.RenderDispCnt & (1<<3))) || wireframe)
{
@ -982,6 +988,12 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
s32 zl = rp->SlopeL.Interp.InterpolateZ(polygon->FinalZ[rp->CurVL], polygon->FinalZ[rp->NextVL], polygon->WBuffer);
s32 zr = rp->SlopeR.Interp.InterpolateZ(polygon->FinalZ[rp->CurVR], polygon->FinalZ[rp->NextVR], polygon->WBuffer);
rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov);
rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov);
if (rp->SlopeL.XMajor && rp->SlopeL.Negative) xstart -= l_edgelen;
if (rp->SlopeR.XMajor && !rp->SlopeR.Negative) xend += r_edgelen;
// right vertical edges are pushed 1px to the left as long as either:
// the left edge slope is not 0, or the span is not 0 pixels wide, and it is not at the leftmost pixel of the screen
@ -1003,10 +1015,17 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp;
rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov);
rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov);
std::swap(xstart, xend);
l_edgelen = 1;
r_edgelen = 1;
std::swap(l_edgecov, r_edgecov);
// yes this breaks vertical slopes, blame hw
if (!rp->SlopeR.XMajor) l_edgecov = 31-l_edgecov;
if (!rp->SlopeL.XMajor) r_edgecov = 31-r_edgecov;
std::swap(wl, wr);
std::swap(zl, zr);
@ -1041,9 +1060,6 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp;
rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov);
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
// edge fill rules for unswapped opaque edges:
// * right edge is filled if slope > 1
// * left edge is filled if slope <= 1

View file

@ -282,7 +282,6 @@ private:
// slope increment has a 18-bit fractional part
// note: for some reason, x/y isn't calculated directly,
// instead, 1/y is calculated and then multiplied by x
// TODO: this is still not perfect (see for example x=169 y=33)
if (ylen == 0)
Increment = 0;
else if (ylen == xlen && xlen != 1)
@ -296,11 +295,11 @@ private:
XMajor = (Increment > 0x40000);
if constexpr (side)
if (side)
{
// right
if (XMajor) dx = Negative ? (0x20000 + 0x40000) : (Increment - 0x20000);
if (XMajor) dx = Negative ? (0x20000 + 0x40000) : -0x20000;
else if (Increment != 0) dx = Negative ? 0x40000 : 0;
else dx = 0;
}
@ -308,28 +307,29 @@ private:
{
// left
if (XMajor) dx = Negative ? ((Increment - 0x20000) + 0x40000) : 0x20000;
if (XMajor) dx = 0x20000;
else if (Increment != 0) dx = Negative ? 0x40000 : 0;
else dx = 0;
}
dx += (y - y0) * Increment;
// used for calculating AA coverage
if (XMajor) xcov_incr = (ylen << 10) / xlen;
s32 x = XVal();
int interpoffset = (Increment >= 0x40000) && (side ^ Negative);
Interp.Setup(y0-interpoffset, y1-interpoffset, w0, w1);
Interp.SetX(y);
// used for calculating AA coverage
if (XMajor) xcov_incr = (ylen << 10) / xlen;
return x;
}
constexpr s32 Step()
{
{
dx += Increment;
y++;
s32 x = XVal();
@ -343,76 +343,53 @@ private:
if (Negative) ret = x0 - (dx >> 18);
else ret = x0 + (dx >> 18);
if (ret < xmin) ret = xmin;
else if (ret > xmax) ret = xmax;
return ret;
}
template<bool swapped>
constexpr void EdgeParams_XMajor(s32* length, s32* coverage) const
{
// 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);
}
// credit to StrikerX3 for their efforts researching the strange rounding behavior of the "length" calculation
*length = (dx & (0x1FF << 9)) + Increment >> 18;
// for X-major edges, we return the coverage
// for the first pixel, and the increment for
// further pixels on the same scanline
s32 startx = dx >> 18;
// TODO: check how coverage interacts with line gaps, I think it's correct though?
s32 startx = dx;
if (side ^ Negative) startx += Increment;
startx >>= 18;
//s32 startcov = (startx * ylen) /9 xlen;
if (Negative) startx = xlen - startx;
if (side) startx = startx - *length + 1;
s32 startcov = (((startx << 10) + 0x1FF) * ylen) / xlen;
*coverage = (1<<31) | ((startcov & 0x3FF) << 12) | (xcov_incr & 0x3FF);
if constexpr (swapped) *length = 1;
}
template<bool swapped>
constexpr void EdgeParams_YMajor(s32* length, s32* coverage) const
{
*length = 1;
if (Increment == 0)
{
// for some reason vertical edges' aa values
// are inverted too when the edges are swapped
if constexpr (swapped)
*coverage = 0;
else
*coverage = 31;
}
if (Increment == 0) *coverage = 31;
else
{
s32 cov = ((dx >> 9) + (Increment >> 10)) >> 4;
if ((cov >> 5) != (dx >> 18)) cov = 31;
cov &= 0x1F;
if constexpr (swapped)
{
if (side ^ Negative) cov = 0x1F - cov;
}
else
{
if (!(side ^ Negative)) cov = 0x1F - cov;
}
if (!(side ^ Negative)) cov = 0x1F - cov;
*coverage = cov;
}
}
template<bool swapped>
constexpr void EdgeParams(s32* length, s32* coverage) const
{
if (XMajor)
return EdgeParams_XMajor<swapped>(length, coverage);
return EdgeParams_XMajor(length, coverage);
else
return EdgeParams_YMajor<swapped>(length, coverage);
return EdgeParams_YMajor(length, coverage);
}
s32 Increment;