diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 2f5664e2..fefd84d3 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -280,7 +280,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) @@ -313,21 +312,41 @@ private: dx += (y - y0) * Increment; + if (XMajor) + { + // used for calculating AA coverage + xcov_incr = (ylen << 10) / xlen; + + if (side ^ Negative) + { + dxold = dx; + // I dont think the first span can have a gap but i think its technically correct to do this calc anyway? + // could probably be removed as a minor optimization + dx &= ~0x1FF; + } + } + 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; + { + if (XMajor && (side ^ Negative)) // tl, br (right side start) & tr, bl (left side start) + { + // round dx; required to create gaps in lines like on hw + // increment using dxold to make the line not completely borked after rendering a gap + dx = (dxold & ~0x1FF) + Increment; + dxold += Increment; + } + else + dx += Increment; + y++; s32 x = XVal(); @@ -353,15 +372,18 @@ private: // 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); + if (side ^ Negative) // tr, bl (left side end) & tl br (right side end) + // dxold used here to avoid rounding the endpoint + *length = (dx >> 18) - (dxold - Increment >> 18); + else // tl, br (left side end) & tr, bl (right side end) + // dx rounded down to create gaps in lines like on hw + *length = ((dx & ~0x1FF) + Increment >> 18) - (dx >> 18); } // for X-major edges, we return the coverage // for the first pixel, and the increment for // further pixels on the same scanline + // TODO: check how coverage interacts with line gaps s32 startx = dx >> 18; if (Negative) startx = xlen - startx; if (side) startx = startx - *length + 1; @@ -421,7 +443,7 @@ private: private: s32 x0, xmin, xmax; s32 xlen, ylen; - s32 dx; + s32 dx, dxold; s32 y; s32 xcov_incr;