GFX3D: Rework polygon attributes and texture parameters using the latest coding style. Also improve the performance of SoftRasterizer while we’re at it.

This commit is contained in:
rogerman 2017-10-06 17:13:08 -07:00
parent e7d63e6cd2
commit c6a5740665
12 changed files with 449 additions and 512 deletions

View File

@ -693,7 +693,7 @@ static void OGLGetDriverVersion(const char *oglVersionString,
}
}
OpenGLTexture::OpenGLTexture(u32 texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes)
OpenGLTexture::OpenGLTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes)
{
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp);
_invSizeS = 1.0f / (float)_sizeS;
@ -1523,7 +1523,7 @@ OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly,
}
template <OGLPolyDrawMode DRAWMODE>
size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr)
size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -1550,7 +1550,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
// Set up the initial polygon
const POLY &initialPoly = polyList->list[indexList->list[firstIndex]];
u32 lastTexParams = initialPoly.texParam;
TEXIMAGE_PARAM lastTexParams = initialPoly.texParam;
u32 lastTexPalette = initialPoly.texPalette;
u32 lastViewport = initialPoly.viewport;
@ -1566,14 +1566,14 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
const POLY &thePoly = polyList->list[indexList->list[i]];
// Set up the polygon if it changed
if (lastPolyAttr != thePoly.polyAttr)
if (lastPolyAttr.value != thePoly.attribute.value)
{
lastPolyAttr = thePoly.polyAttr;
lastPolyAttr = thePoly.attribute;
this->SetupPolygon(thePoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass));
}
// Set up the texture if it changed
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette)
{
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
@ -1602,17 +1602,17 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
// the same and we're not drawing a line loop or line strip.
if (i+1 <= lastIndex)
{
const POLY *nextPoly = &polyList->list[indexList->list[i+1]];
const POLY &nextPoly = polyList->list[indexList->list[i+1]];
if (lastPolyAttr == nextPoly->polyAttr &&
lastTexParams == nextPoly->texParam &&
lastTexPalette == nextPoly->texPalette &&
lastViewport == nextPoly->viewport &&
polyPrimitive == oglPrimitiveType[nextPoly->vtxFormat] &&
if (lastPolyAttr.value == nextPoly.attribute.value &&
lastTexParams.value == nextPoly.texParam.value &&
lastTexPalette == nextPoly.texPalette &&
lastViewport == nextPoly.viewport &&
polyPrimitive == oglPrimitiveType[nextPoly.vtxFormat] &&
polyPrimitive != GL_LINE_LOOP &&
polyPrimitive != GL_LINE_STRIP &&
oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_LOOP &&
oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_STRIP)
oglPrimitiveType[nextPoly.vtxFormat] != GL_LINE_LOOP &&
oglPrimitiveType[nextPoly.vtxFormat] != GL_LINE_STRIP)
{
continue;
}
@ -1621,22 +1621,22 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
// Render the polygons
this->SetPolygonIndex(i);
if (thePoly.getAttributePolygonMode() == POLYGON_MODE_SHADOW)
if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW)
{
if (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass)
{
this->DrawShadowPolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.getAttributePolygonID());
this->DrawShadowPolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.attribute.PolygonID);
}
}
else if ( (thePoly.getTexParamTexFormat() == TEXMODE_A3I5) || (thePoly.getTexParamTexFormat() == TEXMODE_A5I3) )
else if ( (thePoly.texParam.PackedFormat == TEXMODE_A3I5) || (thePoly.texParam.PackedFormat == TEXMODE_A5I3) )
{
if (DRAWMODE == OGLPolyDrawMode_ZeroAlphaPass)
{
this->DrawAlphaTexturePolygon<false>(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque());
this->DrawAlphaTexturePolygon<false>(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque());
}
else
{
this->DrawAlphaTexturePolygon<true>(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque());
this->DrawAlphaTexturePolygon<true>(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque());
}
}
else
@ -3265,7 +3265,7 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr)
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -3618,7 +3618,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
}
else
{
const GLfloat thePolyAlpha = (thePoly->isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly->getAttributeAlpha()];
const GLfloat thePolyAlpha = (thePoly->isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly->attribute.Alpha];
for (size_t j = 0; j < polyType; j++)
{
@ -3692,7 +3692,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
size_t indexOffset = 0;
const POLY &firstPoly = polyList->list[indexList->list[0]];
u32 lastPolyAttr = firstPoly.polyAttr;
POLYGON_ATTR lastPolyAttr = firstPoly.attribute;
if (polyList->opaqueCount > 0)
{
@ -3714,7 +3714,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
if (polyList->opaqueCount > 0)
{
const POLY &lastOpaquePoly = polyList->list[indexList->list[polyList->opaqueCount - 1]];
lastPolyAttr = lastOpaquePoly.polyAttr;
lastPolyAttr = lastOpaquePoly.attribute;
this->SetupPolygon(lastOpaquePoly, false, true);
}
}
@ -4098,15 +4098,13 @@ void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index)
Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer)
{
const PolygonAttributes attr = thePoly.getAttributes();
// Set up depth test mode
static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL};
glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]);
glDepthFunc(oglDepthFunc[thePoly.attribute.DepthEqualTest_Enable]);
// Set up culling mode
static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0};
GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode];
GLenum cullingMode = oglCullingMode[thePoly.attribute.SurfaceCullingMode];
if (cullingMode == 0)
{
@ -4121,13 +4119,13 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
if (willChangeStencilBuffer)
{
// Handle drawing states for the polygon
if (attr.polygonMode == POLYGON_MODE_SHADOW)
if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW)
{
// Set up shadow polygon states.
//
// See comments in DrawShadowPolygon() for more information about
// how this 4-pass process works in OpenGL.
if (attr.polygonID == 0)
if (thePoly.attribute.PolygonID == 0)
{
// 1st pass: Mark stencil buffer bits (0x40) with the shadow polygon volume.
// Bits are only marked on depth-fail.
@ -4140,7 +4138,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
// 2nd pass: Mark stencil buffer bits (0x80) with the result of the polygon ID
// check. Bits are marked if the polygon ID of this polygon differs from the
// one in the stencil buffer.
glStencilFunc(GL_NOTEQUAL, 0x80 | attr.polygonID, 0x3F);
glStencilFunc(GL_NOTEQUAL, 0x80 | thePoly.attribute.PolygonID, 0x3F);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x80);
}
@ -4150,12 +4148,12 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
}
else
{
glStencilFunc(GL_ALWAYS, attr.polygonID, 0x3F);
glStencilFunc(GL_ALWAYS, thePoly.attribute.PolygonID, 0x3F);
glStencilOp(GL_KEEP, GL_KEEP, (treatAsTranslucent) ? GL_KEEP : GL_REPLACE);
glStencilMask(0xFF); // Drawing non-shadow polygons will implicitly reset the stencil buffer bits
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask((!treatAsTranslucent || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
glDepthMask((!treatAsTranslucent || thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE);
}
}
@ -4163,18 +4161,18 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
if (this->isShaderSupported)
{
OGLRenderRef &OGLRef = *this->ref;
glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (attr.isWireframe) ? 1.0f : divide5bitBy31_LUT[attr.alpha]);
glUniform1i(OGLRef.uniformPolyID, attr.polygonID);
glUniform1i(OGLRef.uniformPolyIsWireframe, (attr.isWireframe) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolyMode, thePoly.attribute.Mode);
glUniform1i(OGLRef.uniformPolyEnableFog, (thePoly.attribute.Fog_Enable) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (thePoly.isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha]);
glUniform1i(OGLRef.uniformPolyID, thePoly.attribute.PolygonID);
glUniform1i(OGLRef.uniformPolyIsWireframe, (thePoly.isWireframe()) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE);
}
else
{
// Set the texture blending mode
static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE};
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[thePoly.attribute.Mode]);
}
return OGLERROR_NOERR;
@ -4202,8 +4200,6 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR
return OGLERROR_NOERR;
}
const PolygonTexParams texParams = thePoly.getTexParams();
// Enable textures if they weren't already enabled
if (this->isShaderSupported)
@ -4221,8 +4217,8 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR
}
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (this->_textureSmooth)
{
@ -4687,14 +4683,12 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, size_t polyR
return OGLERROR_NOERR;
}
const PolygonTexParams texParams = thePoly.getTexParams();
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (this->_textureSmooth)
{
@ -4748,6 +4742,6 @@ Render3DError OpenGLRenderer_2_1::RenderFlush(bool willFlushBuffer32, bool willF
return RENDER3DERROR_NOERR;
}
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);

