fix handling of invalid viewports. solves homie rollerz character select. only implemented in softrasterizer. re #27

This commit is contained in:
zeromus 2017-02-23 00:55:24 -06:00
parent 8dd7c9b924
commit e02d134482
2 changed files with 30 additions and 8 deletions

View File

@ -1749,10 +1749,21 @@ static void gfx3d_glVecTest(u32 v)
void VIEWPORT::decode(const u32 v)
{
this->x = (v & 0xFF);
this->y = std::min<u8>(191, (v >> 8) & 0xFF);
this->width = ((v >> 16) & 0xFF) + 1 - this->x;
this->height = std::min<u8>(191, (v >> 24) & 0xFF) + 1 - this->y;
//test: homie rollerz character select chooses nonsense for Y. they did the math backwards. their goal was a fullscreen viewport, they just messed up.
//they also messed up the width...
u8 x1 = (v>> 0)&0xFF;
u8 y1 = (v>> 8)&0xFF;
u8 x2 = (v>>16)&0xFF;
u8 y2 = (v>>24)&0xFF;
//I'm 100% sure this is basically 99% correct
//the modular math is right. the details of how the +1 is handled may be wrong (this might should be dealt with in the viewport transformation instead)
//Its an off by one error in any event so we may never know
width = (u8)(x2-x1)+1;
height = (u8)(y2-y1)+1;
x = x1;
y = y1;
}
void gfx3d_glFogColor(u32 v)

View File

@ -1519,11 +1519,22 @@ template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms()
vert.coord[1] *= viewport.height * yfactor;
vert.coord[1] += viewport.y * yfactor;
vert.coord[1] = ymax - vert.coord[1];
//this is required to fix Homie Rollerz character select.
//this was also a better fix for Princess Debut's giant out of range polys.
//Basically, invalid viewports are blithely used here, and the math overflows and wraps around
//NOTE: this is a crude approximation of the correct fixed point modular arithmetic
if(vert.coord[0] >= 256) vert.coord[0] -= 256;
if(vert.coord[1] >= 256) vert.coord[1] -= 256;
if(vert.coord[0] < 0) vert.coord[0] += 256;
if(vert.coord[1] < 0) vert.coord[1] += 256;
//well, i guess we need to do this to keep Princess Debut from rendering huge polys.
//there must be something strange going on
vert.coord[0] = max(0.0f,min(xmax,vert.coord[0]));
vert.coord[1] = max(0.0f,min(ymax,vert.coord[1]));
//now, this is really lame. probably the rasterizer should be dealing with this, but
//1. its easier here
//2. its more likely reusable in opengl this way (well, this is a bunch more calculations that should be earlier in the pipeline and obligatorily shared)
//I do have some evidence that this wrecks the hardware extremely, but nothing's likely to use that effect.
//This is a sanity check only.
if(vert.coord[1] >= 192) vert.coord[1] = 192;
}
}
}