diff options
| author | StapleButter <thetotalworm@gmail.com> | 2017-05-28 19:18:16 +0200 | 
|---|---|---|
| committer | StapleButter <thetotalworm@gmail.com> | 2017-05-28 19:18:16 +0200 | 
| commit | d3b3255ce3aacc650a00210078e6a8af04e5ec71 (patch) | |
| tree | 2323dfb48be58842eb3cd3a6dddbdb399adc503a | |
| parent | ae78faf2a743ec87f6165b8dc4b008ba1897d06d (diff) | |
* add 'push old pixel down' behavior for antialiasing
* delay final pass (edge/fog/AA) one scanline, required for edgemarking
| -rw-r--r-- | src/GPU3D_Soft.cpp | 198 | 
1 files changed, 135 insertions, 63 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 254e9ee..32a32b9 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -28,9 +28,9 @@ namespace GPU3D  namespace SoftRenderer  { -u32 ColorBuffer[256*192]; -u32 DepthBuffer[256*192]; -u32 AttrBuffer[256*192]; +u32 ColorBuffer[258*3*194]; +u32 DepthBuffer[258*3*194]; +u32 AttrBuffer[258*3*194];  // attribute buffer:  // bit15: fog enable @@ -952,6 +952,7 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)      Interpolator interpX(xstart, xend+1, wl, wr, 8);  //printf("%d: edge %d %d, %d %d\n", y, l_edgelen, r_edgelen, l_edgecov, r_edgecov); +    // TODO: split this based on edge/middle      for (s32 x = xstart; x <= xend; x++)      {          if (x < 0) continue; @@ -968,13 +969,13 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)              continue;          } -        u32 pixeladdr = (y*256) + x; +        u32 pixeladdr = 258*3 + 1 + (y*258*3) + x;          u32 attr = polygon->Attr & 0x3F008000;          // check stencil buffer for shadows          if (polygon->IsShadow)          { -            if (StencilBuffer[pixeladdr & 0x1FF] == 0) +            if (StencilBuffer[256*(y&0x1) + x] == 0)                  continue;          } @@ -1000,13 +1001,19 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)              }              if (!fnDepthTest(DepthBuffer[pixeladdr], z)) -                StencilBuffer[pixeladdr & 0x1FF] = 1; +                StencilBuffer[256*(y&0x1) + x] = 1;              continue;          } +        // if depth test against the topmost pixel fails, test +        // against the pixel underneath          if (!fnDepthTest(DepthBuffer[pixeladdr], z)) -            continue; +        { +            pixeladdr += 258; +            if (!fnDepthTest(DepthBuffer[pixeladdr], z)) +                continue; +        }          u32 vr = interpX.Interpolate(rl, rr);          u32 vg = interpX.Interpolate(gl, gr); @@ -1019,13 +1026,11 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)          u8 alpha = color >> 24;          // alpha test -        // TODO: check alpha test when blending is disabled          if (alpha <= RenderAlphaRef) continue;          if (alpha == 31)          {              // edge fill rules for opaque pixels -            // TODO, eventually: antialiasing              if (!wireframe)              {                  if ((edge & 0x1) && !l_filledge) @@ -1034,6 +1039,14 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)                      continue;              } +            // push old pixel down if needed +            if (edge) +            { +                ColorBuffer[pixeladdr+258] = ColorBuffer[pixeladdr]; +                DepthBuffer[pixeladdr+258] = DepthBuffer[pixeladdr]; +                AttrBuffer[pixeladdr+258] = AttrBuffer[pixeladdr]; +            } +              DepthBuffer[pixeladdr] = z;          }          else @@ -1081,6 +1094,14 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y)                  color = srcR | (srcG << 8) | (srcB << 16) | (dstalpha << 24);              } +            // push old pixel down if needed +            if (edge) +            { +                ColorBuffer[pixeladdr+258] = ColorBuffer[pixeladdr]; +                DepthBuffer[pixeladdr+258] = DepthBuffer[pixeladdr]; +                AttrBuffer[pixeladdr+258] = AttrBuffer[pixeladdr]; +            } +              if (polygon->Attr & (1<<11))                  DepthBuffer[pixeladdr] = z;          } @@ -1132,7 +1153,10 @@ void RenderScanline(s32 y, int npolys)          if (y >= polygon->YTop && (y < polygon->YBottom || (y == polygon->YTop && polygon->YBottom == polygon->YTop)))              RenderPolygonScanline(rp, y);      } +} +void ScanlineFinalPass(s32 y) +{      if (RenderDispCnt & (1<<7))      {          // fog @@ -1141,6 +1165,9 @@ void RenderScanline(s32 y, int npolys)          // basically, the depth values used in GBAtek need to be          // multiplied by 0x200 to match Z-buffer values +        // fog is applied to the topmost two pixels, which is required for +        // proper antialiasing +          bool fogcolor = !(RenderDispCnt & (1<<6));          u32 fogshift = (RenderDispCnt >> 8) & 0xF;          u32 fogoffset = RenderFogOffset * 0x200; @@ -1150,72 +1177,106 @@ void RenderScanline(s32 y, int npolys)          u32 fogB = (RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;          u32 fogA = (RenderFogColor >> 16) & 0x1F; -        for (int x = 0; x < 256; x++) +        for (int i = 0; i < 258*2; i+=258)          { -            u32 pixeladdr = (y*256) + x; +            for (int x = 0; x < 256; x++) +            { +                u32 pixeladdr = 258*3 + 1 + (y*258*3) + i + x; -            u32 attr = AttrBuffer[pixeladdr]; -            if (!(attr & (1<<15))) continue; +                u32 attr = AttrBuffer[pixeladdr]; +                if (!(attr & (1<<15))) continue; -            u32 z = DepthBuffer[pixeladdr]; -            u32 densityid, densityfrac; -            if (z < fogoffset) -            { -                densityid = 0; -                densityfrac = 0; -            } -            else -            { -                z = (z - fogoffset) << fogshift; -                densityid = z >> 19; -                if (densityid >= 32) +                u32 z = DepthBuffer[pixeladdr]; +                u32 densityid, densityfrac; +                if (z < fogoffset)                  { -                    densityid = 32; +                    densityid = 0;                      densityfrac = 0;                  }                  else -                    densityfrac = z & 0x7FFFF; -            } +                { +                    z = (z - fogoffset) << fogshift; +                    densityid = z >> 19; +                    if (densityid >= 32) +                    { +                        densityid = 32; +                        densityfrac = 0; +                    } +                    else +                        densityfrac = z & 0x7FFFF; +                } -            // checkme -            u32 density = -                ((RenderFogDensityTable[densityid] * (0x80000-densityfrac)) + -                 (RenderFogDensityTable[densityid+1] * densityfrac)) >> 19; -            if (density >= 127) density = 128; - -            u32 srccolor = ColorBuffer[pixeladdr]; -            u32 srcR = srccolor & 0x3F; -            u32 srcG = (srccolor >> 8) & 0x3F; -            u32 srcB = (srccolor >> 16) & 0x3F; -            u32 srcA = (srccolor >> 24) & 0x1F; - -            if (fogcolor) -            { -                srcR = ((fogR * density) + (srcR * (128-density))) >> 7; -                srcG = ((fogG * density) + (srcG * (128-density))) >> 7; -                srcB = ((fogB * density) + (srcB * (128-density))) >> 7; -            } +                // checkme +                u32 density = +                    ((RenderFogDensityTable[densityid] * (0x80000-densityfrac)) + +                     (RenderFogDensityTable[densityid+1] * densityfrac)) >> 19; +                if (density >= 127) density = 128; -            if (densityid > 0) -                srcA = ((fogA * density) + (srcA * (128-density))) >> 7; -            else -                srcA = ((0x1F * density) + (srcA * (128-density))) >> 7; // checkme +                u32 srccolor = ColorBuffer[pixeladdr]; +                u32 srcR = srccolor & 0x3F; +                u32 srcG = (srccolor >> 8) & 0x3F; +                u32 srcB = (srccolor >> 16) & 0x3F; +                u32 srcA = (srccolor >> 24) & 0x1F; + +                if (fogcolor) +                { +                    srcR = ((fogR * density) + (srcR * (128-density))) >> 7; +                    srcG = ((fogG * density) + (srcG * (128-density))) >> 7; +                    srcB = ((fogB * density) + (srcB * (128-density))) >> 7; +                } -            ColorBuffer[pixeladdr] = srcR | (srcG << 8) | (srcB << 16) | (srcA << 24); +                if (densityid > 0) +                    srcA = ((fogA * density) + (srcA * (128-density))) >> 7; +                else +                    srcA = ((0x1F * density) + (srcA * (128-density))) >> 7; // checkme + +                ColorBuffer[pixeladdr] = srcR | (srcG << 8) | (srcB << 16) | (srcA << 24); +            }          }      }  }  void ClearBuffers()  { +    u32 clearz = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;      u32 polyid = RenderClearAttr1 & 0x3F000000; +    // fill screen borders for edge marking +    // CHECKME +    // GBAtek is unsure about the polygon ID, and nothing is said about Z + +    for (int x = 0; x < 258; x++) +    { +        ColorBuffer[x] = 0; +        DepthBuffer[x] = clearz; +        AttrBuffer[x] = polyid; +    } + +    for (int x = 258*3; x < 258*3*193; x+=(258*3)) +    { +        ColorBuffer[x] = 0; +        DepthBuffer[x] = clearz; +        AttrBuffer[x] = polyid; +        ColorBuffer[x+257] = 0; +        DepthBuffer[x+257] = clearz; +        AttrBuffer[x+257] = polyid; +    } + +    for (int x = 258*3*193; x < 258*3*194; x++) +    { +        ColorBuffer[x] = 0; +        DepthBuffer[x] = clearz; +        AttrBuffer[x] = polyid; +    } + +    // clear the screen +      if (RenderDispCnt & (1<<14))      {          u8 xoff = (RenderClearAttr2 >> 16) & 0xFF;          u8 yoff = (RenderClearAttr2 >> 24) & 0xFF; -        for (int y = 0; y < 256*192; y += 256) +        for (int y = 0; y < 258*3*192; y+=(258*3))          {              for (int x = 0; x < 256; x++)              { @@ -1231,9 +1292,10 @@ void ClearBuffers()                  u32 z = ((val3 & 0x7FFF) * 0x200) + 0x1FF; -                ColorBuffer[y+x] = color; -                DepthBuffer[y+x] = z; -                AttrBuffer[y+x] = polyid | (val3 & 0x8000); +                u32 pixeladdr = 258*3 + 1 + y + x; +                ColorBuffer[pixeladdr] = color; +                DepthBuffer[pixeladdr] = z; +                AttrBuffer[pixeladdr] = polyid | (val3 & 0x8000);                  xoff++;              } @@ -1251,15 +1313,17 @@ void ClearBuffers()          u32 a = (RenderClearAttr1 >> 16) & 0x1F;          u32 color = r | (g << 8) | (b << 16) | (a << 24); -        u32 z = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF; -  		polyid |= (RenderClearAttr1 & 0x8000); -        for (int i = 0; i < 256*192; i++) +        for (int y = 0; y < 258*3*192; y+=(258*3))          { -            ColorBuffer[i] = color; -            DepthBuffer[i] = z; -            AttrBuffer[i] = polyid; +            for (int x = 0; x < 256; x++) +            { +                u32 pixeladdr = 258*3 + 1 + y + x; +                ColorBuffer[pixeladdr] = color; +                DepthBuffer[pixeladdr] = clearz; +                AttrBuffer[pixeladdr] = polyid; +            }          }      }  } @@ -1282,13 +1346,21 @@ void RenderPolygons(bool threaded, Polygon* polygons, int npolys)          SetupPolygon(&PolygonList[j++], &polygons[i]);      } -    for (s32 y = 0; y < 192; y++) +    RenderScanline(0, npolys); + +    for (s32 y = 1; y < 192; y++)      {          RenderScanline(y, npolys); +        ScanlineFinalPass(y-1);          if (threaded)              Platform::Semaphore_Post(Sema_ScanlineCount);      } + +    ScanlineFinalPass(191); + +    if (threaded) +        Platform::Semaphore_Post(Sema_ScanlineCount);  }  void VCount144() @@ -1327,7 +1399,7 @@ void RequestLine(int line)  u32* GetLine(int line)  { -    return &ColorBuffer[line * 256]; +    return &ColorBuffer[line * 258*3  + 258*3 + 1];  }  }  |