aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-07-15 15:24:25 +0200
committerStapleButter <thetotalworm@gmail.com>2017-07-15 15:24:25 +0200
commit6b6389fbb4df03bf6e180b6f0c1bc55fc5e99b9c (patch)
tree87740e1908332fa47ee1a8c1cbe80d50a7bd8324 /src
parentd9786038527394e0a2912d9b8e091e039efd0833 (diff)
separate polygonID attributes for opaque and translucent pixels.
rendering translucent pixels preserves opaque polygonID and edge flags for edgemarking. fixes edgemarking malfunctions, like #80 or black dots in Pokémon games
Diffstat (limited to 'src')
-rw-r--r--src/GPU3D_Soft.cpp122
1 files changed, 84 insertions, 38 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 89f191f..01653e9 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -46,11 +46,12 @@ u32 AttrBuffer[BufferSize * 2];
// attribute buffer:
// bit0-3: edge flags (left/right/top/bottom)
+// bit4: backfacing flag
// bit8-12: antialiasing alpha
// bit15: fog enable
-// bit23: backfacing flag
-// bit24-29: polygon ID
-// bit30: translucent flag
+// bit16-21: polygon ID for translucent pixels
+// bit22: translucent flag
+// bit24-29: polygon ID for opaque pixels
u8 StencilBuffer[256*2];
bool PrevIsShadowMask;
@@ -706,7 +707,7 @@ bool DepthTest_LessThan(s32 dstz, s32 z, u32 dstattr)
bool DepthTest_LessThan_FrontFacing(s32 dstz, s32 z, u32 dstattr)
{
- if ((dstattr & 0x40800000) == 0x00800000) // opaque, back facing
+ if ((dstattr & 0x00400010) == 0x00000010) // opaque, back facing
{
if (z <= dstz)
return true;
@@ -970,7 +971,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
Polygon* polygon = rp->PolyData;
u32 polyattr = (polygon->Attr & 0x3F008000);
- if (!polygon->FacingView) polyattr |= (1<<23);
+ if (!polygon->FacingView) polyattr |= (1<<4);
u32 polyalpha = (polygon->Attr >> 16) & 0x1F;
bool wireframe = (polyalpha == 0);
@@ -1111,7 +1112,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
for (; x < xlimit; x++)
{
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
- u32 attr = polyattr;
+ u32 attr;
// check stencil buffer for shadows
if (polygon->IsShadow)
@@ -1153,7 +1154,8 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (!(dstattr & 0x3)) continue;
pixeladdr += BufferSize;
- if (!fnDepthTest(DepthBuffer[pixeladdr], z, AttrBuffer[pixeladdr]))
+ dstattr = AttrBuffer[pixeladdr];
+ if (!fnDepthTest(DepthBuffer[pixeladdr], z, dstattr))
continue;
}
@@ -1172,7 +1174,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (alpha == 31)
{
- attr |= edge;
+ attr = polyattr | edge;
if (RenderDispCnt & (1<<4))
{
@@ -1212,12 +1214,28 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
}
else
{
- attr |= (1<<30);
- if (polygon->IsShadow) dstattr |= (1<<30);
+ attr = (polyattr & 0xFFF0) | ((polyattr >> 8) & 0xFF0000) | (1<<22) | (dstattr & 0xFF00000F);
- // skip if polygon IDs are equal
- if ((dstattr & 0x7F000000) == (attr & 0x7F000000))
- continue;
+ if (polygon->IsShadow)
+ {
+ // for shadows, opaque pixels are also checked
+ if (dstattr & (1<<22))
+ {
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
+ else
+ {
+ if ((dstattr & 0x3F000000) == (polyattr & 0x3F000000))
+ continue;
+ }
+ }
+ else
+ {
+ // skip if polygon IDs are equal
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
// fog flag
if (!(dstattr & (1<<15)))
@@ -1240,7 +1258,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
else for (; x < xlimit; x++)
{
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
- u32 attr = polyattr;
+ u32 attr;
// check stencil buffer for shadows
if (polygon->IsShadow)
@@ -1272,7 +1290,8 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (!(dstattr & 0x3)) continue;
pixeladdr += BufferSize;
- if (!fnDepthTest(DepthBuffer[pixeladdr], z, AttrBuffer[pixeladdr]))
+ dstattr = AttrBuffer[pixeladdr];
+ if (!fnDepthTest(DepthBuffer[pixeladdr], z, dstattr))
continue;
}
@@ -1291,23 +1310,33 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (alpha == 31)
{
- attr |= edge;
+ attr = polyattr | edge;
DepthBuffer[pixeladdr] = z;
}
else
{
- u32 dstattr = AttrBuffer[pixeladdr];
- attr |= (1<<30);
- if (polygon->IsShadow) dstattr |= (1<<30);
-
- // skip if polygon IDs are equal
- // note: this only happens if the destination pixel was translucent
- // or always when drawing a shadow
- // (the GPU keeps track of which pixels are translucent, regardless of
- // the destination alpha)
- // TODO: they say that there are two separate polygon ID buffers. verify that.
- if ((dstattr & 0x7F000000) == (attr & 0x7F000000))
- continue;
+ attr = (polyattr & 0xFFF0) | ((polyattr >> 8) & 0xFF0000) | (1<<22) | (dstattr & 0xFF00000F);
+
+ if (polygon->IsShadow)
+ {
+ // for shadows, opaque pixels are also checked
+ if (dstattr & (1<<22))
+ {
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
+ else
+ {
+ if ((dstattr & 0x3F000000) == (polyattr & 0x3F000000))
+ continue;
+ }
+ }
+ else
+ {
+ // skip if polygon IDs are equal
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
// fog flag
if (!(dstattr & (1<<15)))
@@ -1329,7 +1358,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
for (; x < xlimit; x++)
{
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
- u32 attr = polyattr;
+ u32 attr;
// check stencil buffer for shadows
if (polygon->IsShadow)
@@ -1371,7 +1400,8 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (!(dstattr & 0x3)) continue;
pixeladdr += BufferSize;
- if (!fnDepthTest(DepthBuffer[pixeladdr], z, AttrBuffer[pixeladdr]))
+ dstattr = AttrBuffer[pixeladdr];
+ if (!fnDepthTest(DepthBuffer[pixeladdr], z, dstattr))
continue;
}
@@ -1390,7 +1420,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
if (alpha == 31)
{
- attr |= edge;
+ attr = polyattr | edge;
if (RenderDispCnt & (1<<4))
{
@@ -1430,12 +1460,28 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)
}
else
{
- attr |= (1<<30);
- if (polygon->IsShadow) dstattr |= (1<<30);
+ attr = (polyattr & 0xFFF0) | ((polyattr >> 8) & 0xFF0000) | (1<<22) | (dstattr & 0xFF00000F);
- // skip if polygon IDs are equal
- if ((dstattr & 0x7F000000) == (attr & 0x7F000000))
- continue;
+ if (polygon->IsShadow)
+ {
+ // for shadows, opaque pixels are also checked
+ if (dstattr & (1<<22))
+ {
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
+ else
+ {
+ if ((dstattr & 0x3F000000) == (polyattr & 0x3F000000))
+ continue;
+ }
+ }
+ else
+ {
+ // skip if polygon IDs are equal
+ if ((dstattr & 0x007F0000) == (attr & 0x007F0000))
+ continue;
+ }
// fog flag
if (!(dstattr & (1<<15)))
@@ -1486,7 +1532,7 @@ void ScanlineFinalPass(s32 y)
u32 attr = AttrBuffer[pixeladdr];
if (!(attr & 0xF)) continue;
- u32 polyid = attr >> 24;
+ u32 polyid = attr >> 24; // opaque polygon IDs are used for edgemarking
u32 z = DepthBuffer[pixeladdr];
if (((polyid != (AttrBuffer[pixeladdr-1] >> 24)) && (z < DepthBuffer[pixeladdr-1])) ||
@@ -1644,7 +1690,7 @@ void ScanlineFinalPass(s32 y)
void ClearBuffers()
{
u32 clearz = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
- u32 polyid = RenderClearAttr1 & 0x3F000000;
+ u32 polyid = RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
// fill screen borders for edge marking