mirror of
https://github.com/libretro/desmume.git
synced 2024-11-23 08:10:03 +00:00
GFX3D: The polygon clipping stage now occurs before any polygon sorting, allowing for the sorting of smaller lists. This can be a significant performance improvement for some 3D scenes with high polygon counts.
- 3D renderers no longer perform polygon clipping themselves, instead relying on GFX3D to do it. By default, the clipping mode is ClipperMode_DetermineClipOnly, but 3D renderers can change this by overriding the virtual method Render3D::GetPreferredPolygonClippingMode() and returning their preferred clipping mode.
This commit is contained in:
parent
b8e85e0c9d
commit
e06d11f6df
@ -4239,6 +4239,10 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
|
||||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
this->_clippedPolyCount = engine.clippedPolyCount;
|
||||
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
|
||||
this->_clippedPolyList = engine.clippedPolyList;
|
||||
|
||||
if (this->isVBOSupported)
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
|
||||
@ -4256,8 +4260,6 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
|
||||
}
|
||||
|
||||
// Generate the clipped polygon list.
|
||||
this->_PerformClipping<ClipperMode_DetermineClipOnly>(engine.vertList, engine.polylist, &engine.indexlist);
|
||||
|
||||
this->_renderNeedsDepthEqualsTest = false;
|
||||
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
||||
{
|
||||
@ -5531,6 +5533,10 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
|
||||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
this->_clippedPolyCount = engine.clippedPolyCount;
|
||||
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
|
||||
this->_clippedPolyList = engine.clippedPolyList;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
||||
|
||||
@ -5538,8 +5544,6 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertListCount, engine.vertList);
|
||||
|
||||
// Generate the clipped polygon list.
|
||||
this->_PerformClipping<ClipperMode_DetermineClipOnly>(engine.vertList, engine.polylist, &engine.indexlist);
|
||||
|
||||
this->_renderNeedsDepthEqualsTest = false;
|
||||
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
||||
{
|
||||
|
@ -2153,6 +2153,10 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
|
||||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
this->_clippedPolyCount = engine.clippedPolyCount;
|
||||
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
|
||||
this->_clippedPolyList = engine.clippedPolyList;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
||||
|
||||
@ -2213,8 +2217,6 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(this->_pendingRenderStates), &this->_pendingRenderStates);
|
||||
|
||||
// Generate the clipped polygon list.
|
||||
this->_PerformClipping<ClipperMode_DetermineClipOnly>(engine.vertList, engine.polylist, &engine.indexlist);
|
||||
|
||||
if ( (OGLRef.uboPolyStatesID != 0) && (this->_clippedPolyCount > MAX_CLIPPED_POLY_COUNT_FOR_UBO) )
|
||||
{
|
||||
// In practice, there shouldn't be any game scene with a clipped polygon count that
|
||||
|
@ -371,6 +371,11 @@ POLYLIST* polylist = NULL;
|
||||
VERT *vertLists = NULL;
|
||||
VERT *vertList = NULL;
|
||||
|
||||
GFX3D_Clipper *_clipper = NULL;
|
||||
CPoly _clippedPolyWorkingList[POLYLIST_SIZE * 2];
|
||||
CPoly _clippedPolyUnsortedList[POLYLIST_SIZE];
|
||||
CPoly _clippedPolySortedList[POLYLIST_SIZE];
|
||||
|
||||
size_t vertListCount[2] = {0, 0};
|
||||
int polygonListCompleted = 0;
|
||||
|
||||
@ -502,6 +507,9 @@ void VERT::load(EMUFILE &is)
|
||||
|
||||
void gfx3d_init()
|
||||
{
|
||||
_clipper = new GFX3D_Clipper;
|
||||
_clipper->SetClippedPolyBufferPtr(_clippedPolyWorkingList);
|
||||
|
||||
polyAttrInProcess.value = 0;
|
||||
currentPolyAttr.value = 0;
|
||||
currentPolyTexParam.value = 0;
|
||||
@ -564,6 +572,8 @@ void gfx3d_deinit()
|
||||
free_aligned(vertLists);
|
||||
vertLists = NULL;
|
||||
vertList = NULL;
|
||||
|
||||
delete _clipper;
|
||||
}
|
||||
|
||||
void gfx3d_reset()
|
||||
@ -594,6 +604,9 @@ void gfx3d_reset()
|
||||
gfx3d.polylist = polylist;
|
||||
gfx3d.vertList = vertList;
|
||||
gfx3d.vertListCount = vertListCount[listTwiddle];
|
||||
gfx3d.clippedPolyCount = 0;
|
||||
gfx3d.clippedPolyOpaqueCount = 0;
|
||||
gfx3d.clippedPolyList = _clippedPolySortedList;
|
||||
|
||||
polyAttrInProcess.value = 0;
|
||||
currentPolyAttr.value = 0;
|
||||
@ -1800,10 +1813,10 @@ static BOOL gfx3d_glBoxTest(u32 v)
|
||||
&verts[thePoly.vertIndexes[3]]
|
||||
};
|
||||
|
||||
boxtestClipper.ClipPoly<ClipperMode_DetermineClipOnly>(thePoly, vertTable);
|
||||
const bool isPolyUnclipped = boxtestClipper.ClipPoly<ClipperMode_DetermineClipOnly>(0, thePoly, vertTable);
|
||||
|
||||
//if any portion of this poly was retained, then the test passes.
|
||||
if (boxtestClipper.GetPolyCount() > 0)
|
||||
if (isPolyUnclipped)
|
||||
{
|
||||
//printf("%06d PASS %d\n",gxFIFO.size, i);
|
||||
MMU_new.gxstat.tr = 1;
|
||||
@ -2280,8 +2293,8 @@ void gfx3d_glFlush(u32 v)
|
||||
|
||||
static bool gfx3d_ysort_compare(int num1, int num2)
|
||||
{
|
||||
const POLY &poly1 = polylist->list[num1];
|
||||
const POLY &poly2 = polylist->list[num2];
|
||||
const POLY &poly1 = gfx3d.polylist->list[num1];
|
||||
const POLY &poly2 = gfx3d.polylist->list[num2];
|
||||
|
||||
//this may be verified by checking the game create menus in harvest moon island of happiness
|
||||
//also the buttons in the knights in the nightmare frontend depend on this and the perspective division
|
||||
@ -2301,6 +2314,145 @@ static bool gfx3d_ysort_compare(int num1, int num2)
|
||||
return (num1 < num2);
|
||||
}
|
||||
|
||||
template <ClipperMode CLIPPERMODE>
|
||||
void gfx3d_PerformClipping(const VERT *vtxList, const POLYLIST *polyList)
|
||||
{
|
||||
bool isPolyUnclipped = false;
|
||||
_clipper->Reset();
|
||||
|
||||
for (size_t polyIndex = 0, clipCount = 0; polyIndex < polyList->count; polyIndex++)
|
||||
{
|
||||
const POLY &poly = polyList->list[polyIndex];
|
||||
|
||||
const VERT *clipVerts[4] = {
|
||||
&vtxList[poly.vertIndexes[0]],
|
||||
&vtxList[poly.vertIndexes[1]],
|
||||
&vtxList[poly.vertIndexes[2]],
|
||||
(poly.type == POLYGON_TYPE_QUAD) ? &vtxList[poly.vertIndexes[3]] : NULL
|
||||
};
|
||||
|
||||
isPolyUnclipped = _clipper->ClipPoly<CLIPPERMODE>(polyIndex, poly, clipVerts);
|
||||
|
||||
if (CLIPPERMODE == ClipperMode_DetermineClipOnly)
|
||||
{
|
||||
if (isPolyUnclipped)
|
||||
{
|
||||
_clippedPolyUnsortedList[polyIndex].index = _clipper->GetClippedPolyByIndex(clipCount).index;
|
||||
_clippedPolyUnsortedList[polyIndex].poly = _clipper->GetClippedPolyByIndex(clipCount).poly;
|
||||
clipCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isPolyUnclipped)
|
||||
{
|
||||
_clippedPolyUnsortedList[polyIndex] = _clipper->GetClippedPolyByIndex(clipCount);
|
||||
clipCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx3d_GenerateRenderLists(const ClipperMode clippingMode)
|
||||
{
|
||||
switch (clippingMode)
|
||||
{
|
||||
case ClipperMode_Full:
|
||||
gfx3d_PerformClipping<ClipperMode_Full>(gfx3d.vertList, gfx3d.polylist);
|
||||
break;
|
||||
|
||||
case ClipperMode_FullColorInterpolate:
|
||||
gfx3d_PerformClipping<ClipperMode_FullColorInterpolate>(gfx3d.vertList, gfx3d.polylist);
|
||||
break;
|
||||
|
||||
case ClipperMode_DetermineClipOnly:
|
||||
gfx3d_PerformClipping<ClipperMode_DetermineClipOnly>(gfx3d.vertList, gfx3d.polylist);
|
||||
break;
|
||||
}
|
||||
|
||||
gfx3d.clippedPolyCount = _clipper->GetPolyCount();
|
||||
|
||||
#ifdef _SHOW_VTX_COUNTERS
|
||||
max_polys = max((u32)polycount, max_polys);
|
||||
max_verts = max((u32)vertListCount[listTwiddle], max_verts);
|
||||
osd->addFixed(180, 20, "%i/%i", polycount, vertListCount[listTwiddle]); // current
|
||||
osd->addFixed(180, 35, "%i/%i", max_polys, max_verts); // max
|
||||
#endif
|
||||
|
||||
//we need to sort the poly list with alpha polys last
|
||||
//first, look for opaque polys
|
||||
size_t ctr = 0;
|
||||
for (size_t i = 0; i < gfx3d.clippedPolyCount; i++)
|
||||
{
|
||||
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i);
|
||||
if (!clippedPoly.poly->isTranslucent())
|
||||
gfx3d.indexlist.list[ctr++] = clippedPoly.index;
|
||||
}
|
||||
gfx3d.clippedPolyOpaqueCount = ctr;
|
||||
|
||||
//then look for translucent polys
|
||||
for (size_t i = 0; i < gfx3d.clippedPolyCount; i++)
|
||||
{
|
||||
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i);
|
||||
if (clippedPoly.poly->isTranslucent())
|
||||
gfx3d.indexlist.list[ctr++] = clippedPoly.index;
|
||||
}
|
||||
|
||||
//find the min and max y values for each poly.
|
||||
//the w-division here is just an approximation to fix the shop in harvest moon island of happiness
|
||||
//also the buttons in the knights in the nightmare frontend depend on this
|
||||
size_t ysortCount = (gfx3d.state.sortmode) ? gfx3d.clippedPolyOpaqueCount : gfx3d.clippedPolyCount;
|
||||
for (size_t i = 0; i < ysortCount; i++)
|
||||
{
|
||||
// TODO: Possible divide by zero with the w-coordinate.
|
||||
// Is the vertex being read correctly? Is 0 a valid value for w?
|
||||
// If both of these questions answer to yes, then how does the NDS handle a NaN?
|
||||
// For now, simply prevent w from being zero.
|
||||
POLY &poly = *_clipper->GetClippedPolyByIndex(i).poly;
|
||||
float verty = gfx3d.vertList[poly.vertIndexes[0]].y;
|
||||
float vertw = (gfx3d.vertList[poly.vertIndexes[0]].w != 0.0f) ? gfx3d.vertList[poly.vertIndexes[0]].w : 0.00000001f;
|
||||
verty = 1.0f-(verty+vertw)/(2*vertw);
|
||||
poly.miny = poly.maxy = verty;
|
||||
|
||||
for (size_t j = 1; j < poly.type; j++)
|
||||
{
|
||||
verty = gfx3d.vertList[poly.vertIndexes[j]].y;
|
||||
vertw = (gfx3d.vertList[poly.vertIndexes[j]].w != 0.0f) ? gfx3d.vertList[poly.vertIndexes[j]].w : 0.00000001f;
|
||||
verty = 1.0f-(verty+vertw)/(2*vertw);
|
||||
poly.miny = min(poly.miny, verty);
|
||||
poly.maxy = max(poly.maxy, verty);
|
||||
}
|
||||
}
|
||||
|
||||
//now we have to sort the opaque polys by y-value.
|
||||
//(test case: harvest moon island of happiness character creator UI)
|
||||
//should this be done after clipping??
|
||||
std::sort(gfx3d.indexlist.list, gfx3d.indexlist.list + gfx3d.clippedPolyOpaqueCount, gfx3d_ysort_compare);
|
||||
|
||||
if (!gfx3d.state.sortmode)
|
||||
{
|
||||
//if we are autosorting translucent polys, we need to do this also
|
||||
//TODO - this is unverified behavior. need a test case
|
||||
std::sort(gfx3d.indexlist.list + gfx3d.clippedPolyOpaqueCount, gfx3d.indexlist.list + gfx3d.clippedPolyCount, gfx3d_ysort_compare);
|
||||
}
|
||||
|
||||
// Reorder the clipped polygon list to match our sorted index list.
|
||||
if (clippingMode == ClipperMode_DetermineClipOnly)
|
||||
{
|
||||
for (size_t i = 0; i < gfx3d.clippedPolyCount; i++)
|
||||
{
|
||||
_clippedPolySortedList[i].poly = _clippedPolyUnsortedList[gfx3d.indexlist.list[i]].poly;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < gfx3d.clippedPolyCount; i++)
|
||||
{
|
||||
_clippedPolySortedList[i] = _clippedPolyUnsortedList[gfx3d.indexlist.list[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx3d_doFlush()
|
||||
{
|
||||
gfx3d.render3DFrameCount++;
|
||||
@ -2320,75 +2472,10 @@ static void gfx3d_doFlush()
|
||||
gfx3d.renderState = gfx3d.state;
|
||||
|
||||
gfx3d.state.activeFlushCommand = gfx3d.state.pendingFlushCommand;
|
||||
|
||||
const size_t polycount = polylist->count;
|
||||
#ifdef _SHOW_VTX_COUNTERS
|
||||
max_polys = max((u32)polycount, max_polys);
|
||||
max_verts = max((u32)vertListCount[listTwiddle], max_verts);
|
||||
osd->addFixed(180, 20, "%i/%i", polycount, vertListCount[listTwiddle]); // current
|
||||
osd->addFixed(180, 35, "%i/%i", max_polys, max_verts); // max
|
||||
#endif
|
||||
|
||||
//find the min and max y values for each poly.
|
||||
//TODO - this could be a small waste of time if we are manual sorting the translucent polys
|
||||
//TODO - this _MUST_ be moved later in the pipeline, after clipping.
|
||||
//the w-division here is just an approximation to fix the shop in harvest moon island of happiness
|
||||
//also the buttons in the knights in the nightmare frontend depend on this
|
||||
for (size_t i = 0; i < polycount; i++)
|
||||
{
|
||||
// TODO: Possible divide by zero with the w-coordinate.
|
||||
// Is the vertex being read correctly? Is 0 a valid value for w?
|
||||
// If both of these questions answer to yes, then how does the NDS handle a NaN?
|
||||
// For now, simply prevent w from being zero.
|
||||
POLY &poly = polylist->list[i];
|
||||
float verty = vertList[poly.vertIndexes[0]].y;
|
||||
float vertw = (vertList[poly.vertIndexes[0]].w != 0.0f) ? vertList[poly.vertIndexes[0]].w : 0.00000001f;
|
||||
verty = 1.0f-(verty+vertw)/(2*vertw);
|
||||
poly.miny = poly.maxy = verty;
|
||||
|
||||
for (size_t j = 1; j < poly.type; j++)
|
||||
{
|
||||
verty = vertList[poly.vertIndexes[j]].y;
|
||||
vertw = (vertList[poly.vertIndexes[j]].w != 0.0f) ? vertList[poly.vertIndexes[j]].w : 0.00000001f;
|
||||
verty = 1.0f-(verty+vertw)/(2*vertw);
|
||||
poly.miny = min(poly.miny, verty);
|
||||
poly.maxy = max(poly.maxy, verty);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//we need to sort the poly list with alpha polys last
|
||||
//first, look for opaque polys
|
||||
size_t ctr = 0;
|
||||
for (size_t i = 0; i < polycount; i++)
|
||||
{
|
||||
const POLY &poly = polylist->list[i];
|
||||
if (!poly.isTranslucent())
|
||||
gfx3d.indexlist.list[ctr++] = i;
|
||||
}
|
||||
|
||||
polylist->opaqueCount = ctr;
|
||||
const ClipperMode clippingMode = CurrentRenderer->GetPreferredPolygonClippingMode();
|
||||
gfx3d_GenerateRenderLists(clippingMode);
|
||||
|
||||
//then look for translucent polys
|
||||
for (size_t i = 0; i < polycount; i++)
|
||||
{
|
||||
const POLY &poly = polylist->list[i];
|
||||
if (poly.isTranslucent())
|
||||
gfx3d.indexlist.list[ctr++] = i;
|
||||
}
|
||||
|
||||
//now we have to sort the opaque polys by y-value.
|
||||
//(test case: harvest moon island of happiness character creator UI)
|
||||
//should this be done after clipping??
|
||||
std::sort(gfx3d.indexlist.list, gfx3d.indexlist.list + polylist->opaqueCount, gfx3d_ysort_compare);
|
||||
|
||||
if (!gfx3d.state.sortmode)
|
||||
{
|
||||
//if we are autosorting translucent polys, we need to do this also
|
||||
//TODO - this is unverified behavior. need a test case
|
||||
std::sort(gfx3d.indexlist.list + polylist->opaqueCount, gfx3d.indexlist.list + polycount, gfx3d_ysort_compare);
|
||||
}
|
||||
|
||||
//switch to the new lists
|
||||
twiddleLists();
|
||||
|
||||
@ -2470,7 +2557,16 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
|
||||
drawPending = FALSE;
|
||||
|
||||
GPU->GetEventHandler()->DidApplyRender3DSettingsBegin();
|
||||
|
||||
const ClipperMode oldClippingMode = CurrentRenderer->GetPreferredPolygonClippingMode();
|
||||
GPU->Change3DRendererIfNeeded();
|
||||
const ClipperMode newClippingMode = CurrentRenderer->GetPreferredPolygonClippingMode();
|
||||
|
||||
if (oldClippingMode != newClippingMode)
|
||||
{
|
||||
gfx3d_GenerateRenderLists(newClippingMode);
|
||||
}
|
||||
|
||||
CurrentRenderer->ApplyRenderingSettings(gfx3d.renderState);
|
||||
GPU->GetEventHandler()->DidApplyRender3DSettingsEnd();
|
||||
|
||||
@ -3059,7 +3155,7 @@ static FORCEINLINE VERT clipPoint(const VERT *inside, const VERT *outside)
|
||||
ret.color_to_float();
|
||||
break;
|
||||
|
||||
case ClipperMode_InterpolateFull:
|
||||
case ClipperMode_FullColorInterpolate:
|
||||
INTERP(texcoord[0]); INTERP(texcoord[1]);
|
||||
INTERP(fcolor[0]); INTERP(fcolor[1]); INTERP(fcolor[2]);
|
||||
break;
|
||||
@ -3204,12 +3300,12 @@ typedef ClipperPlane<ClipperMode_Full, 0,-1,Stage2> Stage1; static Stage1
|
||||
|
||||
// Interpolated clippers
|
||||
static ClipperOutput clipperOuti;
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 2, 1,ClipperOutput> Stage6i; static Stage6 clipper6i (clipperOuti); // back plane //TODO - we need to parameterize back plane clipping
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 2,-1,Stage6i> Stage5i; static Stage5 clipper5i (clipper6i); // front plane
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 1, 1,Stage5i> Stage4i; static Stage4 clipper4i (clipper5i); // top plane
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 1,-1,Stage4i> Stage3i; static Stage3 clipper3i (clipper4i); // bottom plane
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 0, 1,Stage3i> Stage2i; static Stage2 clipper2i (clipper3i); // right plane
|
||||
typedef ClipperPlane<ClipperMode_InterpolateFull, 0,-1,Stage2i> Stage1i; static Stage1 clipper1i (clipper2i); // left plane
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 2, 1,ClipperOutput> Stage6i; static Stage6 clipper6i (clipperOuti); // back plane //TODO - we need to parameterize back plane clipping
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 2,-1,Stage6i> Stage5i; static Stage5 clipper5i (clipper6i); // front plane
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 1, 1,Stage5i> Stage4i; static Stage4 clipper4i (clipper5i); // top plane
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 1,-1,Stage4i> Stage3i; static Stage3 clipper3i (clipper4i); // bottom plane
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 0, 1,Stage3i> Stage2i; static Stage2 clipper2i (clipper3i); // right plane
|
||||
typedef ClipperPlane<ClipperMode_FullColorInterpolate, 0,-1,Stage2i> Stage1i; static Stage1 clipper1i (clipper2i); // left plane
|
||||
|
||||
// Determine's clip status only
|
||||
static ClipperOutput clipperOutd;
|
||||
@ -3252,7 +3348,7 @@ void GFX3D_Clipper::Reset()
|
||||
}
|
||||
|
||||
template <ClipperMode CLIPPERMODE>
|
||||
void GFX3D_Clipper::ClipPoly(const POLY &poly, const VERT **verts)
|
||||
bool GFX3D_Clipper::ClipPoly(const u16 polyIndex, const POLY &poly, const VERT **verts)
|
||||
{
|
||||
CLIPLOG("==Begin poly==\n");
|
||||
|
||||
@ -3272,7 +3368,7 @@ void GFX3D_Clipper::ClipPoly(const POLY &poly, const VERT **verts)
|
||||
break;
|
||||
}
|
||||
|
||||
case ClipperMode_InterpolateFull:
|
||||
case ClipperMode_FullColorInterpolate:
|
||||
{
|
||||
clipper1i.init(this->_clippedPolyList[this->_clippedPolyCounter].clipVerts);
|
||||
for (size_t i = 0; i < type; i++)
|
||||
@ -3298,16 +3394,17 @@ void GFX3D_Clipper::ClipPoly(const POLY &poly, const VERT **verts)
|
||||
{
|
||||
//a totally clipped poly. discard it.
|
||||
//or, a degenerate poly. we're not handling these right now
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_clippedPolyList[this->_clippedPolyCounter].type = outType;
|
||||
this->_clippedPolyList[this->_clippedPolyCounter].poly = (POLY *)&poly;
|
||||
CPoly &thePoly = this->_clippedPolyList[this->_clippedPolyCounter];
|
||||
thePoly.index = polyIndex;
|
||||
thePoly.type = outType;
|
||||
thePoly.poly = (POLY *)&poly;
|
||||
|
||||
this->_clippedPolyCounter++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//these templates needed to be instantiated manually
|
||||
template void GFX3D_Clipper::ClipPoly<ClipperMode_Full>(const POLY &poly, const VERT **verts);
|
||||
template void GFX3D_Clipper::ClipPoly<ClipperMode_InterpolateFull>(const POLY &poly, const VERT **verts);
|
||||
template void GFX3D_Clipper::ClipPoly<ClipperMode_DetermineClipOnly>(const POLY &poly, const VERT **verts);
|
||||
|
@ -479,13 +479,14 @@ struct VIEWPORT {
|
||||
|
||||
enum ClipperMode
|
||||
{
|
||||
ClipperMode_Full = 0,
|
||||
ClipperMode_InterpolateFull = 1,
|
||||
ClipperMode_DetermineClipOnly = 2
|
||||
ClipperMode_DetermineClipOnly = 0, // Retains only the pointer to the original polygon info. All other information in CPoly is considered undefined.
|
||||
ClipperMode_Full = 1, // Retains all of the modified polygon's info in CPoly, including the clipped vertex info.
|
||||
ClipperMode_FullColorInterpolate = 2 // Same as ClipperMode_Full, but the vertex color attribute is better interpolated.
|
||||
};
|
||||
|
||||
struct CPoly
|
||||
{
|
||||
u16 index; // The index number of this polygon in the full polygon list.
|
||||
PolygonType type; //otherwise known as "count" of verts
|
||||
POLY *poly;
|
||||
VERT clipVerts[MAX_CLIPPED_VERTS];
|
||||
@ -507,7 +508,7 @@ public:
|
||||
size_t GetPolyCount() const;
|
||||
|
||||
void Reset();
|
||||
template<ClipperMode CLIPPERMODE> void ClipPoly(const POLY &poly, const VERT **verts); // the entry point for poly clipping
|
||||
template<ClipperMode CLIPPERMODE> bool ClipPoly(const u16 polyIndex, const POLY &poly, const VERT **verts); // the entry point for poly clipping
|
||||
};
|
||||
|
||||
//used to communicate state to the renderer
|
||||
@ -601,6 +602,10 @@ struct GFX3D
|
||||
VERT *vertList;
|
||||
INDEXLIST indexlist;
|
||||
|
||||
size_t clippedPolyCount;
|
||||
size_t clippedPolyOpaqueCount;
|
||||
CPoly *clippedPolyList;
|
||||
|
||||
size_t vertListCount;
|
||||
u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames.
|
||||
};
|
||||
|
@ -1867,6 +1867,11 @@ Render3DError SoftRasterizerRenderer::InitTables()
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
ClipperMode SoftRasterizerRenderer::GetPreferredPolygonClippingMode() const
|
||||
{
|
||||
return (this->_enableHighPrecisionColorInterpolation) ? ClipperMode_FullColorInterpolate : ClipperMode_Full;
|
||||
}
|
||||
|
||||
void SoftRasterizerRenderer::performViewportTransforms()
|
||||
{
|
||||
const float wScalar = (float)this->_framebufferWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
@ -2020,15 +2025,9 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
|
||||
|
||||
// Keep the current render states for later use
|
||||
this->currentRenderState = (GFX3D_State *)&engine.renderState;
|
||||
|
||||
if (this->_enableHighPrecisionColorInterpolation)
|
||||
{
|
||||
this->_PerformClipping<ClipperMode_InterpolateFull>(engine.vertList, engine.polylist, &engine.indexlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_PerformClipping<ClipperMode_Full>(engine.vertList, engine.polylist, &engine.indexlist);
|
||||
}
|
||||
this->_clippedPolyCount = engine.clippedPolyCount;
|
||||
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
|
||||
this->_clippedPolyList = engine.clippedPolyList;
|
||||
|
||||
const bool doMultithreadedStateSetup = (this->_threadCount >= 2);
|
||||
|
||||
|
@ -191,6 +191,8 @@ public:
|
||||
SoftRasterizerRenderer();
|
||||
virtual ~SoftRasterizerRenderer();
|
||||
|
||||
virtual ClipperMode GetPreferredPolygonClippingMode() const;
|
||||
|
||||
void performViewportTransforms();
|
||||
void performBackfaceTests();
|
||||
void performCoordAdjustment();
|
||||
|
@ -249,9 +249,6 @@ Render3D::Render3D()
|
||||
_textureList[i] = NULL;
|
||||
}
|
||||
|
||||
_clippedPolyList = (CPoly *)malloc_alignedCacheLine(POLYLIST_SIZE * 2 * sizeof(CPoly));
|
||||
_clipper.SetClippedPolyBufferPtr(_clippedPolyList);
|
||||
|
||||
memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer));
|
||||
memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer));
|
||||
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
|
||||
@ -267,8 +264,6 @@ Render3D::~Render3D()
|
||||
this->_textureDeposterizeDstSurface.Surface = NULL;
|
||||
this->_textureDeposterizeDstSurface.workingSurface[0] = NULL;
|
||||
}
|
||||
|
||||
free_aligned(this->_clippedPolyList);
|
||||
}
|
||||
|
||||
const Render3DDeviceInfo& Render3D::GetDeviceInfo()
|
||||
@ -404,6 +399,11 @@ Render3DTexture* Render3D::GetTextureByPolygonRenderIndex(size_t polyRenderIndex
|
||||
return this->_textureList[polyRenderIndex];
|
||||
}
|
||||
|
||||
ClipperMode Render3D::GetPreferredPolygonClippingMode() const
|
||||
{
|
||||
return ClipperMode_DetermineClipOnly;
|
||||
}
|
||||
|
||||
const CPoly& Render3D::GetClippedPolyByIndex(size_t index) const
|
||||
{
|
||||
return this->_clippedPolyList[index];
|
||||
@ -414,44 +414,6 @@ size_t Render3D::GetClippedPolyCount() const
|
||||
return this->_clippedPolyCount;
|
||||
}
|
||||
|
||||
template <ClipperMode CLIPPERMODE>
|
||||
void Render3D::_PerformClipping(const VERT *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
|
||||
{
|
||||
//submit all polys to clipper
|
||||
this->_clipper.Reset();
|
||||
|
||||
size_t i = 0;
|
||||
for (; i < polyList->opaqueCount; i++)
|
||||
{
|
||||
const POLY &poly = polyList->list[indexList->list[i]];
|
||||
const VERT *clipVerts[4] = {
|
||||
&vertList[poly.vertIndexes[0]],
|
||||
&vertList[poly.vertIndexes[1]],
|
||||
&vertList[poly.vertIndexes[2]],
|
||||
(poly.type == POLYGON_TYPE_QUAD) ? &vertList[poly.vertIndexes[3]] : NULL
|
||||
};
|
||||
|
||||
this->_clipper.ClipPoly<CLIPPERMODE>(poly, clipVerts);
|
||||
}
|
||||
|
||||
this->_clippedPolyOpaqueCount = this->_clipper.GetPolyCount();
|
||||
|
||||
for (; i < polyList->count; i++)
|
||||
{
|
||||
const POLY &poly = polyList->list[indexList->list[i]];
|
||||
const VERT *clipVerts[4] = {
|
||||
&vertList[poly.vertIndexes[0]],
|
||||
&vertList[poly.vertIndexes[1]],
|
||||
&vertList[poly.vertIndexes[2]],
|
||||
(poly.type == POLYGON_TYPE_QUAD) ? &vertList[poly.vertIndexes[3]] : NULL
|
||||
};
|
||||
|
||||
this->_clipper.ClipPoly<CLIPPERMODE>(poly, clipVerts);
|
||||
}
|
||||
|
||||
this->_clippedPolyCount = this->_clipper.GetPolyCount();
|
||||
}
|
||||
|
||||
Render3DError Render3D::ApplyRenderingSettings(const GFX3D_State &renderState)
|
||||
{
|
||||
this->_enableEdgeMark = (CommonSettings.GFX3D_EdgeMark) ? renderState.enableEdgeMarking : false;
|
||||
@ -1019,9 +981,5 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState)
|
||||
|
||||
#endif // defined(ENABLE_AVX2) || defined(ENABLE_SSE2)
|
||||
|
||||
template void Render3D::_PerformClipping<ClipperMode_Full>(const VERT *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||
template void Render3D::_PerformClipping<ClipperMode_InterpolateFull>(const VERT *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||
template void Render3D::_PerformClipping<ClipperMode_DetermineClipOnly>(const VERT *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||
|
||||
template Render3D_SIMD<16>::Render3D_SIMD();
|
||||
template Render3D_SIMD<32>::Render3D_SIMD();
|
||||
|
@ -187,15 +187,12 @@ protected:
|
||||
|
||||
size_t _clippedPolyCount;
|
||||
size_t _clippedPolyOpaqueCount;
|
||||
GFX3D_Clipper _clipper;
|
||||
CPoly *_clippedPolyList;
|
||||
|
||||
CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u32 clearImageDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u8 clearImageFogBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
|
||||
template<ClipperMode CLIPPERMODE> void _PerformClipping(const VERT *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||
|
||||
template<bool ISCOLORBLANK, bool ISDEPTHBLANK> void _ClearImageScrolledLoop(const u8 xScroll, const u8 yScroll, const u16 *__restrict inColor16, const u16 *__restrict inDepth16,
|
||||
u16 *__restrict outColor16, u32 *__restrict outDepth24, u8 *__restrict outFog);
|
||||
|
||||
@ -272,6 +269,7 @@ public:
|
||||
void SetTextureProcessingProperties();
|
||||
Render3DTexture* GetTextureByPolygonRenderIndex(size_t polyRenderIndex) const;
|
||||
|
||||
virtual ClipperMode GetPreferredPolygonClippingMode() const;
|
||||
const CPoly& GetClippedPolyByIndex(size_t index) const;
|
||||
size_t GetClippedPolyCount() const;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user