View File

@ -601,7 +601,7 @@ protected:
u32 *_upscaleBuffer;
public:
OpenGLTexture(u32 texAttributes, u32 palAttributes);
OpenGLTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes);
virtual ~OpenGLTexture();
virtual void Load(bool isNewTexture);
@ -657,7 +657,7 @@ protected:
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16);
OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template<bool WILLUPDATESTENCILBUFFER> Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool enableAlphaDepthWrite, const bool isTranslucent, const bool canHaveOpaqueFragments);
// OpenGL-specific methods
@ -773,7 +773,7 @@ protected:
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError DownsampleFBO();
virtual Render3DError ReadBackPixels();

View File

@ -1350,7 +1350,7 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr)
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -1612,19 +1612,19 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
for (size_t i = 0; i < engine.polylist->count; i++)
{
const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]];
const size_t polyType = thePoly->type;
const POLY &thePoly = engine.polylist->list[engine.indexlist.list[i]];
const size_t polyType = thePoly.type;
for (size_t j = 0; j < polyType; j++)
{
const GLushort vertIndex = thePoly->vertIndexes[j];
const GLushort vertIndex = thePoly.vertIndexes[j];
// While we're looping through our vertices, add each vertex index to
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
indexPtr[vertIndexCount++] = vertIndex;
if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP)
if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)
{
if (j == 2)
{
@ -1632,26 +1632,24 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
}
else if (j == 3)
{
indexPtr[vertIndexCount++] = thePoly->vertIndexes[0];
indexPtr[vertIndexCount++] = thePoly.vertIndexes[0];
}
}
}
this->_textureList[i] = this->GetLoadedTextureFromPolygon(*thePoly, engine.renderState.enableTexturing);
this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, engine.renderState.enableTexturing);
const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat();
const PolygonAttributes polyAttr = thePoly->getAttributes();
const PolygonTexParams texParams = thePoly->getTexParams();
polyStates[i].enableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? GL_TRUE : GL_FALSE;
polyStates[i].enableFog = (polyAttr.enableRenderFog) ? GL_TRUE : GL_FALSE;
polyStates[i].isWireframe = (polyAttr.isWireframe) ? GL_TRUE : GL_FALSE;
polyStates[i].setNewDepthForTranslucent = (polyAttr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
polyStates[i].polyAlpha = (polyAttr.isWireframe) ? 0x1F : polyAttr.alpha;
polyStates[i].polyMode = polyAttr.polygonMode;
polyStates[i].polyID = polyAttr.polygonID;
polyStates[i].texSizeS = texParams.sizeS; // Note that we are using the packed version of sizeS
polyStates[i].texSizeT = texParams.sizeT; // Note that we are using the packed version of sizeT
polyStates[i].enableFog = (thePoly.attribute.Fog_Enable) ? GL_TRUE : GL_FALSE;
polyStates[i].isWireframe = (thePoly.isWireframe()) ? GL_TRUE : GL_FALSE;
polyStates[i].setNewDepthForTranslucent = (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE;
polyStates[i].polyAlpha = (thePoly.isWireframe()) ? 0x1F : thePoly.attribute.Alpha;
polyStates[i].polyMode = thePoly.attribute.Mode;
polyStates[i].polyID = thePoly.attribute.PolygonID;
polyStates[i].texSizeS = thePoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S
polyStates[i].texSizeT = thePoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T
polyStates[i].texSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE;
}
@ -1860,15 +1858,13 @@ void OpenGLRenderer_3_2::SetPolygonIndex(const size_t index)
Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer)
{
const PolygonAttributes attr = thePoly.getAttributes();
// Set up depth test mode
static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL};
glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]);
glDepthFunc(oglDepthFunc[thePoly.attribute.DepthEqualTest_Enable]);
// Set up culling mode
static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0};
GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode];
GLenum cullingMode = oglCullingMode[thePoly.attribute.SurfaceCullingMode];
if (cullingMode == 0)
{
@ -1883,13 +1879,13 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs
if (willChangeStencilBuffer)
{
// Handle drawing states for the polygon
if (attr.polygonMode == POLYGON_MODE_SHADOW)
if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW)
{
// Set up shadow polygon states.
//
// See comments in DrawShadowPolygon() for more information about
// how this 4-pass process works in OpenGL.
if (attr.polygonID == 0)
if (thePoly.attribute.PolygonID == 0)
{
// 1st pass: Mark stencil buffer bits (0x40) with the shadow polygon volume.
// Bits are only marked on depth-fail.
@ -1902,7 +1898,7 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs
// 2nd pass: Mark stencil buffer bits (0x80) with the result of the polygon ID
// check. Bits are marked if the polygon ID of this polygon differs from the
// one in the stencil buffer.
glStencilFunc(GL_NOTEQUAL, 0x80 | attr.polygonID, 0x3F);
glStencilFunc(GL_NOTEQUAL, 0x80 | thePoly.attribute.PolygonID, 0x3F);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x80);
}
@ -1912,12 +1908,12 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs
}
else
{
glStencilFunc(GL_ALWAYS, attr.polygonID, 0x3F);
glStencilFunc(GL_ALWAYS, thePoly.attribute.PolygonID, 0x3F);
glStencilOp(GL_KEEP, GL_KEEP, (treatAsTranslucent) ? GL_KEEP : GL_REPLACE);
glStencilMask(0xFF); // Drawing non-shadow polygons will implicitly reset the stencil buffer bits
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask((!treatAsTranslucent || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
glDepthMask((!treatAsTranslucent || thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE);
}
}
@ -1934,11 +1930,9 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, size_t polyR
return OGLERROR_NOERR;
}
PolygonTexParams texParams = thePoly.getTexParams();
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (this->_textureSmooth)
{

View File

@ -85,7 +85,7 @@ protected:
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError DownsampleFBO();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine);

View File

@ -334,7 +334,10 @@ static CACHE_ALIGN u16 BTcoords[6] = {0, 0, 0, 0, 0, 0};
static CACHE_ALIGN float PTcoords[4] = {0.0, 0.0, 0.0, 1.0};
//raw ds format poly attributes
static u32 polyAttr=0,textureFormat=0, texturePalette=0, polyAttrPending=0;
static POLYGON_ATTR polyAttrInProcess;
static POLYGON_ATTR currentPolyAttr;
static TEXIMAGE_PARAM currentPolyTexParam;
static u32 currentPolyTexPalette = 0;
//the current vertex color, 5bit values
static u8 colorRGB[4] = { 31,31,31,31 };
@ -351,11 +354,9 @@ static u8 shininessInd = 0;
//-----------cached things:
//these dont need to go into the savestate. they can be regenerated from HW registers
//from polygonattr:
static unsigned int cullingMask=0;
static u32 envMode=0;
static u32 lightMask=0;
//other things:
static int texCoordinateTransform = 0;
static TextureTransformationMode texCoordTransformMode = TextureTransformationMode_None;
static CACHE_ALIGN s32 cacheLightDirection[4][4];
static CACHE_ALIGN s32 cacheHalfVector[4][4];
//------------------
@ -438,8 +439,8 @@ void POLY::save(EMUFILE &os)
os.write_16LE(vertIndexes[1]);
os.write_16LE(vertIndexes[2]);
os.write_16LE(vertIndexes[3]);
os.write_32LE(polyAttr);
os.write_32LE(texParam);
os.write_32LE(attribute.value);
os.write_32LE(texParam.value);
os.write_32LE(texPalette);
os.write_32LE(viewport);
os.write_floatLE(miny);
@ -456,8 +457,8 @@ void POLY::load(EMUFILE &is)
is.read_16LE(vertIndexes[1]);
is.read_16LE(vertIndexes[2]);
is.read_16LE(vertIndexes[3]);
is.read_32LE(polyAttr);
is.read_32LE(texParam);
is.read_32LE(attribute.value);
is.read_32LE(texParam.value);
is.read_32LE(texPalette);
is.read_32LE(viewport);
is.read_floatLE(miny);
@ -497,6 +498,10 @@ void VERT::load(EMUFILE &is)
void gfx3d_init()
{
polyAttrInProcess.value = 0;
currentPolyAttr.value = 0;
currentPolyTexParam.value = 0;
gxf_hardware.reset();
//gxf_hardware.test();
int zzz=9;
@ -584,10 +589,10 @@ void gfx3d_reset()
gfx3d.vertList = vertList;
gfx3d.vertListCount = vertListCount[listTwiddle];
polyAttr = 0;
textureFormat = 0;
texturePalette = 0;
polyAttrPending = 0;
polyAttrInProcess.value = 0;
currentPolyAttr.value = 0;
currentPolyTexParam.value = 0;
currentPolyTexPalette = 0;
mode = MATRIXMODE_PROJECTION;
s16coord[0] = s16coord[1] = s16coord[2] = s16coord[3] = 0;
coordind = 0;
@ -717,7 +722,7 @@ static void SetVertex()
DS_ALIGN(16) s32 coordTransformed[4] = { coord[0], coord[1], coord[2], (1<<12) };
if (texCoordinateTransform == 3)
if (texCoordTransformMode == TextureTransformationMode_VertexSource)
{
//Tested by: Eledees The Adventures of Kai and Zero (E) [title screen and frontend menus]
last_s = (s32)(((s64)s16coord[0] * mtxCurrent[3][0] +
@ -869,7 +874,7 @@ static void SetVertex()
// Line segment detect
// Tested" Castlevania POR - warp stone, trajectory of ricochet, "Eye of Decay"
if (!(textureFormat & (7 << 26))) // no texture
if (currentPolyTexParam.PackedFormat == TEXMODE_NONE)
{
bool duplicated = false;
const VERT &vert0 = vertList[poly.vertIndexes[0]];
@ -889,9 +894,9 @@ static void SetVertex()
}
}
poly.polyAttr = polyAttr;
poly.texParam = textureFormat;
poly.texPalette = texturePalette;
poly.attribute = polyAttrInProcess;
poly.texParam = currentPolyTexParam;
poly.texPalette = currentPolyTexPalette;
poly.viewport = viewport;
polylist->count++;
}
@ -901,18 +906,12 @@ static void SetVertex()
static void gfx3d_glPolygonAttrib_cache()
{
// Light enable/disable
lightMask = (polyAttr&0xF);
// texture environment
envMode = (polyAttr&0x30)>>4;
// back face culling
cullingMask = (polyAttr>>6)&3;
lightMask = polyAttrInProcess.LightMask;
}
static void gfx3d_glTexImage_cache()
{
texCoordinateTransform = (textureFormat>>30);
texCoordTransformMode = (TextureTransformationMode)currentPolyTexParam.TexCoordTransformMode;
}
static void gfx3d_glLightDirection_cache(const size_t index)
@ -1292,7 +1291,7 @@ static void gfx3d_glNormal(s32 v)
CACHE_ALIGN s32 normal[4] = { nx,ny,nz,(1<<12) };
if (texCoordinateTransform == 2)
if (texCoordTransformMode == TextureTransformationMode_NormalSource)
{
//SM64 highlight rendered star in main menu tests this
//also smackdown 2010 player textures tested this (needed cast on _s and _t)
@ -1391,13 +1390,13 @@ static void gfx3d_glTexCoord(s32 val)
_s = ((val<<16)>>16);
_t = (val>>16);
if (texCoordinateTransform == 1)
if (texCoordTransformMode == TextureTransformationMode_TexCoordSource)
{
//dragon quest 4 overworld will test this
last_s = (s32) (( (s64)_s * mtxCurrent[3][0] + (s64)_t * mtxCurrent[3][4] + (s64)mtxCurrent[3][8] + (s64)mtxCurrent[3][12])>>12);
last_t = (s32) (( (s64)_s * mtxCurrent[3][1] + (s64)_t * mtxCurrent[3][5] + (s64)mtxCurrent[3][9] + (s64)mtxCurrent[3][13])>>12);
}
else if(texCoordinateTransform == 0)
else if (texCoordTransformMode == TextureTransformationMode_None)
{
last_s=_s;
last_t=_t;
@ -1469,20 +1468,20 @@ static void gfx3d_glPolygonAttrib (u32 val)
//PROGINFO("Set polyattr in the middle of a begin/end pair.\n (This won't be activated until the next begin)\n");
//TODO - we need some some similar checking for teximageparam etc.
}
polyAttrPending = val;
currentPolyAttr.value = val;
GFX_DELAY(1);
}
static void gfx3d_glTexImage(u32 val)
{
textureFormat = val;
currentPolyTexParam.value = val;
gfx3d_glTexImage_cache();
GFX_DELAY(1);
}
static void gfx3d_glTexPalette(u32 val)
{
texturePalette = val;
currentPolyTexPalette = val;
GFX_DELAY(1);
}
@ -1558,7 +1557,7 @@ static void gfx3d_glBegin(u32 v)
triStripToggle = 0;
tempVertInfo.count = 0;
tempVertInfo.first = true;
polyAttr = polyAttrPending;
polyAttrInProcess = currentPolyAttr;
gfx3d_glPolygonAttrib_cache();
GFX_DELAY(1);
}
@ -2529,11 +2528,11 @@ void gfx3d_glGetLightColor(const size_t index, u32 &dst)
SFORMAT SF_GFX3D[]={
{ "GCTL", 4, 1, &gfx3d.state.savedDISP3DCNT},
{ "GPAT", 4, 1, &polyAttr},
{ "GPAP", 4, 1, &polyAttrPending},
{ "GPAT", 4, 1, &polyAttrInProcess.value},
{ "GPAP", 4, 1, &currentPolyAttr.value},
{ "GINB", 4, 1, &inBegin},
{ "GTFM", 4, 1, &textureFormat},
{ "GTPA", 4, 1, &texturePalette},
{ "GTFM", 4, 1, &currentPolyTexParam.value},
{ "GTPA", 4, 1, &currentPolyTexPalette},
{ "GMOD", 4, 1, &mode},
{ "GMTM", 4,16, mtxTemporal},
{ "GMCU", 4,64, mtxCurrent},

View File

@ -114,77 +114,6 @@ enum PolygonType
POLYGON_TYPE_QUAD = 4
};
// POLYGON ATTRIBUTES - BIT LOCATIONS
enum
{
POLYGON_ATTR_ENABLE_LIGHT0_BIT = 0,
POLYGON_ATTR_ENABLE_LIGHT1_BIT = 1,
POLYGON_ATTR_ENABLE_LIGHT2_BIT = 2,
POLYGON_ATTR_ENABLE_LIGHT3_BIT = 3,
POLYGON_ATTR_MODE_BIT = 4, // Bits 4 - 5
POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT = 6,
POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT = 7,
// Bits 8 - 10 unused
POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT = 11,
POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT = 12,
POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT = 13,
POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT = 14,
POLYGON_ATTR_ENABLE_FOG_BIT = 15,
POLYGON_ATTR_ALPHA_BIT = 16, // Bits 16 - 20
// Bits 21 - 23 unused
POLYGON_ATTR_POLYGON_ID_BIT = 24 // Bits 24 - 29
// Bits 30 - 31 unused
};
// POLYGON ATTRIBUTES - BIT MASKS
enum
{
POLYGON_ATTR_ENABLE_LIGHT0_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT0_BIT,
POLYGON_ATTR_ENABLE_LIGHT1_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT1_BIT,
POLYGON_ATTR_ENABLE_LIGHT2_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT2_BIT,
POLYGON_ATTR_ENABLE_LIGHT3_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT3_BIT,
POLYGON_ATTR_MODE_MASK = 0x03 << POLYGON_ATTR_MODE_BIT,
POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT,
POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT,
POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK= 0x01 << POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT,
POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK = 0x01 << POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT,
POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK = 0x01 << POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT,
POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK = 0x01 << POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT,
POLYGON_ATTR_ENABLE_FOG_MASK = 0x01 << POLYGON_ATTR_ENABLE_FOG_BIT,
POLYGON_ATTR_ALPHA_MASK = 0x1F << POLYGON_ATTR_ALPHA_BIT,
POLYGON_ATTR_POLYGON_ID_MASK = 0x3F << POLYGON_ATTR_POLYGON_ID_BIT
};
// TEXTURE PARAMETERS - BIT LOCATIONS
enum
{
TEXTURE_PARAM_VRAM_OFFSET_BIT = 0, // Bits 0 - 15
TEXTURE_PARAM_ENABLE_REPEAT_S_BIT = 16,
TEXTURE_PARAM_ENABLE_REPEAT_T_BIT = 17,
TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT = 18,
TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT = 19,
TEXTURE_PARAM_SIZE_S_BIT = 20, // Bits 20 - 22
TEXTURE_PARAM_SIZE_T_BIT = 23, // Bits 23 - 25
TEXTURE_PARAM_FORMAT_BIT = 26, // Bits 26 - 28
TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT = 29,
TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT = 30 // Bits 30 - 31
};
// TEXTURE PARAMETERS - BIT MASKS
enum
{
TEXTURE_PARAM_VRAM_OFFSET_MASK = 0xFFFF << TEXTURE_PARAM_VRAM_OFFSET_BIT,
TEXTURE_PARAM_ENABLE_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_S_BIT,
TEXTURE_PARAM_ENABLE_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_T_BIT,
TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT,
TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT,
TEXTURE_PARAM_SIZE_S_MASK = 0x07 << TEXTURE_PARAM_SIZE_S_BIT,
TEXTURE_PARAM_SIZE_T_MASK = 0x07 << TEXTURE_PARAM_SIZE_T_BIT,
TEXTURE_PARAM_FORMAT_MASK = 0x07 << TEXTURE_PARAM_FORMAT_BIT,
TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK = 0x01 << TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT,
TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK = 0x03 << TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT
};
// TEXTURE PARAMETERS - FORMAT ID
enum NDSTextureFormat
{
@ -198,6 +127,14 @@ enum NDSTextureFormat
TEXMODE_16BPP = 7
};
enum TextureTransformationMode
{
TextureTransformationMode_None = 0,
TextureTransformationMode_TexCoordSource = 1,
TextureTransformationMode_NormalSource = 2,
TextureTransformationMode_VertexSource = 3
};
enum PolygonShadingMode
{
PolygonShadingMode_Toon = 0,
@ -208,48 +145,170 @@ void gfx3d_init();
void gfx3d_deinit();
void gfx3d_reset();
typedef struct
typedef union
{
u8 enableLightFlags;
bool enableLight0;
bool enableLight1;
bool enableLight2;
bool enableLight3;
PolygonMode polygonMode;
u8 surfaceCullingMode;
bool enableRenderBackSurface;
bool enableRenderFrontSurface;
bool enableAlphaDepthWrite;
bool enableRenderOnFarPlaneIntersect;
bool enableRenderOneDot;
bool enableDepthEqualTest;
bool enableRenderFog;
bool isWireframe;
bool isOpaque;
bool isTranslucent;
u8 alpha;
u8 polygonID;
} PolygonAttributes;
u32 value;
struct
{
#ifndef MSB_FIRST
u8 Light0:1; // 0: Light 0; 0=Disable, 1=Enable
u8 Light1:1; // 1: Light 1; 0=Disable, 1=Enable
u8 Light2:1; // 2: Light 2; 0=Disable, 1=Enable
u8 Light3:1; // 3: Light 3; 0=Disable, 1=Enable
u8 Mode:2; // 4- 5: Polygon mode;
// 0=Low
// 1=Medium
// 2=High
// 3=Maximum
u8 BackSurface:1; // 6: Back surface; 0=Hide, 1=Render
u8 FrontSurface:1; // 7: Front surface; 0=Hide, 1=Render
u8 :3; // 8-10: Unused bits
u8 TranslucentDepthWrite_Enable:1; // 11: Translucent depth write; 0=Keep 1=Replace
u8 FarPlaneIntersect_Enable:1; // 12: Far-plane intersecting polygons; 0=Hide, 1=Render/clipped
u8 OneDotPolygons_Enable:1; // 13: One-dot polygons; 0=Hide, 1=Render
u8 DepthEqualTest_Enable:1; // 14: Depth test mode; 0=Less, 1=Equal
u8 Fog_Enable:1; // 15: Fog; 0=Disable, 1=Enable
u8 Alpha:5; // 16-20: Alpha value
u8 :3; // 21-23: Unused bits
u8 PolygonID:6; // 24-29: Polygon ID
u8 :2; // 30-31: Unused bits
#else
u8 FrontSurface:1; // 7: Front surface; 0=Hide, 1=Render
u8 BackSurface:1; // 6: Back surface; 0=Hide, 1=Render
u8 Mode:2; // 4- 5: Polygon mode;
// 0=Low
// 1=Medium
// 2=High
// 3=Maximum
u8 Light3:1; // 3: Light 3; 0=Disable, 1=Enable
u8 Light2:1; // 2: Light 2; 0=Disable, 1=Enable
u8 Light1:1; // 1: Light 1; 0=Disable, 1=Enable
u8 Light0:1; // 0: Light 0; 0=Disable, 1=Enable
u8 Fog_Enable:1; // 15: Fog; 0=Disable, 1=Enable
u8 DepthEqualTest_Enable:1; // 14: Depth test mode; 0=Less, 1=Equal
u8 OneDotPolygons_Enable:1; // 13: One-dot polygons; 0=Hide, 1=Render
u8 FarPlaneIntersect_Enable:1; // 12: Far-plane intersecting polygons; 0=Hide, 1=Render/clipped
u8 TranslucentDepthWrite_Enable:1; // 11: Translucent depth write; 0=Keep 1=Replace
u8 :3; // 8-10: Unused bits
u8 :3; // 21-23: Unused bits
u8 Alpha:5; // 16-20: Alpha value
u8 :2; // 30-31: Unused bits
u8 PolygonID:6; // 24-29: Polygon ID
#endif
};
struct
{
#ifndef MSB_FIRST
u8 LightMask:4; // 0- 3: Light enable mask
u8 :2;
u8 SurfaceCullingMode:2; // 6- 7: Surface culling mode;
// 0=Cull front and back
// 1=Cull front
// 2=Cull back
// 3=No culling
u8 :8;
u8 :8;
u8 :8;
#else
u8 SurfaceCullingMode:2; // 6- 7: Surface culling mode;
// 0=Cull front and back
// 1=Cull front
// 2=Cull back
// 3=No culling
u8 :2;
u8 LightMask:4; // 0- 3: Light enable mask
u8 :8;
u8 :8;
u8 :8;
#endif
};
} POLYGON_ATTR;
typedef struct
typedef union
{
u16 VRAMOffset;
bool enableRepeatS;
bool enableRepeatT;
bool enableMirroredRepeatS;
bool enableMirroredRepeatT;
u8 sizeS;
u8 sizeT;
u8 texFormat;
bool enableTransparentColor0;
u8 coordTransformMode;
} PolygonTexParams;
u32 value;
struct
{
u16 VRAMOffset:16; // 0-15: VRAM offset address
#ifndef MSB_FIRST
u16 RepeatS_Enable:1; // 16: Repeat for S-coordinate; 0=Clamp 1=Repeat
u16 RepeatT_Enable:1; // 17: Repeat for T-coordinate; 0=Clamp 1=Repeat
u16 MirroredRepeatS_Enable:1; // 18: Mirrored repeat for S-coordinate, interacts with bit 16; 0=Disable 1=Enable
u16 MirroredRepeatT_Enable:1; // 19: Mirrored repeat for T-coordinate, interacts with bit 17; 0=Disable 1=Enable
u16 SizeShiftS:3; // 20-22: Texel size shift for S-coordinate; 0...7, where the actual texel size is (8 << N)
u16 SizeShiftT:3; // 23-25: Texel size shift for T-coordinate; 0...7, where the actual texel size is (8 << N)
u16 PackedFormat:3; // 26-28: Packed texture format;
// 0=None
// 1=A3I5, 5-bit indexed color with 3-bit alpha
// 2=I2, 2-bit indexed color (4-color palette)
// 3=I4, 4-bit indexed color (16-color palette)
// 4=I8, 8-bit indexed color (256-color palette)
// 5=4x4-texel compressed
// 6=A5I3, 3-bit indexed color with 5-bit alpha
// 7=Direct 16-bit color
u16 KeyColor0_Enable:1; // 29: Use palette color 0 as transparent; 0=Displayed 1=Transparent
u16 TexCoordTransformMode:2; // 30-31: Texture coordinate transformation mode;
// 0=No transformation
// 1=TexCoord source
// 2=Normal source
// 3=Vertex source
#else
u16 TexCoordTransformMode:2; // 30-31: Texture coordinate transformation mode;
// 0=No transformation
// 1=TexCoord source
// 2=Normal source
// 3=Vertex source
u16 KeyColor0_Enable:1; // 29: Use palette color 0 as transparent; 0=Displayed 1=Transparent
u16 PackedFormat:3; // 26-28: Packed texture format;
// 0=None
// 1=A3I5, 5-bit indexed color (32-color palette) with 3-bit alpha (0...7, where 0=Fully Transparent and 7=Opaque)
// 2=I2, 2-bit indexed color (4-color palette)
// 3=I4, 4-bit indexed color (16-color palette)
// 4=I8, 8-bit indexed color (256-color palette)
// 5=4x4-texel compressed
// 6=A5I3, 3-bit indexed color (8-color palette) with 5-bit alpha (0...31, where 0=Fully Transparent and 31=Opaque)
// 7=Direct 16-bit color
u16 SizeShiftT:3; // 23-25: Texel size shift for T-coordinate; 0...7, where the actual texel size is (8 << N)
u16 SizeShiftS:3; // 20-22: Texel size shift for S-coordinate; 0...7, where the actual texel size is (8 << N)
u16 MirroredRepeatT_Enable:1; // 19: Mirrored repeat for T-coordinate, interacts with bit 17; 0=Disable 1=Enable
u16 MirroredRepeatS_Enable:1; // 18: Mirrored repeat for S-coordinate, interacts with bit 16; 0=Disable 1=Enable
u16 RepeatT_Enable:1; // 17: Repeat for T-coordinate; 0=Clamp 1=Repeat
u16 RepeatS_Enable:1; // 16: Repeat for S-coordinate; 0=Clamp 1=Repeat
#endif
};
struct
{
u16 :16;
#ifndef MSB_FIRST
u16 TextureWrapMode:4; // 16-19: Texture wrap mode for repeat and mirrored repeat
u16 :12;
#else
u16 :12;
u16 TextureWrapMode:4; // 16-19: Texture wrap mode for repeat and mirrored repeat
#endif
};
} TEXIMAGE_PARAM;
struct POLY {
PolygonType type; //tri or quad
PolygonPrimitiveType vtxFormat;
u16 vertIndexes[4]; //up to four verts can be referenced by this poly
u32 polyAttr, texParam, texPalette; //the hardware rendering params
POLYGON_ATTR attribute;
TEXIMAGE_PARAM texParam;
u32 texPalette; //the hardware rendering params
u32 viewport;
float miny, maxy;
@ -262,193 +321,14 @@ struct POLY {
else type = POLYGON_TYPE_TRIANGLE;
}
u8 getAttributeEnableLightFlags() const
{
return ((polyAttr & (POLYGON_ATTR_ENABLE_LIGHT0_MASK |
POLYGON_ATTR_ENABLE_LIGHT1_MASK |
POLYGON_ATTR_ENABLE_LIGHT2_MASK |
POLYGON_ATTR_ENABLE_LIGHT3_MASK)) >> POLYGON_ATTR_ENABLE_LIGHT0_BIT);
}
bool getAttributeEnableLight0() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT0_MASK) > 0);
}
bool getAttributeEnableLight1() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT1_MASK) > 0);
}
bool getAttributeEnableLight2() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT2_MASK) > 0);
}
bool getAttributeEnableLight3() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT3_MASK) > 0);
}
PolygonMode getAttributePolygonMode() const
{
return (PolygonMode)((polyAttr & POLYGON_ATTR_MODE_MASK) >> POLYGON_ATTR_MODE_BIT);
}
u8 getAttributeEnableFaceCullingFlags() const
{
return ((polyAttr & (POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK |
POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK)) >> POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT);
}
bool getAttributeEnableBackSurface() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK) > 0);
}
bool getAttributeEnableFrontSurface() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK) > 0);
}
bool getAttributeEnableAlphaDepthWrite() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK) > 0);
}
bool getAttributeEnableRenderOnFarPlaneIntersect() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK) > 0);
}
bool getAttributeEnableOneDotRender() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK) > 0);
}
bool getAttributeEnableDepthEqualTest() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK) > 0);
}
bool getAttributeEnableFog() const
{
return ((polyAttr & POLYGON_ATTR_ENABLE_FOG_MASK) > 0);
}
u8 getAttributeAlpha() const
{
return ((polyAttr & POLYGON_ATTR_ALPHA_MASK) >> POLYGON_ATTR_ALPHA_BIT);
}
u8 getAttributePolygonID() const
{
return ((polyAttr & POLYGON_ATTR_POLYGON_ID_MASK) >> POLYGON_ATTR_POLYGON_ID_BIT);
}
PolygonAttributes getAttributes() const
{
PolygonAttributes theAttr;
theAttr.enableLightFlags = this->getAttributeEnableLightFlags();
theAttr.enableLight0 = this->getAttributeEnableLight0();
theAttr.enableLight1 = this->getAttributeEnableLight1();
theAttr.enableLight2 = this->getAttributeEnableLight2();
theAttr.enableLight3 = this->getAttributeEnableLight3();
theAttr.polygonMode = this->getAttributePolygonMode();
theAttr.surfaceCullingMode = this->getAttributeEnableFaceCullingFlags();
theAttr.enableRenderBackSurface = this->getAttributeEnableBackSurface();
theAttr.enableRenderFrontSurface = this->getAttributeEnableFrontSurface();
theAttr.enableAlphaDepthWrite = this->getAttributeEnableAlphaDepthWrite();
theAttr.enableRenderOnFarPlaneIntersect = this->getAttributeEnableRenderOnFarPlaneIntersect();
theAttr.enableRenderOneDot = this->getAttributeEnableOneDotRender();
theAttr.enableDepthEqualTest = this->getAttributeEnableDepthEqualTest();
theAttr.enableRenderFog = this->getAttributeEnableFog();
theAttr.alpha = this->getAttributeAlpha();
theAttr.isWireframe = this->isWireframe();
theAttr.isOpaque = this->isOpaque();
theAttr.isTranslucent = this->isTranslucent();
theAttr.polygonID = this->getAttributePolygonID();
return theAttr;
}
u16 getTexParamVRAMOffset() const
{
return ((texParam & TEXTURE_PARAM_VRAM_OFFSET_MASK) >> TEXTURE_PARAM_VRAM_OFFSET_BIT);
}
bool getTexParamEnableRepeatS() const
{
return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_S_MASK) > 0);
}
bool getTexParamEnableRepeatT() const
{
return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_T_MASK) > 0);
}
bool getTexParamEnableMirroredRepeatS() const
{
return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK) > 0);
}
bool getTexParamEnableMirroredRepeatT() const
{
return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK) > 0);
}
u8 getTexParamSizeS() const
{
return ((texParam & TEXTURE_PARAM_SIZE_S_MASK) >> TEXTURE_PARAM_SIZE_S_BIT);
}
u8 getTexParamSizeT() const
{
return ((texParam & TEXTURE_PARAM_SIZE_T_MASK) >> TEXTURE_PARAM_SIZE_T_BIT);
}
u8 getTexParamTexFormat() const
{
return ((texParam & TEXTURE_PARAM_FORMAT_MASK) >> TEXTURE_PARAM_FORMAT_BIT);
}
bool getTexParamEnableTransparentColor0() const
{
return ((texParam & TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK) > 0);
}
u8 getTexParamCoordTransformMode() const
{
return ((texParam & TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK) >> TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT);
}
PolygonTexParams getTexParams() const
{
PolygonTexParams theTexParams;
theTexParams.VRAMOffset = this->getTexParamVRAMOffset();
theTexParams.enableRepeatS = this->getTexParamEnableRepeatS();
theTexParams.enableRepeatT = this->getTexParamEnableRepeatT();
theTexParams.enableMirroredRepeatS = this->getTexParamEnableMirroredRepeatS();
theTexParams.enableMirroredRepeatT = this->getTexParamEnableMirroredRepeatT();
theTexParams.sizeS = this->getTexParamSizeS();
theTexParams.sizeT = this->getTexParamSizeT();
theTexParams.texFormat = this->getTexParamTexFormat();
theTexParams.enableTransparentColor0 = this->getTexParamEnableTransparentColor0();
theTexParams.coordTransformMode = this->getTexParamCoordTransformMode();
return theTexParams;
}
bool isWireframe() const
{
return (this->getAttributeAlpha() == 0);
return (this->attribute.Alpha == 0);
}
bool isOpaque() const
{
return (this->getAttributeAlpha() == 31);
return (this->attribute.Alpha == 31);
}
bool isTranslucent() const
@ -461,8 +341,8 @@ struct POLY {
}
// Also check for translucent texture format.
const u8 texFormat = this->getTexParamTexFormat();
const PolygonMode mode = this->getAttributePolygonMode();
const NDSTextureFormat texFormat = (NDSTextureFormat)this->texParam.PackedFormat;
const PolygonMode mode = (PolygonMode)this->attribute.Mode;
//a5i3 or a3i5 -> translucent
if ( (texFormat == TEXMODE_A3I5 || texFormat == TEXMODE_A5I3) && (mode != POLYGON_MODE_DECAL && mode != POLYGON_MODE_SHADOW) )

