SoftRasterizer: Fix the animating characters in Customize status screen in Sands of Destruction by emulating a special LEQUAL depth test. (Fixes #41. Special thanks to StapleButter for his insight on this issue.)

This commit is contained in:
rogerman 2018-08-01 13:46:08 -07:00
parent c4317df76f
commit 36ee2477b1
4 changed files with 79 additions and 27 deletions

View File

@ -497,7 +497,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_shade(const PolygonMode polygonMode,
} }
} }
template<bool RENDERER> template<bool ISSHADOWPOLYGON> template<bool RENDERER> template<bool ISFRONTFACING, bool ISSHADOWPOLYGON>
FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z) FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z)
{ {
FragmentColor srcColor; FragmentColor srcColor;
@ -510,6 +510,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
u8 &dstAttributeStencil = this->_softRender->_framebufferAttributes->stencil[fragmentIndex]; u8 &dstAttributeStencil = this->_softRender->_framebufferAttributes->stencil[fragmentIndex];
u8 &dstAttributeIsFogged = this->_softRender->_framebufferAttributes->isFogged[fragmentIndex]; u8 &dstAttributeIsFogged = this->_softRender->_framebufferAttributes->isFogged[fragmentIndex];
u8 &dstAttributeIsTranslucentPoly = this->_softRender->_framebufferAttributes->isTranslucentPoly[fragmentIndex]; u8 &dstAttributeIsTranslucentPoly = this->_softRender->_framebufferAttributes->isTranslucentPoly[fragmentIndex];
u8 &dstAttributePolyFacing = this->_softRender->_framebufferAttributes->polyFacing[fragmentIndex];
// not sure about the w-buffer depth value: this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64 // not sure about the w-buffer depth value: this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64
// //
@ -520,9 +521,13 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
// run the depth test // run the depth test
bool depthFail = false; bool depthFail = false;
if (polyAttr.DepthEqualTest_Enable) if (polyAttr.DepthEqualTest_Enable)
{ {
const u32 minDepth = max<u32>(0x00000000, dstAttributeDepth - DEPTH_EQUALS_TEST_TOLERANCE); // The EQUAL depth test is used if the polygon requests it. Note that the NDS doesn't perform
// a true EQUAL test -- there is a set tolerance to it that makes it easier for pixels to
// pass the depth test.
const u32 minDepth = (u32)max<s32>(0x00000000, (s32)dstAttributeDepth - DEPTH_EQUALS_TEST_TOLERANCE);
const u32 maxDepth = min<u32>(0x00FFFFFF, dstAttributeDepth + DEPTH_EQUALS_TEST_TOLERANCE); const u32 maxDepth = min<u32>(0x00FFFFFF, dstAttributeDepth + DEPTH_EQUALS_TEST_TOLERANCE);
if (newDepth < minDepth || newDepth > maxDepth) if (newDepth < minDepth || newDepth > maxDepth)
@ -530,8 +535,21 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
depthFail = true; depthFail = true;
} }
} }
else if ( (ISFRONTFACING && (dstAttributePolyFacing == PolyFacing_Back)) && (dstColor.a == 0x1F))
{
// The LEQUAL test is used in the special case where an incoming front-facing polygon's pixel
// is to be drawn on top of a back-facing polygon's opaque pixel.
//
// Test case: The Customize status screen in Sands of Destruction requires this type of depth
// test in order to correctly show the animating characters.
if (newDepth > dstAttributeDepth)
{
depthFail = true;
}
}
else else
{ {
// The LESS depth test is the default type of depth test for all other conditions.
if (newDepth >= dstAttributeDepth) if (newDepth >= dstAttributeDepth)
{ {
depthFail = true; depthFail = true;
@ -624,13 +642,15 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable); dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable);
} }
dstAttributePolyFacing = (ISFRONTFACING) ? PolyFacing_Front : PolyFacing_Back;
//depth writing //depth writing
if (isOpaquePixel || polyAttr.TranslucentDepthWrite_Enable) if (isOpaquePixel || polyAttr.TranslucentDepthWrite_Enable)
dstAttributeDepth = newDepth; dstAttributeDepth = newDepth;
} }
//draws a single scanline //draws a single scanline
template<bool RENDERER> template<bool ISSHADOWPOLYGON, bool USELINEHACK> template<bool RENDERER> template<bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK>
FORCEINLINE void RasterizerUnit<RENDERER>::_drawscanline(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight) FORCEINLINE void RasterizerUnit<RENDERER>::_drawscanline(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight)
{ {
int XStart = pLeft->X; int XStart = pLeft->X;
@ -717,7 +737,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_drawscanline(const POLYGON_ATTR poly
while (width-- > 0) while (width-- > 0)
{ {
this->_pixel<ISSHADOWPOLYGON>(polyAttr, isTranslucent, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); this->_pixel<ISFRONTFACING, ISSHADOWPOLYGON>(polyAttr, isTranslucent, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z);
adr++; adr++;
x++; x++;
@ -732,7 +752,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_drawscanline(const POLYGON_ATTR poly
} }
//runs several scanlines, until an edge is finished //runs several scanlines, until an edge is finished
template<bool RENDERER> template<bool SLI, bool ISSHADOWPOLYGON, bool USELINEHACK, bool ISHORIZONTAL> template<bool RENDERER> template<bool SLI, bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK, bool ISHORIZONTAL>
void RasterizerUnit<RENDERER>::_runscanlines(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right) void RasterizerUnit<RENDERER>::_runscanlines(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right)
{ {
//oh lord, hack city for edge drawing //oh lord, hack city for edge drawing
@ -745,13 +765,13 @@ void RasterizerUnit<RENDERER>::_runscanlines(const POLYGON_ATTR polyAttr, const
if ( USELINEHACK && (left->Height == 0) && (right->Height == 0) && (left->Y < framebufferHeight) && (left->Y >= 0) ) if ( USELINEHACK && (left->Height == 0) && (right->Height == 0) && (left->Y < framebufferHeight) && (left->Y >= 0) )
{ {
const bool draw = ( !SLI || ((left->Y >= this->_SLI_startLine) && (left->Y < this->_SLI_endLine)) ); const bool draw = ( !SLI || ((left->Y >= this->_SLI_startLine) && (left->Y < this->_SLI_endLine)) );
if (draw) this->_drawscanline<ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right); if (draw) this->_drawscanline<ISFRONTFACING, ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right);
} }
while (Height--) while (Height--)
{ {
const bool draw = ( !SLI || ((left->Y >= this->_SLI_startLine) && (left->Y < this->_SLI_endLine)) ); const bool draw = ( !SLI || ((left->Y >= this->_SLI_startLine) && (left->Y < this->_SLI_endLine)) );
if (draw) this->_drawscanline<ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right); if (draw) this->_drawscanline<ISFRONTFACING, ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right);
const int xl = left->X; const int xl = left->X;
const int xr = right->X; const int xr = right->X;
const int y = left->Y; const int y = left->Y;
@ -834,11 +854,16 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_rot_verts()
//rotate verts until vert0.y is minimum, and then vert0.x is minimum in case of ties //rotate verts until vert0.y is minimum, and then vert0.x is minimum in case of ties
//this is a necessary precondition for our shape engine //this is a necessary precondition for our shape engine
template<bool RENDERER> template<bool ISBACKWARDS, int TYPE> template<bool RENDERER> template<bool ISFRONTFACING, int TYPE>
void RasterizerUnit<RENDERER>::_sort_verts() void RasterizerUnit<RENDERER>::_sort_verts()
{ {
//if the verts are backwards, reorder them first //if the verts are backwards, reorder them first
if (ISBACKWARDS) //
// At least... that's what the last comment says. But historically, we've
// always been using front-facing polygons the entire time, and so the
// comment should actually read, "if the verts are front-facing, reorder
// them first". So what is the real behavior for this? - rogerman, 2018/08/01
if (ISFRONTFACING)
for (size_t i = 0; i < TYPE/2; i++) for (size_t i = 0; i < TYPE/2; i++)
swap(this->_verts[i],this->_verts[TYPE-i-1]); swap(this->_verts[i],this->_verts[TYPE-i-1]);
@ -871,21 +896,21 @@ void RasterizerUnit<RENDERER>::_sort_verts()
//verts must be clockwise. //verts must be clockwise.
//I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before.
//Maybe it is like crow's algorithm //Maybe it is like crow's algorithm
template<bool RENDERER> template<bool SLI, bool ISBACKWARDS, bool ISSHADOWPOLYGON, bool USELINEHACK> template<bool RENDERER> template<bool SLI, bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK>
void RasterizerUnit<RENDERER>::_shape_engine(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type) void RasterizerUnit<RENDERER>::_shape_engine(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type)
{ {
bool failure = false; bool failure = false;
switch (type) switch (type)
{ {
case 3: this->_sort_verts<ISBACKWARDS, 3>(); break; case 3: this->_sort_verts<ISFRONTFACING, 3>(); break;
case 4: this->_sort_verts<ISBACKWARDS, 4>(); break; case 4: this->_sort_verts<ISFRONTFACING, 4>(); break;
case 5: this->_sort_verts<ISBACKWARDS, 5>(); break; case 5: this->_sort_verts<ISFRONTFACING, 5>(); break;
case 6: this->_sort_verts<ISBACKWARDS, 6>(); break; case 6: this->_sort_verts<ISFRONTFACING, 6>(); break;
case 7: this->_sort_verts<ISBACKWARDS, 7>(); break; case 7: this->_sort_verts<ISFRONTFACING, 7>(); break;
case 8: this->_sort_verts<ISBACKWARDS, 8>(); break; case 8: this->_sort_verts<ISFRONTFACING, 8>(); break;
case 9: this->_sort_verts<ISBACKWARDS, 9>(); break; case 9: this->_sort_verts<ISFRONTFACING, 9>(); break;
case 10: this->_sort_verts<ISBACKWARDS, 10>(); break; case 10: this->_sort_verts<ISFRONTFACING, 10>(); break;
default: printf("skipping type %d\n", type); return; default: printf("skipping type %d\n", type); return;
} }
@ -914,11 +939,11 @@ void RasterizerUnit<RENDERER>::_shape_engine(const POLYGON_ATTR polyAttr, const
const bool horizontal = (left.Y == right.Y); const bool horizontal = (left.Y == right.Y);
if (horizontal) if (horizontal)
{ {
this->_runscanlines<SLI, ISSHADOWPOLYGON, USELINEHACK, true>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right); this->_runscanlines<SLI, ISFRONTFACING, ISSHADOWPOLYGON, USELINEHACK, true>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right);
} }
else else
{ {
this->_runscanlines<SLI, ISSHADOWPOLYGON, USELINEHACK, false>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right); this->_runscanlines<SLI, ISFRONTFACING, ISSHADOWPOLYGON, USELINEHACK, false>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right);
} }
//if we ran out of an edge, step to the next one //if we ran out of an edge, step to the next one
@ -2153,6 +2178,7 @@ Render3DError SoftRasterizerRenderer::ClearUsingImage(const u16 *__restrict colo
this->_framebufferAttributes->opaquePolyID[iw] = polyIDBuffer[ir]; this->_framebufferAttributes->opaquePolyID[iw] = polyIDBuffer[ir];
this->_framebufferAttributes->translucentPolyID[iw] = kUnsetTranslucentPolyID; this->_framebufferAttributes->translucentPolyID[iw] = kUnsetTranslucentPolyID;
this->_framebufferAttributes->isTranslucentPoly[iw] = 0; this->_framebufferAttributes->isTranslucentPoly[iw] = 0;
this->_framebufferAttributes->polyFacing[iw] = PolyFacing_Unwritten;
this->_framebufferAttributes->stencil[iw] = 0; this->_framebufferAttributes->stencil[iw] = 0;
} }
} }
@ -2480,6 +2506,7 @@ void SoftRasterizerRenderer_AVX2::LoadClearValues(const FragmentColor &clearColo
this->_clearAttrStencil_v256u8 = _mm256_set1_epi8(clearAttributes.stencil); this->_clearAttrStencil_v256u8 = _mm256_set1_epi8(clearAttributes.stencil);
this->_clearAttrIsFogged_v256u8 = _mm256_set1_epi8(clearAttributes.isFogged); this->_clearAttrIsFogged_v256u8 = _mm256_set1_epi8(clearAttributes.isFogged);
this->_clearAttrIsTranslucentPoly_v256u8 = _mm256_set1_epi8(clearAttributes.isTranslucentPoly); this->_clearAttrIsTranslucentPoly_v256u8 = _mm256_set1_epi8(clearAttributes.isTranslucentPoly);
this->_clearAttrPolyFacing_v256u8 = _mm256_set1_epi8(clearAttributes.polyFacing);
} }
void SoftRasterizerRenderer_AVX2::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel) void SoftRasterizerRenderer_AVX2::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel)
@ -2501,6 +2528,7 @@ void SoftRasterizerRenderer_AVX2::ClearUsingValues_Execute(const size_t startPix
_mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->stencil + i), this->_clearAttrStencil_v256u8); _mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->stencil + i), this->_clearAttrStencil_v256u8);
_mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->isFogged + i), this->_clearAttrIsFogged_v256u8); _mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->isFogged + i), this->_clearAttrIsFogged_v256u8);
_mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->isTranslucentPoly + i), this->_clearAttrIsTranslucentPoly_v256u8); _mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->isTranslucentPoly + i), this->_clearAttrIsTranslucentPoly_v256u8);
_mm256_stream_si256((v256u8 *)(this->_framebufferAttributes->polyFacing + i), this->_clearAttrPolyFacing_v256u8);
} }
} }
@ -2515,6 +2543,7 @@ void SoftRasterizerRenderer_SSE2::LoadClearValues(const FragmentColor &clearColo
this->_clearAttrStencil_v128u8 = _mm_set1_epi8(clearAttributes.stencil); this->_clearAttrStencil_v128u8 = _mm_set1_epi8(clearAttributes.stencil);
this->_clearAttrIsFogged_v128u8 = _mm_set1_epi8(clearAttributes.isFogged); this->_clearAttrIsFogged_v128u8 = _mm_set1_epi8(clearAttributes.isFogged);
this->_clearAttrIsTranslucentPoly_v128u8 = _mm_set1_epi8(clearAttributes.isTranslucentPoly); this->_clearAttrIsTranslucentPoly_v128u8 = _mm_set1_epi8(clearAttributes.isTranslucentPoly);
this->_clearAttrPolyFacing_v128u8 = _mm_set1_epi8(clearAttributes.polyFacing);
} }
void SoftRasterizerRenderer_SSE2::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel) void SoftRasterizerRenderer_SSE2::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel)
@ -2536,6 +2565,7 @@ void SoftRasterizerRenderer_SSE2::ClearUsingValues_Execute(const size_t startPix
_mm_stream_si128((v128u8 *)(this->_framebufferAttributes->stencil + i), this->_clearAttrStencil_v128u8); _mm_stream_si128((v128u8 *)(this->_framebufferAttributes->stencil + i), this->_clearAttrStencil_v128u8);
_mm_stream_si128((v128u8 *)(this->_framebufferAttributes->isFogged + i), this->_clearAttrIsFogged_v128u8); _mm_stream_si128((v128u8 *)(this->_framebufferAttributes->isFogged + i), this->_clearAttrIsFogged_v128u8);
_mm_stream_si128((v128u8 *)(this->_framebufferAttributes->isTranslucentPoly + i), this->_clearAttrIsTranslucentPoly_v128u8); _mm_stream_si128((v128u8 *)(this->_framebufferAttributes->isTranslucentPoly + i), this->_clearAttrIsTranslucentPoly_v128u8);
_mm_stream_si128((v128u8 *)(this->_framebufferAttributes->polyFacing + i), this->_clearAttrPolyFacing_v128u8);
} }
} }
@ -2570,6 +2600,11 @@ void SoftRasterizerRenderer_Altivec::LoadClearValues(const FragmentColor &clearC
clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly, clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,
clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly, clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,
clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly}; clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly,clearAttributes.isTranslucentPoly};
this->_clearAttrPolyFacing_v128u8 = (v128u8){clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,
clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,
clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,
clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing,clearAttributes.polyFacing};
} }
void SoftRasterizerRenderer_Altivec::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel) void SoftRasterizerRenderer_Altivec::ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel)
@ -2591,6 +2626,7 @@ void SoftRasterizerRenderer_Altivec::ClearUsingValues_Execute(const size_t start
vec_st(this->_clearAttrStencil_v128u8, i, this->_framebufferAttributes->stencil); vec_st(this->_clearAttrStencil_v128u8, i, this->_framebufferAttributes->stencil);
vec_st(this->_clearAttrIsFogged_v128u8, i, this->_framebufferAttributes->isFogged); vec_st(this->_clearAttrIsFogged_v128u8, i, this->_framebufferAttributes->isFogged);
vec_st(this->_clearAttrIsTranslucentPoly_v128u8, i, this->_framebufferAttributes->isTranslucentPoly); vec_st(this->_clearAttrIsTranslucentPoly_v128u8, i, this->_framebufferAttributes->isTranslucentPoly);
vec_st(this->_clearAttrPolyFacing_v128u8, i, this->_framebufferAttributes->polyFacing);
} }
} }

