diff options
| author | StapleButter <thetotalworm@gmail.com> | 2017-07-15 15:24:25 +0200 | 
|---|---|---|
| committer | StapleButter <thetotalworm@gmail.com> | 2017-07-15 15:24:25 +0200 | 
| commit | 6b6389fbb4df03bf6e180b6f0c1bc55fc5e99b9c (patch) | |
| tree | 87740e1908332fa47ee1a8c1cbe80d50a7bd8324 /src | |
| parent | d9786038527394e0a2912d9b8e091e039efd0833 (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.cpp | 122 | 
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  |