aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-07-13 23:09:42 +0200
committerStapleButter <thetotalworm@gmail.com>2017-07-13 23:09:42 +0200
commita1401e724c73dcbcc5c9a60c010eebd405df5848 (patch)
treeca59b4032bd103e39443df29a2dee3adc893c8f5 /src
parent800540b710eaa0db23c42d603d844c809885e1a5 (diff)
* actually fix linear interpolation when y0>y1
* change the backfacing attribute bit, so that it doesn't mess with edgemarking
Diffstat (limited to 'src')
-rw-r--r--src/GPU3D.cpp5
-rw-r--r--src/GPU3D_Soft.cpp33
2 files changed, 22 insertions, 16 deletions
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 71a6711..f4de0c1 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -849,7 +849,7 @@ void SubmitPolygon()
}
u32 w = (u32)vtx->Position[3];
- while (w >> wsize)
+ while ((w >> wsize) && (wsize < 32))
wsize += 4;
}
@@ -1264,6 +1264,9 @@ void ExecuteCommand()
if (ExecParamCount >= CmdNumParams[entry.Command])
{
+ /*printf("0x%02X, ", entry.Command);
+ for (int k = 0; k < ExecParamCount; k++) printf("0x%08X, ", ExecParams[k]);
+ printf("\n");*/
CycleCount += CmdNumCycles[entry.Command];
ExecParamCount = 0;
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index b377b73..9e0ccdb 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -48,9 +48,9 @@ u32 AttrBuffer[BufferSize * 2];
// bit0-3: edge flags (left/right/top/bottom)
// bit8-12: antialiasing alpha
// bit15: fog enable
+// bit23: backfacing flag
// bit24-29: polygon ID
// bit30: translucent flag
-// bit31: backfacing flag
u8 StencilBuffer[256*2];
bool PrevIsShadowMask;
@@ -181,6 +181,9 @@ public:
this->x = x;
if (xdiff != 0 && wdiff != 0)
{
+ // TODO: hardware tests show that this method is too precise
+ // I haven't yet figured out what the hardware does, though
+
s64 num = ((s64)x << (shift + 40)) / w1factor;
s64 denw0 = ((s64)(xdiff-x) << 40) / w0factor;
s64 denw1 = num >> shift;
@@ -197,24 +200,24 @@ public:
s32 Interpolate(s32 y0, s32 y1)
{
- if (xdiff == 0) return y0;
+ if (xdiff == 0 || y0 == y1) return y0;
- s32 ybase, ydiff;
- if (y1 < y0)
+ if (wdiff != 0)
{
- ybase = y0;
- ydiff = y1 - y0 - 1;
+ // perspective-correct approx. interpolation
+ if (y0 < y1)
+ return y0 + (((y1-y0) * yfactor) >> shift);
+ else
+ return y1 + (((y0-y1) * ((1<<shift)-yfactor)) >> shift);
}
else
{
- ybase = y0;
- ydiff = y1 - y0;
+ // linear interpolation
+ if (y0 < y1)
+ return y0 + (((y1-y0) * x) / xdiff);
+ else
+ return y1 + (((y0-y1) * (xdiff-x)) / xdiff);
}
-
- if (wdiff != 0)
- return ybase + ((ydiff * yfactor) >> shift);
- else
- return ybase + ((ydiff * x) / xdiff);
}
s32 InterpolateZ(s32 z0, s32 z1, bool wbuffer)
@@ -703,7 +706,7 @@ bool DepthTest_LessThan(s32 dstz, s32 z, u32 dstattr)
bool DepthTest_LessThan_FrontFacing(s32 dstz, s32 z, u32 dstattr)
{
- if ((dstattr >> 30) == 0x2) // opaque, back facing
+ if ((dstattr & 0x40800000) == 0x00800000) // opaque, back facing
{
if (z <= dstz)
return true;
@@ -967,7 +970,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
Polygon* polygon = rp->PolyData;
u32 polyattr = (polygon->Attr & 0x3F008000);
- if (!polygon->FacingView) polyattr |= (1<<31);
+ if (!polygon->FacingView) polyattr |= (1<<23);
u32 polyalpha = (polygon->Attr >> 16) & 0x1F;
bool wireframe = (polyalpha == 0);