View File

@ -111,13 +111,13 @@ protected:
FORCEINLINE float _round_s(double val); FORCEINLINE float _round_s(double val);
template<bool ISSHADOWPOLYGON> FORCEINLINE void _shade(const PolygonMode polygonMode, const FragmentColor src, FragmentColor &dst, const float texCoordU, const float texCoordV); template<bool ISSHADOWPOLYGON> FORCEINLINE void _shade(const PolygonMode polygonMode, const FragmentColor src, FragmentColor &dst, const float texCoordU, const float texCoordV);
template<bool ISSHADOWPOLYGON> FORCEINLINE void _pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z); template<bool ISFRONTFACING, bool ISSHADOWPOLYGON> FORCEINLINE void _pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z);
template<bool ISSHADOWPOLYGON, bool USELINEHACK> FORCEINLINE void _drawscanline(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight); template<bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK> FORCEINLINE void _drawscanline(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight);
template<bool SLI, bool ISSHADOWPOLYGON, bool USELINEHACK, bool ISHORIZONTAL> void _runscanlines(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right); template<bool SLI, bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK, bool ISHORIZONTAL> void _runscanlines(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right);
template<int TYPE> FORCEINLINE void _rot_verts(); template<int TYPE> FORCEINLINE void _rot_verts();
template<bool ISBACKWARDS, int TYPE> void _sort_verts(); template<bool ISFRONTFACING, int TYPE> void _sort_verts();
template<bool SLI, bool ISBACKWARDS, bool ISSHADOWPOLYGON, bool USELINEHACK> void _shape_engine(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type); template<bool SLI, bool ISFRONTFACING, bool ISSHADOWPOLYGON, bool USELINEHACK> void _shape_engine(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type);
public: public:
void SetSLI(u32 startLine, u32 endLine, bool debug); void SetSLI(u32 startLine, u32 endLine, bool debug);
@ -225,6 +225,7 @@ protected:
v256u8 _clearAttrStencil_v256u8; v256u8 _clearAttrStencil_v256u8;
v256u8 _clearAttrIsFogged_v256u8; v256u8 _clearAttrIsFogged_v256u8;
v256u8 _clearAttrIsTranslucentPoly_v256u8; v256u8 _clearAttrIsTranslucentPoly_v256u8;
v256u8 _clearAttrPolyFacing_v256u8;
#elif defined(ENABLE_SSE2) || defined(ENABLE_ALTIVEC) #elif defined(ENABLE_SSE2) || defined(ENABLE_ALTIVEC)
v128u32 _clearColor_v128u32; v128u32 _clearColor_v128u32;
v128u32 _clearDepth_v128u32; v128u32 _clearDepth_v128u32;
@ -233,6 +234,7 @@ protected:
v128u8 _clearAttrStencil_v128u8; v128u8 _clearAttrStencil_v128u8;
v128u8 _clearAttrIsFogged_v128u8; v128u8 _clearAttrIsFogged_v128u8;
v128u8 _clearAttrIsTranslucentPoly_v128u8; v128u8 _clearAttrIsTranslucentPoly_v128u8;
v128u8 _clearAttrPolyFacing_v128u8;
#endif #endif
virtual void LoadClearValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes) = 0; virtual void LoadClearValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes) = 0;

