start work on polygon edges and shit
This commit is contained in:
parent
94dced7c41
commit
671050a7f0
19
GPU3D.cpp
19
GPU3D.cpp
|
@ -418,13 +418,14 @@ void ClipSegment(Vertex* outbuf, Vertex* vout, Vertex* vin)
|
||||||
s32 factor_den = factor_num - (vout->Position[3] - (plane*vout->Position[comp]));
|
s32 factor_den = factor_num - (vout->Position[3] - (plane*vout->Position[comp]));
|
||||||
|
|
||||||
Vertex mid;
|
Vertex mid;
|
||||||
#define INTERPOLATE(var) mid.var = (vin->var + ((vout->var - vin->var) * factor_num) / factor_den);
|
#define INTERPOLATE(var) { mid.var = (vin->var + ((vout->var - vin->var) * factor_num) / factor_den); }
|
||||||
|
|
||||||
INTERPOLATE(Position[0]);
|
if (comp != 0) INTERPOLATE(Position[0]);
|
||||||
INTERPOLATE(Position[1]);
|
if (comp != 1) INTERPOLATE(Position[1]);
|
||||||
INTERPOLATE(Position[2]);
|
if (comp != 2) INTERPOLATE(Position[2]);
|
||||||
INTERPOLATE(Position[3]);
|
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[0]);
|
||||||
INTERPOLATE(Color[1]);
|
INTERPOLATE(Color[1]);
|
||||||
INTERPOLATE(Color[2]);
|
INTERPOLATE(Color[2]);
|
||||||
|
@ -775,14 +776,14 @@ void SubmitPolygon()
|
||||||
|
|
||||||
poly->NumVertices += 2;
|
poly->NumVertices += 2;
|
||||||
}
|
}
|
||||||
|
//if (c==4 && NumPolygons>340) printf("polygon:\n");
|
||||||
for (int i = clipstart; i < c; i++)
|
for (int i = clipstart; i < c; i++)
|
||||||
{
|
{
|
||||||
CurVertexRAM[NumVertices] = clippedvertices[1][i];
|
CurVertexRAM[NumVertices] = clippedvertices[1][i];
|
||||||
poly->Vertices[i] = &CurVertexRAM[NumVertices];
|
poly->Vertices[i] = &CurVertexRAM[NumVertices];
|
||||||
|
|
||||||
NumVertices++;
|
NumVertices++;
|
||||||
poly->NumVertices++;
|
poly->NumVertices++;//if (c==4 && NumPolygons>340)printf(" - v%d: %08X %08X %08X\n", i, poly->Vertices[i]->Position[0], poly->Vertices[i]->Position[1],poly->Vertices[i]->Position[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PolygonMode >= 2)
|
if (PolygonMode >= 2)
|
||||||
|
@ -795,7 +796,9 @@ void SubmitVertex()
|
||||||
{
|
{
|
||||||
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
||||||
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
|
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
|
||||||
|
if (PolygonMode==0&&NumPolygons>440&&false)printf("raw vertex %d: %08X %08X | %08X %08X %08X %08X\n",
|
||||||
|
VertexNum, CurVertex[0], CurVertex[1],
|
||||||
|
ClipMatrix[1],ClipMatrix[5],ClipMatrix[9],ClipMatrix[13]);
|
||||||
UpdateClipMatrix();
|
UpdateClipMatrix();
|
||||||
vertextrans->Position[0] = (vertex[0]*ClipMatrix[0] + vertex[1]*ClipMatrix[4] + vertex[2]*ClipMatrix[8] + vertex[3]*ClipMatrix[12]) >> 12;
|
vertextrans->Position[0] = (vertex[0]*ClipMatrix[0] + vertex[1]*ClipMatrix[4] + vertex[2]*ClipMatrix[8] + vertex[3]*ClipMatrix[12]) >> 12;
|
||||||
vertextrans->Position[1] = (vertex[0]*ClipMatrix[1] + vertex[1]*ClipMatrix[5] + vertex[2]*ClipMatrix[9] + vertex[3]*ClipMatrix[13]) >> 12;
|
vertextrans->Position[1] = (vertex[0]*ClipMatrix[1] + vertex[1]*ClipMatrix[5] + vertex[2]*ClipMatrix[9] + vertex[3]*ClipMatrix[13]) >> 12;
|
||||||
|
|
441
GPU3D_Soft.cpp
441
GPU3D_Soft.cpp
|
@ -29,6 +29,11 @@ namespace SoftRenderer
|
||||||
|
|
||||||
u32 ColorBuffer[256*192];
|
u32 ColorBuffer[256*192];
|
||||||
u32 DepthBuffer[256*192];
|
u32 DepthBuffer[256*192];
|
||||||
|
u32 AttrBuffer[256*192];
|
||||||
|
|
||||||
|
// attribute buffer:
|
||||||
|
// bit0-5: polygon ID
|
||||||
|
// bit8: fog enable
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
|
@ -45,6 +50,7 @@ void Reset()
|
||||||
{
|
{
|
||||||
memset(ColorBuffer, 0, 256*192 * 4);
|
memset(ColorBuffer, 0, 256*192 * 4);
|
||||||
memset(DepthBuffer, 0, 256*192 * 4);
|
memset(DepthBuffer, 0, 256*192 * 4);
|
||||||
|
memset(AttrBuffer, 0, 256*192 * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,26 +279,26 @@ void TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPixel(Polygon* polygon, s32 x, s32 y, s32 z, u8 vr, u8 vg, u8 vb, s16 s, s16 t)
|
bool DepthTest(Polygon* polygon, s32 x, s32 y, s32 z)
|
||||||
{
|
{
|
||||||
u32 attr = polygon->Attr;
|
u32 oldz = DepthBuffer[(256*y) + x];
|
||||||
|
|
||||||
u32* color = &ColorBuffer[(256*y) + x];
|
if (polygon->Attr & (1<<14))
|
||||||
u32* depth = &DepthBuffer[(256*y) + x];
|
|
||||||
|
|
||||||
bool passdepth = false;
|
|
||||||
if (attr & (1<<14))
|
|
||||||
{
|
{
|
||||||
s32 diff = *depth - z;
|
s32 diff = oldz - z;
|
||||||
if ((u32)(diff + 0x200) <= 0x400)
|
if ((u32)(diff + 0x200) <= 0x400)
|
||||||
passdepth = true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (z < *depth)
|
if (z < oldz)
|
||||||
passdepth = true;
|
return true;
|
||||||
|
|
||||||
if (!passdepth) return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RenderPixel(Polygon* polygon, s32 x, s32 y, s32 z, u8 vr, u8 vg, u8 vb, s16 s, s16 t)
|
||||||
|
{
|
||||||
|
u32 attr = polygon->Attr;
|
||||||
u8 r, g, b, a;
|
u8 r, g, b, a;
|
||||||
|
|
||||||
if (((polygon->TexParam >> 26) & 0x7) != 0)
|
if (((polygon->TexParam >> 26) & 0x7) != 0)
|
||||||
|
@ -325,11 +331,7 @@ void RenderPixel(Polygon* polygon, s32 x, s32 y, s32 z, u8 vr, u8 vg, u8 vb, s16
|
||||||
|
|
||||||
a = 31;
|
a = 31;
|
||||||
|
|
||||||
*color = r | (g << 8) | (b << 16) | (a << 24);
|
return r | (g << 8) | (b << 16) | (a << 24);
|
||||||
|
|
||||||
// TODO: optional update for translucent pixels
|
|
||||||
if (z > 0xFFFFFF) z = 0xFFFFFF;
|
|
||||||
*depth = z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
||||||
|
@ -361,25 +363,27 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
posX = ((s64)vtx->Position[0] << 12) / w;
|
//posX = ((s64)vtx->Position[0] << 12) / w;
|
||||||
posY = ((s64)vtx->Position[1] << 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];
|
||||||
|
|
||||||
if (wbuffer) posZ = w;
|
if (wbuffer) posZ = w;
|
||||||
else posZ = (((s64)vtx->Position[2] * 0x800000) / w) + 0x7FFEFF;
|
else posZ = (((s64)vtx->Position[2] * 0x800000) / w) + 0x7FFEFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 scrX = (((posX + 0x1000) * Viewport[2]) >> 13) + Viewport[0];
|
//s32 scrX = (((posX + 0x1000) * Viewport[2]) >> 13) + Viewport[0];
|
||||||
s32 scrY = ((0x180000 - ((posY + 0x1000) * Viewport[3])) >> 13) + Viewport[1];
|
//s32 scrY = ((0x180000 - ((posY + 0x1000) * Viewport[3])) >> 13) + Viewport[1];
|
||||||
|
|
||||||
if (scrX < 0) scrX = 0;
|
if (posX < 0) posX = 0;
|
||||||
else if (scrX > 256) scrX = 256;
|
else if (posX > 256) posX = 256;
|
||||||
if (scrY < 0) scrY = 0;
|
if (posY < 0) posY = 0;
|
||||||
else if (scrY > 192) scrY = 192;
|
else if (posY > 192) posY = 192;
|
||||||
if (posZ < 0) posZ = 0;
|
if (posZ < 0) posZ = 0;
|
||||||
else if (posZ > 0xFFFFFF) posZ = 0xFFFFFF;
|
else if (posZ > 0xFFFFFF) posZ = 0xFFFFFF;
|
||||||
|
|
||||||
vtx->FinalPosition[0] = scrX;
|
vtx->FinalPosition[0] = posX;
|
||||||
vtx->FinalPosition[1] = scrY;
|
vtx->FinalPosition[1] = posY;
|
||||||
vtx->FinalPosition[2] = posZ;
|
vtx->FinalPosition[2] = posZ;
|
||||||
vtx->FinalPosition[3] = w;
|
vtx->FinalPosition[3] = w;
|
||||||
|
|
||||||
|
@ -406,14 +410,25 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
||||||
vbot = i;
|
vbot = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("v%d: %d,%d\n", i, vtx->FinalPosition[0], vtx->FinalPosition[1]);
|
//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;
|
||||||
|
|
||||||
// draw, line per line
|
// draw, line per line
|
||||||
|
|
||||||
|
u32 polyalpha = (polygon->Attr >> 16) & 0x1F;
|
||||||
|
bool wireframe = (polyalpha == 0);
|
||||||
|
|
||||||
int lcur = vtop, rcur = vtop;
|
int lcur = vtop, rcur = vtop;
|
||||||
int lnext, rnext;
|
int lnext, rnext;
|
||||||
|
|
||||||
|
s32 dxl, dxr;
|
||||||
|
s32 lslope, rslope;
|
||||||
|
bool l_xmajor, r_xmajor;
|
||||||
|
|
||||||
if (ybot == ytop)
|
if (ybot == ytop)
|
||||||
{
|
{
|
||||||
ybot++;
|
ybot++;
|
||||||
|
@ -433,9 +448,13 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
||||||
|
|
||||||
lcur = vtop; lnext = vtop;
|
lcur = vtop; lnext = vtop;
|
||||||
rcur = vbot; rnext = vbot;
|
rcur = vbot; rnext = vbot;
|
||||||
|
|
||||||
|
lslope = 0; l_xmajor = false;
|
||||||
|
rslope = 0; r_xmajor = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//while (polygon->Vertices[lnext]->FinalPosition[1] )
|
||||||
if (polygon->FacingView)
|
if (polygon->FacingView)
|
||||||
{
|
{
|
||||||
lnext = lcur + 1;
|
lnext = lcur + 1;
|
||||||
|
@ -450,174 +469,323 @@ void RenderPolygon(Polygon* polygon, u32 wbuffer)
|
||||||
rnext = rcur + 1;
|
rnext = rcur + 1;
|
||||||
if (rnext >= nverts) rnext = 0;
|
if (rnext >= nverts) rnext = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (polygon->Vertices[lnext]->FinalPosition[1] == polygon->Vertices[lcur]->FinalPosition[1])
|
||||||
|
lslope = 0;
|
||||||
|
else
|
||||||
|
lslope = ((polygon->Vertices[lnext]->FinalPosition[0] - polygon->Vertices[lcur]->FinalPosition[0]) << 12) /
|
||||||
|
(polygon->Vertices[lnext]->FinalPosition[1] - polygon->Vertices[lcur]->FinalPosition[1]);
|
||||||
|
|
||||||
|
if (polygon->Vertices[rnext]->FinalPosition[1] == polygon->Vertices[rcur]->FinalPosition[1])
|
||||||
|
rslope = 0;
|
||||||
|
else
|
||||||
|
rslope = ((polygon->Vertices[rnext]->FinalPosition[0] - polygon->Vertices[rcur]->FinalPosition[0]) << 12) /
|
||||||
|
(polygon->Vertices[rnext]->FinalPosition[1] - polygon->Vertices[rcur]->FinalPosition[1]);
|
||||||
|
|
||||||
|
l_xmajor = (lslope < -0x1000) || (lslope > 0x1000);
|
||||||
|
r_xmajor = (rslope < -0x1000) || (rslope > 0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (l_xmajor) dxl = (lslope > 0) ? 0x800 : (-lslope-0x800)+0x1000;
|
||||||
|
else if (lslope) dxl = (lslope > 0) ? 0 : 0x1000;
|
||||||
|
else dxl = 0;
|
||||||
|
|
||||||
|
if (r_xmajor) dxr = (rslope > 0) ? rslope-0x800 : 0x800+0x1000;
|
||||||
|
else if (rslope) dxr = (rslope > 0) ? 0 : 0x1000;
|
||||||
|
else dxr = 0x1000;
|
||||||
|
|
||||||
for (s32 y = ytop; y < ybot; y++)
|
for (s32 y = ytop; y < ybot; y++)
|
||||||
{
|
{
|
||||||
if (y > 191) break;
|
|
||||||
|
|
||||||
if (!isline)
|
if (!isline)
|
||||||
{
|
{
|
||||||
while (y >= polygon->Vertices[lnext]->FinalPosition[1] && lcur != vbot)
|
if (y >= polygon->Vertices[lnext]->FinalPosition[1] && lcur != vbot)
|
||||||
{
|
{
|
||||||
lcur = lnext;
|
while (y >= polygon->Vertices[lnext]->FinalPosition[1] && lcur != vbot)
|
||||||
|
|
||||||
if (polygon->FacingView)
|
|
||||||
{
|
{
|
||||||
lnext = lcur + 1;
|
lcur = lnext;
|
||||||
if (lnext >= nverts) lnext = 0;
|
|
||||||
|
if (polygon->FacingView)
|
||||||
|
{
|
||||||
|
lnext = lcur + 1;
|
||||||
|
if (lnext >= nverts) lnext = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lnext = lcur - 1;
|
||||||
|
if (lnext < 0) lnext = nverts - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (polygon->Vertices[lnext]->FinalPosition[1] == polygon->Vertices[lcur]->FinalPosition[1])
|
||||||
|
lslope = 0;
|
||||||
else
|
else
|
||||||
{
|
lslope = ((polygon->Vertices[lnext]->FinalPosition[0] - polygon->Vertices[lcur]->FinalPosition[0]) << 12) /
|
||||||
lnext = lcur - 1;
|
(polygon->Vertices[lnext]->FinalPosition[1] - polygon->Vertices[lcur]->FinalPosition[1]);
|
||||||
if (lnext < 0) lnext = nverts - 1;
|
|
||||||
}
|
l_xmajor = (lslope < -0x1000) || (lslope > 0x1000);
|
||||||
|
|
||||||
|
if (l_xmajor) dxl = (lslope > 0) ? 0x800 : (-lslope-0x800)+0x1000;
|
||||||
|
else if (lslope) dxl = (lslope > 0) ? 0 : 0x1000;
|
||||||
|
else dxl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (y >= polygon->Vertices[rnext]->FinalPosition[1] && rcur != vbot)
|
if (y >= polygon->Vertices[rnext]->FinalPosition[1] && rcur != vbot)
|
||||||
{
|
{
|
||||||
rcur = rnext;
|
while (y >= polygon->Vertices[rnext]->FinalPosition[1] && rcur != vbot)
|
||||||
|
|
||||||
if (polygon->FacingView)
|
|
||||||
{
|
{
|
||||||
rnext = rcur - 1;
|
rcur = rnext;
|
||||||
if (rnext < 0) rnext = nverts - 1;
|
|
||||||
|
if (polygon->FacingView)
|
||||||
|
{
|
||||||
|
rnext = rcur - 1;
|
||||||
|
if (rnext < 0) rnext = nverts - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rnext = rcur + 1;
|
||||||
|
if (rnext >= nverts) rnext = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (polygon->Vertices[rnext]->FinalPosition[1] == polygon->Vertices[rcur]->FinalPosition[1])
|
||||||
|
rslope = 0;
|
||||||
else
|
else
|
||||||
{
|
rslope = ((polygon->Vertices[rnext]->FinalPosition[0] - polygon->Vertices[rcur]->FinalPosition[0]) << 12) /
|
||||||
rnext = rcur + 1;
|
(polygon->Vertices[rnext]->FinalPosition[1] - polygon->Vertices[rcur]->FinalPosition[1]);
|
||||||
if (rnext >= nverts) rnext = 0;
|
|
||||||
}
|
r_xmajor = (rslope < -0x1000) || (rslope > 0x1000);
|
||||||
|
|
||||||
|
if (r_xmajor) dxr = (rslope > 0) ? rslope-0x800 : 0x800+0x1000;
|
||||||
|
else if (rslope) dxr = (rslope > 0) ? 0 : 0x1000;
|
||||||
|
else dxr = 0x1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex* vlcur = polygon->Vertices[lcur];
|
Vertex *vlcur, *vlnext, *vrcur, *vrnext;
|
||||||
Vertex* vlnext = polygon->Vertices[lnext];
|
s32 xstart, xend;
|
||||||
Vertex* vrcur = polygon->Vertices[rcur];
|
s32 xstart_int, xend_int;
|
||||||
Vertex* vrnext = polygon->Vertices[rnext];
|
s32 slope_start, slope_end;
|
||||||
|
|
||||||
s32 lfactor, rfactor;
|
if (lslope > 0)
|
||||||
|
{
|
||||||
// TODO: work out the actual division bias there. 0x400 was found to make things look good.
|
xstart = polygon->Vertices[lcur]->FinalPosition[0] + (dxl >> 12);
|
||||||
// but actually, it isn't right. so what's going on there?
|
if (xstart < polygon->Vertices[lcur]->FinalPosition[0])
|
||||||
// seems vertical slopes are interpolated starting from the bottom and not the top. maybe.
|
xstart = polygon->Vertices[lcur]->FinalPosition[0];
|
||||||
// also seems lfactor/rfactor are rounded
|
else if (xstart > polygon->Vertices[lnext]->FinalPosition[0]-1)
|
||||||
|
xstart = polygon->Vertices[lnext]->FinalPosition[0]-1;
|
||||||
// TODO: the calculations can be simplified
|
}
|
||||||
|
else if (lslope < 0)
|
||||||
if (vlnext->FinalPosition[1] == vlcur->FinalPosition[1])
|
{
|
||||||
lfactor = 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
|
else
|
||||||
lfactor = (((y+1 - vlcur->FinalPosition[1]) << 12) + 0x00) / (vlnext->FinalPosition[1] - vlcur->FinalPosition[1]);
|
xstart = polygon->Vertices[lcur]->FinalPosition[0];
|
||||||
|
|
||||||
if (vrnext->FinalPosition[1] == vrcur->FinalPosition[1])
|
if (rslope > 0)
|
||||||
rfactor = 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
|
else
|
||||||
rfactor = (((y+1 - vrcur->FinalPosition[1]) << 12) + 0x00) / (vrnext->FinalPosition[1] - vrcur->FinalPosition[1]);
|
xend = polygon->Vertices[rcur]->FinalPosition[0] - 1;
|
||||||
|
|
||||||
s32 xl = vlcur->FinalPosition[0] + ((((vlnext->FinalPosition[0] - vlcur->FinalPosition[0]) * lfactor) + 0x800) >> 12);
|
// if the left and right edges are swapped, render backwards.
|
||||||
s32 xr = vrcur->FinalPosition[0] + ((((vrnext->FinalPosition[0] - vrcur->FinalPosition[0]) * rfactor) + 0x800) >> 12);
|
// note: we 'forget' to swap the xmajor flags, on purpose
|
||||||
//printf("y:%d xl:%d xr:%d %08X\n", y, xl, xr, rfactor); // y: 48 143
|
// the hardware has the same bug
|
||||||
if (xl > xr) // TODO: handle it in a more elegant way
|
if (xstart > xend)
|
||||||
{
|
{
|
||||||
Vertex* vtmp;
|
vlcur = polygon->Vertices[rcur];
|
||||||
s32 tmp;
|
vlnext = polygon->Vertices[rnext];
|
||||||
|
vrcur = polygon->Vertices[lcur];
|
||||||
|
vrnext = polygon->Vertices[lnext];
|
||||||
|
|
||||||
vtmp = vlcur; vlcur = vrcur; vrcur = vtmp;
|
slope_start = rslope;
|
||||||
vtmp = vlnext; vlnext = vrnext; vrnext = vtmp;
|
slope_end = lslope;
|
||||||
|
|
||||||
tmp = lfactor; lfactor = rfactor; rfactor = tmp;
|
s32 tmp = xstart; xstart = xend; xend = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vlcur = polygon->Vertices[lcur];
|
||||||
|
vlnext = polygon->Vertices[lnext];
|
||||||
|
vrcur = polygon->Vertices[rcur];
|
||||||
|
vrnext = polygon->Vertices[rnext];
|
||||||
|
|
||||||
tmp = xl; xl = xr; xr = tmp;
|
slope_start = lslope;
|
||||||
|
slope_end = rslope;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xl<0 || xr>256)
|
// interpolate attributes along Y
|
||||||
|
|
||||||
|
s64 lfactor1 = (vlnext->FinalPosition[1] - y) * vlnext->FinalPosition[3];
|
||||||
|
s64 lfactor2 = (y - vlcur->FinalPosition[1]) * vlcur->FinalPosition[3];
|
||||||
|
s64 denom = lfactor1 + lfactor2;
|
||||||
|
if (denom)
|
||||||
{
|
{
|
||||||
printf("!! BAD X %d %d\n", xl, xr);
|
lfactor1 = (lfactor1 << 12) / denom;
|
||||||
continue; // hax
|
lfactor2 = (lfactor2 << 12) / denom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lfactor1 = 0x1000;
|
||||||
|
lfactor2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 perspfactorl1 = ((s64)(0x1000 - lfactor) * vlnext->FinalPosition[3]) >> 12;
|
s64 rfactor1 = (vrnext->FinalPosition[1] - y) * vrnext->FinalPosition[3];
|
||||||
s64 perspfactorl2 = ((s64)lfactor * vlcur->FinalPosition[3]) >> 12;
|
s64 rfactor2 = (y - vrcur->FinalPosition[1]) * vrcur->FinalPosition[3];
|
||||||
s64 perspfactorr1 = ((s64)(0x1000 - rfactor) * vrnext->FinalPosition[3]) >> 12;
|
denom = rfactor1 + rfactor2;
|
||||||
s64 perspfactorr2 = ((s64)rfactor * vrcur->FinalPosition[3]) >> 12;
|
if (denom)
|
||||||
|
|
||||||
if (perspfactorl1 + perspfactorl2 == 0)
|
|
||||||
{
|
{
|
||||||
perspfactorl1 = 0x1000;
|
rfactor1 = (rfactor1 << 12) / denom;
|
||||||
perspfactorl2 = 0;
|
rfactor2 = (rfactor2 << 12) / denom;
|
||||||
}
|
}
|
||||||
if (perspfactorr1 + perspfactorr2 == 0)
|
else
|
||||||
{
|
{
|
||||||
perspfactorr1 = 0x1000;
|
rfactor1 = 0x1000;
|
||||||
perspfactorr2 = 0;
|
rfactor2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 zl = ((perspfactorl1 * vlcur->FinalPosition[2]) + (perspfactorl2 * vlnext->FinalPosition[2])) / (perspfactorl1 + perspfactorl2);
|
s32 zl = ((lfactor1 * vlcur->FinalPosition[2]) + (lfactor2 * vlnext->FinalPosition[2])) >> 12;
|
||||||
s32 zr = ((perspfactorr1 * vrcur->FinalPosition[2]) + (perspfactorr2 * vrnext->FinalPosition[2])) / (perspfactorr1 + perspfactorr2);
|
s32 zr = ((rfactor1 * vrcur->FinalPosition[2]) + (rfactor2 * vrnext->FinalPosition[2])) >> 12;
|
||||||
|
|
||||||
s32 wl = ((perspfactorl1 * vlcur->FinalPosition[3]) + (perspfactorl2 * vlnext->FinalPosition[3])) / (perspfactorl1 + perspfactorl2);
|
s32 wl = ((lfactor1 * vlcur->FinalPosition[3]) + (lfactor2 * vlnext->FinalPosition[3])) >> 12;
|
||||||
s32 wr = ((perspfactorr1 * vrcur->FinalPosition[3]) + (perspfactorr2 * vrnext->FinalPosition[3])) / (perspfactorr1 + perspfactorr2);
|
s32 wr = ((rfactor1 * vrcur->FinalPosition[3]) + (rfactor2 * vrnext->FinalPosition[3])) >> 12;
|
||||||
|
|
||||||
s32 rl = ((perspfactorl1 * vlcur->FinalColor[0]) + (perspfactorl2 * vlnext->FinalColor[0])) / (perspfactorl1 + perspfactorl2);
|
s32 rl = ((lfactor1 * vlcur->FinalColor[0]) + (lfactor2 * vlnext->FinalColor[0])) >> 12;
|
||||||
s32 gl = ((perspfactorl1 * vlcur->FinalColor[1]) + (perspfactorl2 * vlnext->FinalColor[1])) / (perspfactorl1 + perspfactorl2);
|
s32 gl = ((lfactor1 * vlcur->FinalColor[1]) + (lfactor2 * vlnext->FinalColor[1])) >> 12;
|
||||||
s32 bl = ((perspfactorl1 * vlcur->FinalColor[2]) + (perspfactorl2 * vlnext->FinalColor[2])) / (perspfactorl1 + perspfactorl2);
|
s32 bl = ((lfactor1 * vlcur->FinalColor[2]) + (lfactor2 * vlnext->FinalColor[2])) >> 12;
|
||||||
|
|
||||||
s32 sl = ((perspfactorl1 * vlcur->TexCoords[0]) + (perspfactorl2 * vlnext->TexCoords[0])) / (perspfactorl1 + perspfactorl2);
|
s32 sl = ((lfactor1 * vlcur->TexCoords[0]) + (lfactor2 * vlnext->TexCoords[0])) >> 12;
|
||||||
s32 tl = ((perspfactorl1 * vlcur->TexCoords[1]) + (perspfactorl2 * vlnext->TexCoords[1])) / (perspfactorl1 + perspfactorl2);
|
s32 tl = ((lfactor1 * vlcur->TexCoords[1]) + (lfactor2 * vlnext->TexCoords[1])) >> 12;
|
||||||
|
|
||||||
s32 rr = ((perspfactorr1 * vrcur->FinalColor[0]) + (perspfactorr2 * vrnext->FinalColor[0])) / (perspfactorr1 + perspfactorr2);
|
s32 rr = ((rfactor1 * vrcur->FinalColor[0]) + (rfactor2 * vrnext->FinalColor[0])) >> 12;
|
||||||
s32 gr = ((perspfactorr1 * vrcur->FinalColor[1]) + (perspfactorr2 * vrnext->FinalColor[1])) / (perspfactorr1 + perspfactorr2);
|
s32 gr = ((rfactor1 * vrcur->FinalColor[1]) + (rfactor2 * vrnext->FinalColor[1])) >> 12;
|
||||||
s32 br = ((perspfactorr1 * vrcur->FinalColor[2]) + (perspfactorr2 * vrnext->FinalColor[2])) / (perspfactorr1 + perspfactorr2);
|
s32 br = ((rfactor1 * vrcur->FinalColor[2]) + (rfactor2 * vrnext->FinalColor[2])) >> 12;
|
||||||
|
|
||||||
s32 sr = ((perspfactorr1 * vrcur->TexCoords[0]) + (perspfactorr2 * vrnext->TexCoords[0])) / (perspfactorr1 + perspfactorr2);
|
s32 sr = ((rfactor1 * vrcur->TexCoords[0]) + (rfactor2 * vrnext->TexCoords[0])) >> 12;
|
||||||
s32 tr = ((perspfactorr1 * vrcur->TexCoords[1]) + (perspfactorr2 * vrnext->TexCoords[1])) / (perspfactorr1 + perspfactorr2);
|
s32 tr = ((rfactor1 * vrcur->TexCoords[1]) + (rfactor2 * vrnext->TexCoords[1])) >> 12;
|
||||||
|
|
||||||
if (xr == xl) xr++;
|
// calculate edges
|
||||||
|
s32 l_edgeend, r_edgestart;
|
||||||
|
|
||||||
// temp.
|
if (l_xmajor)
|
||||||
if (xl > 255) continue;
|
|
||||||
|
|
||||||
//s32 xdiv = 0x1000 / (xr - xl);
|
|
||||||
//s32 xdiv = 0x100000 / (xr - xl);
|
|
||||||
|
|
||||||
for (s32 x = xl; x < xr; x++)
|
|
||||||
{
|
{
|
||||||
//if (x!=xl && x!=(xr-1)) continue;
|
if (slope_start > 0) l_edgeend = vlcur->FinalPosition[0] + ((dxl + slope_start) >> 12);
|
||||||
s32 xfactor = ((x - xl) << 12) / (xr - xl);
|
else l_edgeend = vlcur->FinalPosition[0] - ((dxl - slope_start) >> 12);
|
||||||
//s32 xfactor = (x - xl) * xdiv;
|
|
||||||
//s32 xfactor = ((x - xl) * xdiv) >> 8;
|
|
||||||
|
|
||||||
|
if (l_edgeend == xstart) l_edgeend++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
l_edgeend = xstart + 1;
|
||||||
|
|
||||||
s32 perspfactor1 = ((s64)(0x1000 - xfactor) * wr) >> 12;
|
if (r_xmajor)
|
||||||
s32 perspfactor2 = ((s64)xfactor * wl) >> 12;
|
{
|
||||||
|
if (slope_end > 0) r_edgestart = vrcur->FinalPosition[0] + ((dxr + slope_end) >> 12);
|
||||||
|
else r_edgestart = vrcur->FinalPosition[0] - ((dxr - slope_end) >> 12);
|
||||||
|
|
||||||
if (perspfactor1 + perspfactor2 == 0)
|
if (r_edgestart == xend_int) r_edgestart--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
r_edgestart = xend - 1;
|
||||||
|
|
||||||
|
// edge fill rules for opaque pixels:
|
||||||
|
// * right edge is filled if slope > 1
|
||||||
|
// * 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; }
|
||||||
|
for (s32 x = xstart; x <= xend; x++)
|
||||||
|
{
|
||||||
|
int edge = 0;
|
||||||
|
if (y == ytop) edge |= 0x4;
|
||||||
|
else if (y == ybot-1) edge |= 0x8;
|
||||||
|
if (x < l_edgeend) edge |= 0x1;
|
||||||
|
else if (x > r_edgestart) edge |= 0x2;
|
||||||
|
|
||||||
|
// wireframe polygons. really ugly, but works
|
||||||
|
if (wireframe && edge==0) continue;
|
||||||
|
|
||||||
|
s64 factor1 = (xend - x) * wr;
|
||||||
|
s64 factor2 = (x - xstart) * wl;
|
||||||
|
s64 denom = factor1 + factor2;
|
||||||
|
if (denom)
|
||||||
{
|
{
|
||||||
perspfactor1 = 0x1000;
|
factor1 = (factor1 << 12) / denom;
|
||||||
perspfactor2 = 0;
|
factor2 = (factor2 << 12) / denom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
factor1 = 0x1000;
|
||||||
|
factor2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 z = ((perspfactor1 * (s64)zl) + (perspfactor2 * (s64)zr)) / (perspfactor1 + perspfactor2);
|
s32 z = ((factor1 * zl) + (factor2 * zr)) >> 12;
|
||||||
|
if (!DepthTest(polygon, x, y, z)) continue;
|
||||||
|
|
||||||
// possible optimization: only do color interpolation if the depth test passes
|
u32 vr = ((factor1 * rl) + (factor2 * rr)) >> 12;
|
||||||
u32 vr = ((perspfactor1 * rl) + (perspfactor2 * rr)) / (perspfactor1 + perspfactor2);
|
u32 vg = ((factor1 * gl) + (factor2 * gr)) >> 12;
|
||||||
u32 vg = ((perspfactor1 * gl) + (perspfactor2 * gr)) / (perspfactor1 + perspfactor2);
|
u32 vb = ((factor1 * bl) + (factor2 * br)) >> 12;
|
||||||
u32 vb = ((perspfactor1 * bl) + (perspfactor2 * br)) / (perspfactor1 + perspfactor2);
|
|
||||||
|
|
||||||
s16 s = ((perspfactor1 * (s64)sl) + (perspfactor2 * (s64)sr)) / (perspfactor1 + perspfactor2);
|
s16 s = ((factor1 * sl) + (factor2 * sr)) >> 12;
|
||||||
s16 t = ((perspfactor1 * (s64)tl) + (perspfactor2 * (s64)tr)) / (perspfactor1 + perspfactor2);
|
s16 t = ((factor1 * tl) + (factor2 * tr)) >> 12;
|
||||||
|
|
||||||
RenderPixel(polygon, x, y, z, vr>>3, vg>>3, vb>>3, s, t);
|
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)
|
||||||
|
{
|
||||||
|
if ((edge & 0x1) && slope_start > 0x1000)
|
||||||
|
continue;
|
||||||
|
if ((edge & 0x2) && (slope_end != 0 && slope_end <= 0x1000))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: blending
|
||||||
|
|
||||||
|
//if (ColorBuffer[(y*256) + x] != 0x1F3F3F3F)
|
||||||
|
ColorBuffer[(y*256) + x] = color;
|
||||||
|
DepthBuffer[(y*256) + x] = z;
|
||||||
|
AttrBuffer[(y*256) + x] = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lslope > 0) dxl += lslope;
|
||||||
|
else dxl -= lslope;
|
||||||
|
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)
|
void RenderFrame(u32 attr, Vertex* vertices, Polygon* polygons, int npolys)
|
||||||
{
|
{
|
||||||
// TODO: render translucent polygons last
|
// TODO: render translucent polygons last
|
||||||
|
|
||||||
// TODO: fog, poly ID, other attributes
|
u32 polyid = (ClearAttr1 >> 24) & 0x3F;
|
||||||
|
|
||||||
if (DispCnt & (1<<14))
|
if (DispCnt & (1<<14))
|
||||||
{
|
{
|
||||||
|
@ -643,6 +811,7 @@ void RenderFrame(u32 attr, Vertex* vertices, Polygon* polygons, int npolys)
|
||||||
|
|
||||||
ColorBuffer[y+x] = color;
|
ColorBuffer[y+x] = color;
|
||||||
DepthBuffer[y+x] = z;
|
DepthBuffer[y+x] = z;
|
||||||
|
AttrBuffer[y+x] = polyid | ((val3 & 0x8000) >> 7);
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
}
|
}
|
||||||
|
@ -662,15 +831,19 @@ void RenderFrame(u32 attr, Vertex* vertices, Polygon* polygons, int npolys)
|
||||||
u32 z = ((ClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
u32 z = ((ClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||||
if (z >= 0x10000 && z < 0xFFFFFF) z++;
|
if (z >= 0x10000 && z < 0xFFFFFF) z++;
|
||||||
|
|
||||||
|
polyid |= ((ClearAttr1 & 0x8000) >> 7);
|
||||||
|
|
||||||
for (int i = 0; i < 256*192; i++)
|
for (int i = 0; i < 256*192; i++)
|
||||||
{
|
{
|
||||||
ColorBuffer[i] = color;
|
ColorBuffer[i] = color;
|
||||||
DepthBuffer[i] = z;
|
DepthBuffer[i] = z;
|
||||||
|
AttrBuffer[i] = polyid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < npolys; i++)
|
for (int i = 0; i < npolys; i++)
|
||||||
{
|
{//if (i<npolys-6) continue;//printf("poly %d\n", i);
|
||||||
|
//if (i<npolys-2)continue;
|
||||||
RenderPolygon(&polygons[i], attr&0x2);
|
RenderPolygon(&polygons[i], attr&0x2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,7 @@ TODO LIST
|
||||||
IMMEDIATE TODO LIST (prior release 1.0)
|
IMMEDIATE TODO LIST (prior release 1.0)
|
||||||
|
|
||||||
* UI
|
* UI
|
||||||
* 3D engine that atleast supports texturing
|
* some polish to the 3D engine
|
||||||
* emulate DMA timings
|
|
||||||
* make timers suck less
|
* make timers suck less
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,3 +52,5 @@ TODO LIST FOR LATER
|
||||||
* hardware renderer for 3D
|
* hardware renderer for 3D
|
||||||
* wifi
|
* wifi
|
||||||
* maybe emulate flashcarts or other fancy hardware
|
* maybe emulate flashcarts or other fancy hardware
|
||||||
|
* big-endian compatibility (Wii, etc)
|
||||||
|
* LCD refresh time (used by some games for blending effects)
|
||||||
|
|
Loading…
Reference in New Issue