View File

@ -380,7 +380,7 @@ public:
return RENDER3DERROR_NOERR;
}
this->_textureWrapMode = (thePoly.texParam >> 16) & 0x0F;
this->_textureWrapMode = thePoly.texParam.TextureWrapMode;
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
@ -508,7 +508,7 @@ public:
}
template<bool ISSHADOWPOLYGON>
FORCEINLINE void pixel(const PolygonAttributes &polyAttr, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z)
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)
{
FragmentColor srcColor;
FragmentColor shaderOutput;
@ -530,7 +530,7 @@ public:
// run the depth test
bool depthFail = false;
if (polyAttr.enableDepthEqualTest)
if (polyAttr.DepthEqualTest_Enable)
{
const u32 minDepth = max<u32>(0x00000000, dstAttributeDepth - SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE);
const u32 maxDepth = min<u32>(0x00FFFFFF, dstAttributeDepth + SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE);
@ -548,10 +548,10 @@ public:
}
}
if(depthFail)
if (depthFail)
{
//shadow mask polygons set stencil bit here
if (ISSHADOWPOLYGON && polyAttr.polygonID == 0)
if (ISSHADOWPOLYGON && polyAttr.PolygonID == 0)
dstAttributeStencil=1;
return;
}
@ -559,7 +559,7 @@ public:
//handle shadow polys
if (ISSHADOWPOLYGON)
{
if (polyAttr.polygonID == 0)
if (polyAttr.PolygonID == 0)
{
//shadow mask polygons only affect the stencil buffer, and then only when they fail depth test
//if we made it here, the shadow mask polygon fragment needs to be trashed
@ -573,7 +573,7 @@ public:
//draw only where stencil bit is set
return;
}
if (dstAttributeOpaquePolyID == polyAttr.polygonID)
if (dstAttributeOpaquePolyID == polyAttr.PolygonID)
{
//draw only when polygon ID differs
//TODO: are we using the right dst polyID?
@ -596,10 +596,10 @@ public:
srcColor = MakeFragmentColor(max<u8>(0x00, min<u32>(0x3F,u32floor(r))),
max<u8>(0x00, min<u32>(0x3F,u32floor(g))),
max<u8>(0x00, min<u32>(0x3F,u32floor(b))),
polyAttr.alpha);
polyAttr.Alpha);
//pixel shader
shade(polyAttr.polygonMode, srcColor, shaderOutput, invu * w, invv * w);
shade((PolygonMode)polyAttr.Mode, srcColor, shaderOutput, invu * w, invv * w);
// handle alpha test
if ( shaderOutput.a == 0 ||
@ -612,42 +612,42 @@ public:
isOpaquePixel = (shaderOutput.a == 0x1F);
if (isOpaquePixel)
{
dstAttributeOpaquePolyID = polyAttr.polygonID;
dstAttributeIsTranslucentPoly = polyAttr.isTranslucent;
dstAttributeIsFogged = polyAttr.enableRenderFog;
dstAttributeOpaquePolyID = polyAttr.PolygonID;
dstAttributeIsTranslucentPoly = isTranslucent;
dstAttributeIsFogged = polyAttr.Fog_Enable;
dstColor = shaderOutput;
}
else
{
//dont overwrite pixels on translucent polys with the same polyids
if (dstAttributeTranslucentPolyID == polyAttr.polygonID)
if (dstAttributeTranslucentPolyID == polyAttr.PolygonID)
return;
//originally we were using a test case of shadows-behind-trees in sm64ds
//but, it looks bad in that game. this is actually correct
//if this isnt correct, then complex shape cart shadows in mario kart don't work right
dstAttributeTranslucentPolyID = polyAttr.polygonID;
dstAttributeTranslucentPolyID = polyAttr.PolygonID;
//alpha blending and write color
alphaBlend(dstColor, shaderOutput);
dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.enableRenderFog);
dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable);
}
//depth writing
if (isOpaquePixel || polyAttr.enableAlphaDepthWrite)
if (isOpaquePixel || polyAttr.TranslucentDepthWrite_Enable)
dstAttributeDepth = newDepth;
}
//draws a single scanline
template <bool ISSHADOWPOLYGON>
FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack)
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)
{
int XStart = pLeft->X;
int width = pRight->X - XStart;
// HACK: workaround for vertical/slant line poly
if (lineHack && width == 0)
if (USELINEHACK && width == 0)
{
int leftWidth = pLeft->XStep;
if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator)
@ -699,7 +699,7 @@ public:
if (x < 0)
{
if (RENDERER && !lineHack)
if (RENDERER && !USELINEHACK)
{
printf("rasterizer rendering at x=%d! oops!\n",x);
return;
@ -717,7 +717,7 @@ public:
}
if (x+width > framebufferWidth)
{
if (RENDERER && !lineHack && framebufferWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH)
if (RENDERER && !USELINEHACK && framebufferWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH)
{
printf("rasterizer rendering at x=%d! oops!\n",x+width-1);
return;
@ -727,7 +727,7 @@ public:
while (width-- > 0)
{
pixel<ISSHADOWPOLYGON>(polyAttr, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z);
pixel<ISSHADOWPOLYGON>(polyAttr, isTranslucent, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z);
adr++;
x++;
@ -742,44 +742,44 @@ public:
}
//runs several scanlines, until an edge is finished
template<bool SLI, bool ISSHADOWPOLYGON>
void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack)
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)
{
//oh lord, hack city for edge drawing
//do not overstep either of the edges
int Height = min(left->Height,right->Height);
bool first=true;
bool first = true;
//HACK: special handling for horizontal line poly
if (lineHack && 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)
{
bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE);
if(draw) drawscanline<ISSHADOWPOLYGON>(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack);
if (draw) drawscanline<ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right);
}
while(Height--)
while (Height--)
{
bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE);
if(draw) drawscanline<ISSHADOWPOLYGON>(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack);
if (draw) drawscanline<ISSHADOWPOLYGON, USELINEHACK>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right);
const int xl = left->X;
const int xr = right->X;
const int y = left->Y;
left->Step();
right->Step();
if(!RENDERER && _debug_thisPoly)
if (!RENDERER && _debug_thisPoly)
{
//debug drawing
bool top = (horizontal&&first);
bool bottom = (!Height&&horizontal);
if(Height || top || bottom)
bool top = (ISHORIZONTAL && first);
bool bottom = (!Height && ISHORIZONTAL);
if (Height || top || bottom)
{
if(draw)
if (draw)
{
int nxl = left->X;
int nxr = right->X;
if(top)
if (top)
{
int xs = min(xl,xr);
int xe = max(xl,xr);
@ -791,7 +791,7 @@ public:
dstColor[adr].b = 0;
}
}
else if(bottom)
else if (bottom)
{
int xs = min(xl,xr);
int xe = max(xl,xr);
@ -844,11 +844,11 @@ public:
//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
template<int TYPE>
void sort_verts(bool backwards)
template<bool ISBACKWARDS, int TYPE>
void sort_verts()
{
//if the verts are backwards, reorder them first
if (backwards)
if (ISBACKWARDS)
for (size_t i = 0; i < TYPE/2; i++)
swap(verts[i],verts[TYPE-i-1]);
@ -881,22 +881,22 @@ public:
//verts must be clockwise.
//I didnt reference anything for this algorithm but it seems like I've seen it somewhere before.
//Maybe it is like crow's algorithm
template<bool SLI, bool ISSHADOWPOLYGON>
void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack)
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)
{
bool failure = false;
switch(type)
switch (type)
{
case 3: sort_verts<3>(backwards); break;
case 4: sort_verts<4>(backwards); break;
case 5: sort_verts<5>(backwards); break;
case 6: sort_verts<6>(backwards); break;
case 7: sort_verts<7>(backwards); break;
case 8: sort_verts<8>(backwards); break;
case 9: sort_verts<9>(backwards); break;
case 10: sort_verts<10>(backwards); break;
default: printf("skipping type %d\n",type); return;
case 3: sort_verts<ISBACKWARDS, 3>(); break;
case 4: sort_verts<ISBACKWARDS, 4>(); break;
case 5: sort_verts<ISBACKWARDS, 5>(); break;
case 6: sort_verts<ISBACKWARDS, 6>(); break;
case 7: sort_verts<ISBACKWARDS, 7>(); break;
case 8: sort_verts<ISBACKWARDS, 8>(); break;
case 9: sort_verts<ISBACKWARDS, 9>(); break;
case 10: sort_verts<ISBACKWARDS, 10>(); break;
default: printf("skipping type %d\n", type); return;
}
//we are going to step around the polygon in both directions starting from vert 0.
@ -912,18 +912,25 @@ public:
//generate new edges if necessary. we must avoid regenerating edges when they are incomplete
//so that they can be continued on down the shape
assert(rv != type);
int _lv = lv==type?0:lv; //make sure that we ask for vert 0 when the variable contains the starting value
int _lv = (lv == type) ? 0 : lv; //make sure that we ask for vert 0 when the variable contains the starting value
if (step_left) left = edge_fx_fl(_lv,lv-1,(VERT**)&verts, failure);
if (step_right) right = edge_fx_fl(rv,rv+1,(VERT**)&verts, failure);
step_left = step_right = false;
//handle a failure in the edge setup due to nutty polys
if(failure)
if (failure)
return;
bool horizontal = left.Y == right.Y;
runscanlines<SLI, ISSHADOWPOLYGON>(polyAttr, dstColor, framebufferWidth, framebufferHeight, &left, &right, horizontal, lineHack);
const bool horizontal = (left.Y == right.Y);
if (horizontal)
{
runscanlines<SLI, ISSHADOWPOLYGON, USELINEHACK, true>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right);
}
else
{
runscanlines<SLI, ISSHADOWPOLYGON, USELINEHACK, false>(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right);
}
//if we ran out of an edge, step to the next one
if (right.Height == 0)
{
@ -937,11 +944,11 @@ public:
}
//this is our completion condition: when our stepped edges meet in the middle
if (lv<=rv+1) break;
if (lv <= rv+1) break;
}
}
template<bool SLI>
template<bool SLI, bool USELINEHACK>
FORCEINLINE void mainLoop()
{
const size_t polyCount = this->_softRender->_clippedPolyCount;
@ -956,9 +963,8 @@ public:
const GFX3D_Clipper::TClippedPoly &firstClippedPoly = this->_softRender->clippedPolys[0];
const POLY &firstPoly = *firstClippedPoly.poly;
PolygonAttributes polyAttr = firstPoly.getAttributes();
u32 lastPolyAttr = firstPoly.polyAttr;
u32 lastTexParams = firstPoly.texParam;
POLYGON_ATTR polyAttr = firstPoly.attribute;
TEXIMAGE_PARAM lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette;
this->SetupTexture(firstPoly, 0);
@ -972,38 +978,78 @@ public:
GFX3D_Clipper::TClippedPoly &clippedPoly = this->_softRender->clippedPolys[i];
const POLY &thePoly = *clippedPoly.poly;
const PolygonType type = clippedPoly.type;
const int vertCount = clippedPoly.type;
const bool useLineHack = USELINEHACK && (thePoly.vtxFormat & 4);
if (lastPolyAttr != thePoly.polyAttr)
{
polyAttr = thePoly.getAttributes();
lastPolyAttr = thePoly.polyAttr;
}
polyAttr = thePoly.attribute;
const bool isTranslucent = thePoly.isTranslucent();
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette)
{
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
this->SetupTexture(thePoly, i);
}
for (int j = 0; j < type; j++)
for (int j = 0; j < vertCount; j++)
this->verts[j] = &clippedPoly.clipVerts[j];
for (int j = type; j < MAX_CLIPPED_VERTS; j++)
for (int j = vertCount; j < MAX_CLIPPED_VERTS; j++)
this->verts[j] = NULL;
if (polyAttr.polygonMode == POLYGON_MODE_SHADOW)
if (!this->_softRender->polyBackfacing[i])
{
shape_engine<SLI, true>(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack);
if (polyAttr.Mode == POLYGON_MODE_SHADOW)
{
if (useLineHack)
{
shape_engine<SLI, true, true, true>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
else
{
shape_engine<SLI, true, true, false>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
}
else
{
if (useLineHack)
{
shape_engine<SLI, true, false, true>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
else
{
shape_engine<SLI, true, false, false>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
}
}
else
{
shape_engine<SLI, false>(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack);
if (polyAttr.Mode == POLYGON_MODE_SHADOW)
{
if (useLineHack)
{
shape_engine<SLI, false, true, true>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
else
{
shape_engine<SLI, false, true, false>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
}
else
{
if (useLineHack)
{
shape_engine<SLI, false, false, true>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
else
{
shape_engine<SLI, false, false, false>(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount);
}
}
}
}
}
}; //rasterizerUnit
#define _MAX_CORES 16
@ -1016,7 +1062,16 @@ static bool rasterizerUnitTasksInited = false;
static void* execRasterizerUnit(void *arg)
{
intptr_t which = (intptr_t)arg;
rasterizerUnit[which].mainLoop<true>();
if (CommonSettings.GFX3D_LineHack)
{
rasterizerUnit[which].mainLoop<true, true>();
}
else
{
rasterizerUnit[which].mainLoop<true, false>();
}
return 0;
}
@ -1066,7 +1121,14 @@ static void* SoftRasterizer_RunRenderEdgeMarkAndFog(void *arg)
void _HACK_Viewer_ExecUnit()
{
_HACK_viewer_rasterizerUnit.mainLoop<false>();
if (CommonSettings.GFX3D_LineHack)
{
_HACK_viewer_rasterizerUnit.mainLoop<false, true>();
}
else
{
_HACK_viewer_rasterizerUnit.mainLoop<false, false>();
}
}
static Render3D* SoftRasterizerRendererCreate()
@ -1092,7 +1154,7 @@ static void SoftRasterizerRendererDestroy()
}
}
SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes)
SoftRasterizerTexture::SoftRasterizerTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes)
{
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_15bpp);
_unpackData = (u32 *)malloc_alignedCacheLine(_cacheSize);
@ -1599,7 +1661,7 @@ void SoftRasterizerRenderer::performBackfaceTests()
const POLY &thePoly = *clippedPoly.poly;
const PolygonType type = clippedPoly.type;
const VERT *verts = &clippedPoly.clipVerts[0];
const u8 cullingMode = thePoly.getAttributeEnableFaceCullingFlags();
const u8 cullingMode = thePoly.attribute.SurfaceCullingMode;
//HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built
@ -1714,7 +1776,15 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
}
else
{
rasterizerUnit[0].mainLoop<false>();
if (CommonSettings.GFX3D_LineHack)
{
rasterizerUnit[0].mainLoop<false, true>();
}
else
{
rasterizerUnit[0].mainLoop<false, false>();
}
this->_renderGeometryNeedsFinish = false;
texCache.Evict(); // Since we're finishing geometry rendering here and now, also check the texture cache now.
}