View File

@ -91,6 +91,7 @@ FragmentAttributesBuffer::FragmentAttributesBuffer(size_t newCount)
stencil = (u8 *)malloc_alignedCacheLine(count * sizeof(u8)); stencil = (u8 *)malloc_alignedCacheLine(count * sizeof(u8));
isFogged = (u8 *)malloc_alignedCacheLine(count * sizeof(u8)); isFogged = (u8 *)malloc_alignedCacheLine(count * sizeof(u8));
isTranslucentPoly = (u8 *)malloc_alignedCacheLine(count * sizeof(u8)); isTranslucentPoly = (u8 *)malloc_alignedCacheLine(count * sizeof(u8));
polyFacing = (u8 *)malloc_alignedCacheLine(count * sizeof(u8));
} }
FragmentAttributesBuffer::~FragmentAttributesBuffer() FragmentAttributesBuffer::~FragmentAttributesBuffer()
@ -101,6 +102,7 @@ FragmentAttributesBuffer::~FragmentAttributesBuffer()
free_aligned(stencil); free_aligned(stencil);
free_aligned(isFogged); free_aligned(isFogged);
free_aligned(isTranslucentPoly); free_aligned(isTranslucentPoly);
free_aligned(polyFacing);
} }
void FragmentAttributesBuffer::SetAtIndex(const size_t index, const FragmentAttributes &attr) void FragmentAttributesBuffer::SetAtIndex(const size_t index, const FragmentAttributes &attr)
@ -111,6 +113,7 @@ void FragmentAttributesBuffer::SetAtIndex(const size_t index, const FragmentAttr
this->stencil[index] = attr.stencil; this->stencil[index] = attr.stencil;
this->isFogged[index] = attr.isFogged; this->isFogged[index] = attr.isFogged;
this->isTranslucentPoly[index] = attr.isTranslucentPoly; this->isTranslucentPoly[index] = attr.isTranslucentPoly;
this->polyFacing[index] = attr.polyFacing;
} }
Render3DTexture::Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes) Render3DTexture::Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
@ -502,6 +505,7 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState)
clearFragment.depth = renderState.clearDepth; clearFragment.depth = renderState.clearDepth;
clearFragment.stencil = 0; clearFragment.stencil = 0;
clearFragment.isTranslucentPoly = 0; clearFragment.isTranslucentPoly = 0;
clearFragment.polyFacing = PolyFacing_Unwritten;
clearFragment.isFogged = BIT15(clearColorSwapped); clearFragment.isFogged = BIT15(clearColorSwapped);
if (renderState.enableClearImage) if (renderState.enableClearImage)
@ -693,6 +697,7 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState)
clearFragment.depth = renderState.clearDepth; clearFragment.depth = renderState.clearDepth;
clearFragment.stencil = 0; clearFragment.stencil = 0;
clearFragment.isTranslucentPoly = 0; clearFragment.isTranslucentPoly = 0;
clearFragment.polyFacing = PolyFacing_Unwritten;
clearFragment.isFogged = BIT15(renderState.clearColor); clearFragment.isFogged = BIT15(renderState.clearColor);
if (renderState.enableClearImage) if (renderState.enableClearImage)

