3D: fix Z calculation in Z-buffering mode (should use original W, not normalized one). fixes horrendous Z-fighting in Pokémon games.

This commit is contained in:
StapleButter 2017-07-14 18:35:34 +02:00
parent cd6ecfc21f
commit d978603852
1 changed files with 8 additions and 11 deletions

View File

@ -790,22 +790,15 @@ void SubmitPolygon()
poly->NumVertices++; poly->NumVertices++;
// viewport transform // viewport transform
s32 posX, posY, posZ; s32 posX, posY;
s32 w = vtx->Position[3]; s32 w = vtx->Position[3];
if (w == 0) if (w == 0)
{ {
posX = 0; posX = 0;
posY = 0; posY = 0;
posZ = 0;
w = 0x1000;
} }
else else
{ {
// W is normalized, such that all the polygon's W values fit within 16 bits
// the viewport transform for X and Y uses the original W values, but
// 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[4]) / (((s64)w) << 1)) + Viewport[0]; 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]; posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3];
} }
@ -867,6 +860,11 @@ void SubmitPolygon()
Vertex* vtx = poly->Vertices[i]; Vertex* vtx = poly->Vertices[i];
s32 w, wshifted; s32 w, wshifted;
// W is normalized, such that all the polygon's W values fit within 16 bits
// the viewport transform for X/Y/Z uses the original W values, but
// when W-buffering is used, the normalized W is used
// W normalization is applied to separate polygons, even within strips
if (wsize < 16) if (wsize < 16)
{ {
w = vtx->Position[3] << (16 - wsize); w = vtx->Position[3] << (16 - wsize);
@ -882,11 +880,10 @@ void SubmitPolygon()
if (FlushAttributes & 0x2) if (FlushAttributes & 0x2)
z = wshifted; z = wshifted;
else if (wshifted) else if (wshifted)
z = ((((s64)vtx->Position[2] * 0x4000) / wshifted) * 0x200) + 0x7FFE00; z = ((((s64)vtx->Position[2] * 0x4000) / vtx->Position[3]) + 0x3FFF) * 0x200;
else else
z = 0x7FFEFF; z = 0x3FFF;
// checkme
if (z < 0) z = 0; if (z < 0) z = 0;
else if (z > 0xFFFFFF) z = 0xFFFFFF; else if (z > 0xFFFFFF) z = 0xFFFFFF;