From 1acf355d99c3afbc17d5ddfbd2392369eda2dad7 Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 4 Jul 2017 19:11:43 +0200 Subject: [PATCH] 3D: change viewport handling to match hardware. finally fixes #18 --- src/GPU3D.cpp | 33 +++++++++++---------------------- src/GPU3D_Soft.cpp | 24 ++++++++++++++++-------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index a7461890..25d04767 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -203,7 +203,7 @@ s32 TexMatrix[16]; s32 ClipMatrix[16]; bool ClipMatrixDirty; -s32 Viewport[4]; +u32 Viewport[6]; s32 ProjMatrixStack[16]; s32 PosMatrixStack[31][16]; @@ -723,7 +723,6 @@ void SubmitPolygon() // clipping nverts = ClipPolygon(clippedvertices, nverts, clipstart); - if (nverts == 0) { LastStripPolygon = NULL; @@ -803,24 +802,12 @@ void SubmitPolygon() // the transform for Z uses the normalized W values // W normalization is applied to separate polygons, even within strips - posX = (((s64)(vtx->Position[0] + w) * Viewport[2]) / (((s64)w) << 1)) + Viewport[0]; - posY = (((s64)(-vtx->Position[1] + w) * Viewport[3]) / (((s64)w) << 1)) + Viewport[1]; - - //if (FlushAttributes & 0x2) posZ = w; - //else posZ = (((s64)vtx->Position[2] * 0x800000) / w) + 0x7FFEFF; + posX = (((s64)(vtx->Position[0] + w) * Viewport[4]) / (((s64)w) << 1)) + Viewport[0]; + posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3]; } - if (posX < 0) posX = 0; - else if (posX > 256) posX = 256; - if (posY < 0) posY = 0; - else if (posY > 192) posY = 192; - //if (posZ < 0) posZ = 0; - //else if (posZ > 0xFFFFFF) posZ = 0xFFFFFF; - - vtx->FinalPosition[0] = posX; - vtx->FinalPosition[1] = posY; - //vtx->FinalPosition[2] = posZ; - //vtx->FinalPosition[3] = w; + vtx->FinalPosition[0] = posX & 0x1FF; + vtx->FinalPosition[1] = posY & 0xFF; vtx->FinalColor[0] = vtx->Color[0] >> 12; if (vtx->FinalColor[0]) vtx->FinalColor[0] = ((vtx->FinalColor[0] << 4) + 0xF); @@ -1711,10 +1698,12 @@ void ExecuteCommand() case 0x60: // viewport x1,y1,x2,y2 // note: viewport Y coordinates are upside-down - Viewport[0] = ExecParams[0] & 0xFF; - Viewport[1] = 191 - (ExecParams[0] >> 24); - Viewport[2] = ((ExecParams[0] >> 16) & 0xFF) - Viewport[0] + 1; - Viewport[3] = (191 - ((ExecParams[0] >> 8) & 0xFF)) - Viewport[1] + 1; + Viewport[0] = ExecParams[0] & 0xFF; // x0 + Viewport[1] = (191 - ((ExecParams[0] >> 8) & 0xFF)) & 0xFF; // y0 + Viewport[2] = (ExecParams[0] >> 16) & 0xFF; // x1 + Viewport[3] = (191 - (ExecParams[0] >> 24)) & 0xFF; // y1 + Viewport[4] = (Viewport[2] - Viewport[0] + 1) & 0x1FF; // width + Viewport[5] = (Viewport[1] - Viewport[3] + 1) & 0xFF; // height break; case 0x70: // box test diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index ab7f517a..b12ed8c3 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -1049,10 +1049,12 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) Interpolator interpX(xstart, xend+1, wl, wr, 8); if (x < 0) x = 0; + s32 xlimit; // part 1: left edge edge = yedge | 0x1; - for (; x < xstart+l_edgelen; x++) + xlimit = xstart+l_edgelen; if (xlimit > 256) xlimit = 256; + for (; x < xlimit; x++) { u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 attr = (polygon->Attr & 0x3F008000); @@ -1180,8 +1182,9 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) // part 2: polygon inside edge = yedge; - if (wireframe && !edge) x = xend-r_edgelen+1; - else for (; x <= xend-r_edgelen; x++) + xlimit = xend-r_edgelen+1; if (xlimit > 256) xlimit = 256; + if (wireframe && !edge) x = xlimit; + else for (; x < xlimit; x++) { u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 attr = (polygon->Attr & 0x3F008000); @@ -1268,11 +1271,10 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) AttrBuffer[pixeladdr] = attr; } - if (xend > 255) xend = 255; - // part 3: right edge edge = yedge | 0x2; - for (; x <= xend; x++) + xlimit = xend+1; if (xlimit > 256) xlimit = 256; + for (; x < xlimit; x++) { u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 attr = (polygon->Attr & 0x3F008000); @@ -1679,23 +1681,29 @@ void RenderPolygons(bool threaded, Polygon* polygons, int npolys) // TODO: Y-sorting for translucent polygons // TODO: all sorting should be done in GPU3D.cpp + // polygons with ybottom>192 aren't rendered at all + int j = 0; for (int i = 0; i < npolys; i++) { if (polygons[i].Translucent) continue; + + if (polygons[i].YBottom > 192) continue; SetupPolygon(&PolygonList[j++], &polygons[i]); } for (int i = 0; i < npolys; i++) { if (!polygons[i].Translucent) continue; + + if (polygons[i].YBottom > 192) continue; SetupPolygon(&PolygonList[j++], &polygons[i]); } - RenderScanline(0, npolys); + RenderScanline(0, j); for (s32 y = 1; y < 192; y++) { - RenderScanline(y, npolys); + RenderScanline(y, j); ScanlineFinalPass(y-1); if (threaded)