View File

@ -68,6 +68,13 @@ enum RendererID
enum Render3DErrorCode enum Render3DErrorCode
{ {
RENDER3DERROR_NOERR = 0 RENDER3DERROR_NOERR = 0
};
enum PolyFacing
{
PolyFacing_Unwritten = 0,
PolyFacing_Front = 1,
PolyFacing_Back = 2
}; };
typedef int Render3DError; typedef int Render3DError;
@ -79,7 +86,8 @@ struct FragmentAttributes
u8 translucentPolyID; u8 translucentPolyID;
u8 stencil; u8 stencil;
u8 isFogged; u8 isFogged;
u8 isTranslucentPoly; u8 isTranslucentPoly;
u8 polyFacing;
}; };
struct FragmentAttributesBuffer struct FragmentAttributesBuffer
@ -90,7 +98,8 @@ struct FragmentAttributesBuffer
u8 *translucentPolyID; u8 *translucentPolyID;
u8 *stencil; u8 *stencil;
u8 *isFogged; u8 *isFogged;
u8 *isTranslucentPoly; u8 *isTranslucentPoly;
u8 *polyFacing;
FragmentAttributesBuffer(size_t newCount); FragmentAttributesBuffer(size_t newCount);
~FragmentAttributesBuffer(); ~FragmentAttributesBuffer();