mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-03-06 21:00:31 +01:00
Merge c2abc1050c
into e8265df4bd
This commit is contained in:
commit
40d621fd2d
2 changed files with 50 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue