less shitty texture mapping. alpha test, sort of.

This commit is contained in:
StapleButter 2017-03-15 00:10:32 +01:00
parent 671050a7f0
commit 74f291757a
3 changed files with 161 additions and 113 deletions

View File

@ -144,6 +144,8 @@ FIFO<CmdFIFOEntry>* CmdPIPE;
u32 NumCommands, CurCommand, ParamCount, TotalParams;
u32 DispCnt;
u32 AlphaRef;
u32 GXStat;
u32 ExecParams[32];
@ -233,6 +235,8 @@ void Reset()
TotalParams = 0;
DispCnt = 0;
AlphaRef = 0;
GXStat = 0;
memset(ExecParams, 0, 32*4);
@ -425,7 +429,7 @@ void ClipSegment(Vertex* outbuf, Vertex* vout, Vertex* vin)
if (comp != 2) INTERPOLATE(Position[2]);
INTERPOLATE(Position[3]);
mid.Position[comp] = plane*mid.Position[3];
//printf("clip %d,%d: Y = %08X %08X %08X, %08X %08X\n", comp, plane, vin->Position[1], vout->Position[1], mid.Position[1], (s32)factor_num, factor_den);
INTERPOLATE(Color[0]);
INTERPOLATE(Color[1]);
INTERPOLATE(Color[2]);
@ -1382,6 +1386,8 @@ void VBlank()
{
if (FlushRequest)
{
SoftRenderer::DispCnt = DispCnt;
SoftRenderer::AlphaRef = AlphaRef;
SoftRenderer::RenderFrame(CurFlushAttributes, CurVertexRAM, CurPolygonRAM, NumPolygons);
CurRAMBank = CurRAMBank?0:1;
@ -1462,6 +1468,12 @@ u32 Read32(u32 addr)
void Write8(u32 addr, u8 val)
{
switch (addr)
{
case 0x04000340:
AlphaRef = val & 0x1F;
return;
}
}
void Write16(u32 addr, u16 val)
@ -1472,6 +1484,10 @@ void Write16(u32 addr, u16 val)
DispCnt = val;
return;
case 0x04000340:
AlphaRef = val & 0x1F;
return;
case 0x04000350:
ClearAttr1 = (ClearAttr1 & 0xFFFF0000) | val;
return;
@ -1495,6 +1511,10 @@ void Write32(u32 addr, u32 val)
DispCnt = val & 0xFFFF;
return;
case 0x04000340:
AlphaRef = val & 0x1F;
return;
case 0x04000350:
ClearAttr1 = val;
return;

View File

@ -80,6 +80,9 @@ void Write32(u32 addr, u32 val);
namespace SoftRenderer
{
extern u32 DispCnt;
extern u32 AlphaRef;
bool Init();
void DeInit();
void Reset();

View File

@ -27,6 +27,9 @@ namespace GPU3D
namespace SoftRenderer
{
u32 DispCnt;
u32 AlphaRef;
u32 ColorBuffer[256*192];
u32 DepthBuffer[256*192];
u32 AttrBuffer[256*192];
@ -43,7 +46,6 @@ bool Init()
void DeInit()
{
//
}
void Reset()
@ -301,10 +303,11 @@ u32 RenderPixel(Polygon* polygon, s32 x, s32 y, s32 z, u8 vr, u8 vg, u8 vb, s16
u32 attr = polygon->Attr;
u8 r, g, b, a;
if (((polygon->TexParam >> 26) & 0x7) != 0)
{
// TODO: also take DISP3DCNT into account
u32 polyalpha = (polygon->Attr >> 16) & 0x1F;
bool wireframe = (polyalpha == 0);
if ((DispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
{
u8 tr, tg, tb;
u16 tcolor; u8 talpha;
@ -315,21 +318,20 @@ u32 RenderPixel(Polygon* polygon, s32 x, s32 y, s32 z, u8 vr, u8 vg, u8 vb, s16
tb = (tcolor >> 9) & 0x3E; if (tb) tb++;
// TODO: other blending modes
/*r = ((tr+1) * (vr+1) - 1) >> 6;
r = ((tr+1) * (vr+1) - 1) >> 6;
g = ((tg+1) * (vg+1) - 1) >> 6;
b = ((tb+1) * (vb+1) - 1) >> 6;*/
r = tr;
g = tg;
b = tb;
b = ((tb+1) * (vb+1) - 1) >> 6;
a = ((talpha+1) * (polyalpha+1) - 1) >> 5;
}
else
{
r = vr;
g = vg;
b = vb;
a = polyalpha;
}
a = 31;
if (wireframe) a = 31;
return r | (g << 8) | (b << 16) | (a << 24);
}
@ -363,8 +365,6 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
}
else
{
//posX = ((s64)vtx->Position[0] << 12) / w;
//posY = ((s64)vtx->Position[1] << 12) / w;
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];
@ -372,9 +372,6 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
else posZ = (((s64)vtx->Position[2] * 0x800000) / w) + 0x7FFEFF;
}
//s32 scrX = (((posX + 0x1000) * Viewport[2]) >> 13) + Viewport[0];
//s32 scrY = ((0x180000 - ((posY + 0x1000) * Viewport[3])) >> 13) + Viewport[1];
if (posX < 0) posX = 0;
else if (posX > 256) posX = 256;
if (posY < 0) posY = 0;
@ -409,10 +406,6 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
ybot = vtx->FinalPosition[1];
vbot = i;
}
//printf("v%d: %d %d %06X, %04X %04X\n",
// i, vtx->FinalPosition[0], vtx->FinalPosition[1], vtx->FinalPosition[2],
// vtx->TexCoords[0], vtx->TexCoords[1]);
}
if (ytop > 191) return;
@ -494,6 +487,7 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
else if (rslope) dxr = (rslope > 0) ? 0 : 0x1000;
else dxr = 0x1000;
if (ybot > 191) ybot = 191;
for (s32 y = ytop; y < ybot; y++)
{
if (!isline)
@ -566,43 +560,52 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
s32 xstart_int, xend_int;
s32 slope_start, slope_end;
if (lslope > 0)
if (lslope == 0 && rslope == 0 &&
polygon->Vertices[lcur]->FinalPosition[0] == polygon->Vertices[rcur]->FinalPosition[0])
{
xstart = polygon->Vertices[lcur]->FinalPosition[0] + (dxl >> 12);
if (xstart < polygon->Vertices[lcur]->FinalPosition[0])
xstart = polygon->Vertices[lcur]->FinalPosition[0];
else if (xstart > polygon->Vertices[lnext]->FinalPosition[0]-1)
xstart = polygon->Vertices[lnext]->FinalPosition[0]-1;
}
else if (lslope < 0)
{
xstart = polygon->Vertices[lcur]->FinalPosition[0] - (dxl >> 12);
if (xstart < polygon->Vertices[lnext]->FinalPosition[0])
xstart = polygon->Vertices[lnext]->FinalPosition[0];
else if (xstart > polygon->Vertices[lcur]->FinalPosition[0]-1)
xstart = polygon->Vertices[lcur]->FinalPosition[0]-1;
}
else
xstart = polygon->Vertices[lcur]->FinalPosition[0];
if (rslope > 0)
{
xend = polygon->Vertices[rcur]->FinalPosition[0] + (dxr >> 12);
if (xend < polygon->Vertices[rcur]->FinalPosition[0])
xend = polygon->Vertices[rcur]->FinalPosition[0];
else if (xend > polygon->Vertices[rnext]->FinalPosition[0]-1)
xend = polygon->Vertices[rnext]->FinalPosition[0]-1;
}
else if (rslope < 0)
{
xend = polygon->Vertices[rcur]->FinalPosition[0] - (dxr >> 12);
if (xend < polygon->Vertices[rnext]->FinalPosition[0])
xend = polygon->Vertices[rnext]->FinalPosition[0];
else if (xend > polygon->Vertices[rcur]->FinalPosition[0]-1)
xend = polygon->Vertices[rcur]->FinalPosition[0]-1;
xend = xstart;
}
else
xend = polygon->Vertices[rcur]->FinalPosition[0] - 1;
{
if (lslope > 0)
{
xstart = polygon->Vertices[lcur]->FinalPosition[0] + (dxl >> 12);
if (xstart < polygon->Vertices[lcur]->FinalPosition[0])
xstart = polygon->Vertices[lcur]->FinalPosition[0];
else if (xstart > polygon->Vertices[lnext]->FinalPosition[0]-1)
xstart = polygon->Vertices[lnext]->FinalPosition[0]-1;
}
else if (lslope < 0)
{
xstart = polygon->Vertices[lcur]->FinalPosition[0] - (dxl >> 12);
if (xstart < polygon->Vertices[lnext]->FinalPosition[0])
xstart = polygon->Vertices[lnext]->FinalPosition[0];
else if (xstart > polygon->Vertices[lcur]->FinalPosition[0]-1)
xstart = polygon->Vertices[lcur]->FinalPosition[0]-1;
}
else
xstart = polygon->Vertices[lcur]->FinalPosition[0];
if (rslope > 0)
{
xend = polygon->Vertices[rcur]->FinalPosition[0] + (dxr >> 12);
if (xend < polygon->Vertices[rcur]->FinalPosition[0])
xend = polygon->Vertices[rcur]->FinalPosition[0];
else if (xend > polygon->Vertices[rnext]->FinalPosition[0]-1)
xend = polygon->Vertices[rnext]->FinalPosition[0]-1;
}
else if (rslope < 0)
{
xend = polygon->Vertices[rcur]->FinalPosition[0] - (dxr >> 12);
if (xend < polygon->Vertices[rnext]->FinalPosition[0])
xend = polygon->Vertices[rnext]->FinalPosition[0];
else if (xend > polygon->Vertices[rcur]->FinalPosition[0]-1)
xend = polygon->Vertices[rcur]->FinalPosition[0]-1;
}
else
xend = polygon->Vertices[rcur]->FinalPosition[0] - 1;
}
// if the left and right edges are swapped, render backwards.
// note: we 'forget' to swap the xmajor flags, on purpose
@ -631,54 +634,66 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
}
// interpolate attributes along Y
s64 lfactor1, lfactor2;
s64 rfactor1, rfactor2;
s64 lfactor1 = (vlnext->FinalPosition[1] - y) * vlnext->FinalPosition[3];
s64 lfactor2 = (y - vlcur->FinalPosition[1]) * vlcur->FinalPosition[3];
s64 denom = lfactor1 + lfactor2;
if (denom)
if (l_xmajor)
{
lfactor1 = (lfactor1 << 12) / denom;
lfactor2 = (lfactor2 << 12) / denom;
lfactor1 = (vlnext->FinalPosition[0] - xstart) * vlnext->FinalPosition[3];
lfactor2 = (xstart - vlcur->FinalPosition[0]) * vlcur->FinalPosition[3];
}
else
{
lfactor1 = (vlnext->FinalPosition[1] - y) * vlnext->FinalPosition[3];
lfactor2 = (y - vlcur->FinalPosition[1]) * vlcur->FinalPosition[3];
}
s64 ldenom = lfactor1 + lfactor2;
if (ldenom == 0)
{
lfactor1 = 0x1000;
lfactor2 = 0;
ldenom = 0x1000;
}
s64 rfactor1 = (vrnext->FinalPosition[1] - y) * vrnext->FinalPosition[3];
s64 rfactor2 = (y - vrcur->FinalPosition[1]) * vrcur->FinalPosition[3];
denom = rfactor1 + rfactor2;
if (denom)
if (r_xmajor)
{
rfactor1 = (rfactor1 << 12) / denom;
rfactor2 = (rfactor2 << 12) / denom;
rfactor1 = (vrnext->FinalPosition[0] - xend+1) * vrnext->FinalPosition[3];
rfactor2 = (xend+1 - vrcur->FinalPosition[0]) * vrcur->FinalPosition[3];
}
else
{
rfactor1 = 0x1000;
rfactor2 = 0;
rfactor1 = (vrnext->FinalPosition[1] - y) * vrnext->FinalPosition[3];
rfactor2 = (y - vrcur->FinalPosition[1]) * vrcur->FinalPosition[3];
}
s32 zl = ((lfactor1 * vlcur->FinalPosition[2]) + (lfactor2 * vlnext->FinalPosition[2])) >> 12;
s32 zr = ((rfactor1 * vrcur->FinalPosition[2]) + (rfactor2 * vrnext->FinalPosition[2])) >> 12;
s64 rdenom = rfactor1 + rfactor2;
if (rdenom == 0)
{
rfactor1 = 0x1000;
rfactor2 = 0;
rdenom = 0x1000;
}
s32 wl = ((lfactor1 * vlcur->FinalPosition[3]) + (lfactor2 * vlnext->FinalPosition[3])) >> 12;
s32 wr = ((rfactor1 * vrcur->FinalPosition[3]) + (rfactor2 * vrnext->FinalPosition[3])) >> 12;
s32 zl = ((lfactor1 * vlcur->FinalPosition[2]) + (lfactor2 * vlnext->FinalPosition[2])) / ldenom;
s32 zr = ((rfactor1 * vrcur->FinalPosition[2]) + (rfactor2 * vrnext->FinalPosition[2])) / rdenom;
s32 rl = ((lfactor1 * vlcur->FinalColor[0]) + (lfactor2 * vlnext->FinalColor[0])) >> 12;
s32 gl = ((lfactor1 * vlcur->FinalColor[1]) + (lfactor2 * vlnext->FinalColor[1])) >> 12;
s32 bl = ((lfactor1 * vlcur->FinalColor[2]) + (lfactor2 * vlnext->FinalColor[2])) >> 12;
s32 wl = ((lfactor1 * vlcur->FinalPosition[3]) + (lfactor2 * vlnext->FinalPosition[3])) / ldenom;
s32 wr = ((rfactor1 * vrcur->FinalPosition[3]) + (rfactor2 * vrnext->FinalPosition[3])) / rdenom;
s32 sl = ((lfactor1 * vlcur->TexCoords[0]) + (lfactor2 * vlnext->TexCoords[0])) >> 12;
s32 tl = ((lfactor1 * vlcur->TexCoords[1]) + (lfactor2 * vlnext->TexCoords[1])) >> 12;
s32 rl = ((lfactor1 * vlcur->FinalColor[0]) + (lfactor2 * vlnext->FinalColor[0])) / ldenom;
s32 gl = ((lfactor1 * vlcur->FinalColor[1]) + (lfactor2 * vlnext->FinalColor[1])) / ldenom;
s32 bl = ((lfactor1 * vlcur->FinalColor[2]) + (lfactor2 * vlnext->FinalColor[2])) / ldenom;
s32 rr = ((rfactor1 * vrcur->FinalColor[0]) + (rfactor2 * vrnext->FinalColor[0])) >> 12;
s32 gr = ((rfactor1 * vrcur->FinalColor[1]) + (rfactor2 * vrnext->FinalColor[1])) >> 12;
s32 br = ((rfactor1 * vrcur->FinalColor[2]) + (rfactor2 * vrnext->FinalColor[2])) >> 12;
s32 sl = ((lfactor1 * vlcur->TexCoords[0]) + (lfactor2 * vlnext->TexCoords[0])) / ldenom;
s32 tl = ((lfactor1 * vlcur->TexCoords[1]) + (lfactor2 * vlnext->TexCoords[1])) / ldenom;
s32 sr = ((rfactor1 * vrcur->TexCoords[0]) + (rfactor2 * vrnext->TexCoords[0])) >> 12;
s32 tr = ((rfactor1 * vrcur->TexCoords[1]) + (rfactor2 * vrnext->TexCoords[1])) >> 12;
s32 rr = ((rfactor1 * vrcur->FinalColor[0]) + (rfactor2 * vrnext->FinalColor[0])) / rdenom;
s32 gr = ((rfactor1 * vrcur->FinalColor[1]) + (rfactor2 * vrnext->FinalColor[1])) / rdenom;
s32 br = ((rfactor1 * vrcur->FinalColor[2]) + (rfactor2 * vrnext->FinalColor[2])) / rdenom;
s32 sr = ((rfactor1 * vrcur->TexCoords[0]) + (rfactor2 * vrnext->TexCoords[0])) / rdenom;
s32 tr = ((rfactor1 * vrcur->TexCoords[1]) + (rfactor2 * vrnext->TexCoords[1])) / rdenom;
// calculate edges
s32 l_edgeend, r_edgestart;
@ -708,9 +723,13 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
// * left edge is filled if slope <= 1
// * edges with slope = 0 are always filled
// edges are always filled if the pixels are translucent
if (y<0 || y>191 || xstart<0 || xend>255) { printf("BAD COORD %d %d %d\n", y, xstart, xend); return; }
// in wireframe mode, there are special rules for equal Z (TODO)
for (s32 x = xstart; x <= xend; x++)
{
if (x < 0) continue;
if (x > 255) break;
int edge = 0;
if (y == ytop) edge |= 0x4;
else if (y == ybot-1) edge |= 0x8;
@ -720,47 +739,63 @@ if (y<0 || y>191 || xstart<0 || xend>255) { printf("BAD COORD %d %d %d\n", y, xs
// wireframe polygons. really ugly, but works
if (wireframe && edge==0) continue;
s64 factor1 = (xend - x) * wr;
s64 factor1 = (xend+1 - x) * wr;
s64 factor2 = (x - xstart) * wl;
s64 denom = factor1 + factor2;
if (denom)
{
factor1 = (factor1 << 12) / denom;
factor2 = (factor2 << 12) / denom;
}
else
if (denom == 0)
{
factor1 = 0x1000;
factor2 = 0;
denom = 0x1000;
}
s32 z = ((factor1 * zl) + (factor2 * zr)) >> 12;
s32 z = ((factor1 * zl) + (factor2 * zr)) / denom;
if (!DepthTest(polygon, x, y, z)) continue;
u32 vr = ((factor1 * rl) + (factor2 * rr)) >> 12;
u32 vg = ((factor1 * gl) + (factor2 * gr)) >> 12;
u32 vb = ((factor1 * bl) + (factor2 * br)) >> 12;
u32 vr = ((factor1 * rl) + (factor2 * rr)) / denom;
u32 vg = ((factor1 * gl) + (factor2 * gr)) / denom;
u32 vb = ((factor1 * bl) + (factor2 * br)) / denom;
s16 s = ((factor1 * sl) + (factor2 * sr)) >> 12;
s16 t = ((factor1 * tl) + (factor2 * tr)) >> 12;
s16 s = ((factor1 * sl) + (factor2 * sr)) / denom;
s16 t = ((factor1 * tl) + (factor2 * tr)) / denom;
u32 color = RenderPixel(polygon, x, y, z, vr>>3, vg>>3, vb>>3, s, t);
u32 attr = 0;
u8 alpha = color >> 24;
if (alpha == 31 && !wireframe)
// alpha test
if (DispCnt & (1<<2))
{
if ((edge & 0x1) && slope_start > 0x1000)
continue;
if ((edge & 0x2) && (slope_end != 0 && slope_end <= 0x1000))
continue;
if (alpha <= AlphaRef) continue;
}
// TODO: blending
// alpha blending disable
// TODO: check alpha test when blending is disabled
if (!(DispCnt & (1<<3)))
alpha = 31;
if (alpha == 31)
{
if (!wireframe)
{
if ((edge & 0x1) && slope_start > 0x1000)
continue;
if ((edge & 0x2) && (slope_end != 0 && slope_end <= 0x1000))
continue;
}
DepthBuffer[(y*256) + x] = z;
}
else if (alpha > 0)
{
//
// TODO: conditional Z-buffer update
DepthBuffer[(y*256) + x] = z;
}
//if (ColorBuffer[(y*256) + x] != 0x1F3F3F3F)
ColorBuffer[(y*256) + x] = color;
DepthBuffer[(y*256) + x] = z;
AttrBuffer[(y*256) + x] = attr;
}
@ -769,16 +804,6 @@ if (y<0 || y>191 || xstart<0 || xend>255) { printf("BAD COORD %d %d %d\n", y, xs
if (rslope > 0) dxr += rslope;
else dxr -= rslope;
}
/*for (int i = 0; i < nverts; i++)
{
Vertex* vtx = polygon->Vertices[i];
int x = vtx->FinalPosition[0];
int y = vtx->FinalPosition[1];
if (x>=0 && x<256 && y>=0 && y<192)
ColorBuffer[(y*256) + x] = 0x1F3F3F3F;//printf("%d %d -- %08X %08X %08X\n", x, y, vtx->Position[0], vtx->Position[1], vtx->Position[3]);
}*/
}
void RenderFrame(u32 attr, Vertex* vertices, Polygon* polygons, int npolys)