Render3D: Another rework on viewport transformations in SoftRasterizer and OpenGL. Completes fixes on #27.
- Also fixes major rendering regressions with SoftRasterizer in Metroid Prime Hunters and Princess Debut. (Regressions from e02d134.)
This commit is contained in:
parent
5335312704
commit
c71da856f5
|
@ -3149,12 +3149,21 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR
|
|||
|
||||
Render3DError OpenGLRenderer_1_2::SetupViewport(const u32 viewportValue)
|
||||
{
|
||||
const GLfloat wScalar = this->_framebufferWidth / GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
const GLfloat hScalar = this->_framebufferHeight / GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
const GLfloat wScalar = this->_framebufferWidth / (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
const GLfloat hScalar = this->_framebufferHeight / (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
|
||||
VIEWPORT viewport;
|
||||
viewport.decode(viewportValue);
|
||||
glViewport(viewport.x * wScalar, viewport.y * hScalar, viewport.width * wScalar, viewport.height * hScalar);
|
||||
|
||||
// The maximum viewport y-value is 191. Values above 191 need to wrap
|
||||
// around and go negative.
|
||||
//
|
||||
// Test case: The Homie Rollerz character select screen sets the y-value
|
||||
// to 253, which then wraps around to -2.
|
||||
glViewport( viewport.x * wScalar,
|
||||
(viewport.y > 191) ? (viewport.y - 0xFF) * hScalar : viewport.y * hScalar,
|
||||
viewport.width * wScalar,
|
||||
viewport.height * hScalar);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
|
|
@ -1006,7 +1006,7 @@ static void* execRasterizerUnit(void *arg)
|
|||
static void* SoftRasterizer_RunCalculateVertices(void *arg)
|
||||
{
|
||||
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
|
||||
softRender->performViewportTransforms<false>();
|
||||
softRender->performViewportTransforms();
|
||||
softRender->performBackfaceTests();
|
||||
softRender->performCoordAdjustment();
|
||||
|
||||
|
@ -1479,12 +1479,10 @@ size_t SoftRasterizerRenderer::performClipping(const VERTLIST *vertList, const P
|
|||
return clipper.clippedPolyCounter;
|
||||
}
|
||||
|
||||
template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms()
|
||||
void SoftRasterizerRenderer::performViewportTransforms()
|
||||
{
|
||||
const float xfactor = (float)this->_framebufferWidth/(float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
const float yfactor = (float)this->_framebufferHeight/(float)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
const float xmax = (float)this->_framebufferWidth-(CUSTOM?0.001f:0); //fudge factor to keep from overrunning render buffers
|
||||
const float ymax = (float)this->_framebufferHeight-(CUSTOM?0.001f:0);
|
||||
const float wScalar = (float)this->_framebufferWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
const float hScalar = (float)this->_framebufferHeight / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
|
||||
//viewport transforms
|
||||
for (size_t i = 0; i < this->_clippedPolyCount; i++)
|
||||
|
@ -1494,12 +1492,21 @@ template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms()
|
|||
{
|
||||
VERT &vert = poly.clipVerts[j];
|
||||
|
||||
// TODO: Possible divide by zero with the w-coordinate.
|
||||
// Is the vertex being read correctly? Is 0 a valid value for w?
|
||||
// If both of these questions answer to yes, then how does the NDS handle a NaN?
|
||||
// For now, simply prevent w from being zero.
|
||||
//
|
||||
// Test case: Dance scenes in Princess Debut can generate undefined vertices
|
||||
// when the -ffast-math option (relaxed IEEE754 compliance) is used.
|
||||
const float vertw = (vert.coord[3] != 0.0f) ? vert.coord[3] : 0.00000001f;
|
||||
|
||||
//homogeneous divide
|
||||
vert.coord[0] = (vert.coord[0]+vert.coord[3]) / (2*vert.coord[3]);
|
||||
vert.coord[1] = (vert.coord[1]+vert.coord[3]) / (2*vert.coord[3]);
|
||||
vert.coord[2] = (vert.coord[2]+vert.coord[3]) / (2*vert.coord[3]);
|
||||
vert.texcoord[0] /= vert.coord[3];
|
||||
vert.texcoord[1] /= vert.coord[3];
|
||||
vert.coord[0] = (vert.coord[0]+vertw) / (2*vertw);
|
||||
vert.coord[1] = (vert.coord[1]+vertw) / (2*vertw);
|
||||
vert.coord[2] = (vert.coord[2]+vertw) / (2*vertw);
|
||||
vert.texcoord[0] /= vertw;
|
||||
vert.texcoord[1] /= vertw;
|
||||
|
||||
//CONSIDER: do we need to guarantee that these are in bounds? perhaps not.
|
||||
//vert.coord[0] = max(0.0f,min(1.0f,vert.coord[0]));
|
||||
|
@ -1507,44 +1514,30 @@ template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms()
|
|||
//vert.coord[2] = max(0.0f,min(1.0f,vert.coord[2]));
|
||||
|
||||
//perspective-correct the colors
|
||||
vert.fcolor[0] /= vert.coord[3];
|
||||
vert.fcolor[1] /= vert.coord[3];
|
||||
vert.fcolor[2] /= vert.coord[3];
|
||||
vert.fcolor[0] /= vertw;
|
||||
vert.fcolor[1] /= vertw;
|
||||
vert.fcolor[2] /= vertw;
|
||||
|
||||
//viewport transformation
|
||||
VIEWPORT viewport;
|
||||
viewport.decode(poly.poly->viewport);
|
||||
vert.coord[0] *= viewport.width;
|
||||
vert.coord[0] += viewport.x;
|
||||
|
||||
// The maximum viewport y-value is 191. Values above 191 need to wrap
|
||||
// around and go negative.
|
||||
//
|
||||
// Test case: The Homie Rollerz character select screen sets the y-value
|
||||
// to 253, which then wraps around to -2.
|
||||
vert.coord[1] *= viewport.height;
|
||||
vert.coord[1] += viewport.y;
|
||||
vert.coord[1] += (viewport.y > 191) ? (viewport.y - 0xFF) : viewport.y;
|
||||
vert.coord[1] = 192 - 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
|
||||
//NOTE: you'd think we need >= 256 here, but that just isnt the way it works out (on softrasterizer) right now. coordinates @ 256.0 exactly will come in here.
|
||||
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;
|
||||
|
||||
//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;
|
||||
|
||||
vert.coord[0] *= xfactor;
|
||||
vert.coord[1] *= yfactor;
|
||||
vert.coord[0] *= wScalar;
|
||||
vert.coord[1] *= hScalar;
|
||||
}
|
||||
}
|
||||
}
|
||||
//these templates needed to be instantiated manually
|
||||
template void SoftRasterizerRenderer::performViewportTransforms<true>();
|
||||
template void SoftRasterizerRenderer::performViewportTransforms<false>();
|
||||
|
||||
void SoftRasterizerRenderer::performCoordAdjustment()
|
||||
{
|
||||
|
@ -1665,7 +1658,7 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
|
|||
}
|
||||
else
|
||||
{
|
||||
this->performViewportTransforms<false>();
|
||||
this->performViewportTransforms();
|
||||
this->performBackfaceTests();
|
||||
this->performCoordAdjustment();
|
||||
this->GetAndLoadAllTextures();
|
||||
|
|
|
@ -127,7 +127,7 @@ public:
|
|||
SoftRasterizerRenderer();
|
||||
virtual ~SoftRasterizerRenderer();
|
||||
|
||||
template<bool CUSTOM> void performViewportTransforms();
|
||||
void performViewportTransforms();
|
||||
void performBackfaceTests();
|
||||
void performCoordAdjustment();
|
||||
void GetAndLoadAllTextures();
|
||||
|
|
Loading…
Reference in New Issue