View File

@ -63,7 +63,7 @@ protected:
u32 _renderWidthShift;
public:
SoftRasterizerTexture(u32 texAttributes, u32 palAttributes);
SoftRasterizerTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes);
virtual ~SoftRasterizerTexture();
virtual void Load();

View File

@ -193,7 +193,7 @@ void FragmentAttributesBuffer::SetAll(const FragmentAttributes &attr)
}
}
Render3DTexture::Render3DTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
Render3DTexture::Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
{
_isSamplingEnabled = true;
_useDeposterize = false;

View File

@ -126,7 +126,7 @@ protected:
template<size_t SCALEFACTOR> void _Upscale(const u32 *__restrict src, u32 *__restrict dst);
public:
Render3DTexture(u32 texAttributes, u32 palAttributes);
Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes);
bool IsSamplingEnabled() const;
void SetSamplingEnabled(bool isEnabled);

View File

@ -321,7 +321,7 @@ void TextureCache::ForceReloadAllTextures()
}
}
TextureStore* TextureCache::GetTexture(u32 texAttributes, u32 palAttributes)
TextureStore* TextureCache::GetTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes)
{
TextureStore *theTexture = NULL;
const TextureCacheKey key = TextureCache::GenerateKey(texAttributes, palAttributes);
@ -364,16 +364,16 @@ void TextureCache::Remove(TextureStore *texItem)
this->_actualCacheSize -= texItem->GetCacheSize();
}
TextureCacheKey TextureCache::GenerateKey(const u32 texAttributes, const u32 palAttributes)
TextureCacheKey TextureCache::GenerateKey(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes)
{
// Since the repeat, flip, and coordinate transformation modes are render settings
// and not data settings, we can mask out those bits to help reduce duplicate entries.
return (TextureCacheKey)( ((u64)palAttributes << 32) | (u64)(texAttributes & 0x3FF0FFFF) );
return (TextureCacheKey)( ((u64)palAttributes << 32) | (u64)(texAttributes.value & 0x3FF0FFFF) );
}
TextureStore::TextureStore()
{
_textureAttributes = 0;
_textureAttributes.value = 0;
_paletteAttributes = 0;
_cacheKey = 0;
@ -406,7 +406,7 @@ TextureStore::TextureStore()
_cacheUsageCount = 0;
}
TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes)
TextureStore::TextureStore(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes)
{
//for each texformat, multiplier from numtexels to numbytes (fixed point 30.2)
static const u32 texSizes[] = {0, 4, 1, 2, 4, 1, 4, 8};
@ -418,16 +418,16 @@ TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes)
_paletteAttributes = palAttributes;
_cacheKey = TextureCache::GenerateKey(texAttributes, palAttributes);
_sizeS = (8 << ((texAttributes >> 20) & 0x07));
_sizeT = (8 << ((texAttributes >> 23) & 0x07));
_sizeS = (8 << texAttributes.SizeShiftS);
_sizeT = (8 << texAttributes.SizeShiftT);
_packFormat = (NDSTextureFormat)((texAttributes >> 26) & 0x07);
_packAddress = (texAttributes & 0xFFFF) << 3;
_packFormat = (NDSTextureFormat)(texAttributes.PackedFormat);
_packAddress = texAttributes.VRAMOffset << 3;
_packSize = (_sizeS * _sizeT * texSizes[_packFormat]) >> 2; //shifted because the texSizes multiplier is fixed point
if ( (_packFormat == TEXMODE_I2) || (_packFormat == TEXMODE_I4) || (_packFormat == TEXMODE_I8) )
{
_isPalZeroTransparent = ( ((texAttributes >> 29) & 1) != 0 );
_isPalZeroTransparent = (texAttributes.KeyColor0_Enable != 0);
}
else
{
@ -439,8 +439,8 @@ TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes)
if (_packFormat == TEXMODE_4X4)
{
const u32 indexBase = ((texAttributes & 0xC000) == 0x8000) ? 0x30000 : 0x20000;
const u32 indexOffset = (texAttributes & 0x3FFF) << 2;
const u32 indexBase = ((texAttributes.VRAMOffset & 0xC000) == 0x8000) ? 0x30000 : 0x20000;
const u32 indexOffset = (texAttributes.VRAMOffset & 0x3FFF) << 2;
_packIndexAddress = indexBase + indexOffset;
_packIndexSize = (_sizeS * _sizeT) >> 3;
@ -502,7 +502,7 @@ TextureStore::~TextureStore()
free_aligned(this->_packData);
}
u32 TextureStore::GetTextureAttributes() const
TEXIMAGE_PARAM TextureStore::GetTextureAttributes() const
{
return this->_textureAttributes;
}
@ -647,7 +647,7 @@ void TextureStore::Unpack(u32 *unpackBuffer)
PROGINFO("Your 4x4 texture has overrun its texture slot.\n");
}
NDSTextureUnpack4x4<TEXCACHEFORMAT>(this->_packSizeFirstSlot, (u32 *)this->_packData, (u16 *)this->_packIndexData, this->_paletteAddress, this->_textureAttributes, this->_sizeS, this->_sizeT, unpackBuffer);
NDSTextureUnpack4x4<TEXCACHEFORMAT>(this->_packSizeFirstSlot, (u32 *)this->_packData, (u16 *)this->_packIndexData, this->_paletteAddress, this->_sizeS, this->_sizeT, unpackBuffer);
break;
}
@ -1164,7 +1164,7 @@ void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, co
#define PAL4X4(offset) ( LE_TO_LOCAL_16( *(u16*)( MMU.texInfo.texPalSlot[((palAddress + (offset)*2)>>14)&0x7] + ((palAddress + (offset)*2)&0x3FFF) ) ) & 0x7FFF )
template <TextureStoreUnpackFormat TEXCACHEFORMAT>
void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer)
void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer)
{
const u32 limit = srcSize * sizeof(u32);
const u16 xTmpSize = sizeX >> 2;

View File

@ -76,18 +76,18 @@ public:
void Reset();
void ForceReloadAllTextures();
TextureStore* GetTexture(u32 texAttributes, u32 palAttributes);
TextureStore* GetTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes);
void Add(TextureStore *texItem);
void Remove(TextureStore *texItem);
static TextureCacheKey GenerateKey(const u32 texAttributes, const u32 palAttributes);
static TextureCacheKey GenerateKey(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes);
};
class TextureStore
{
protected:
u32 _textureAttributes;
TEXIMAGE_PARAM _textureAttributes;
u32 _paletteAttributes;
u32 _sizeS;
@ -123,10 +123,10 @@ protected:
public:
TextureStore();
TextureStore(const u32 texAttributes, const u32 palAttributes);
TextureStore(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes);
virtual ~TextureStore();
u32 GetTextureAttributes() const;
TEXIMAGE_PARAM GetTextureAttributes() const;
u32 GetPaletteAttributes() const;
u32 GetWidth() const;
@ -187,7 +187,7 @@ template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u16 *__restrict srcData, u32 *__restrict dstBuffer);
extern TextureCache texCache;