mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-01-27 19:50:51 +00:00
Faster sprite sorting algorithm
This commit is contained in:
parent
628bd27b88
commit
b5fb88922a
1 changed files with 51 additions and 109 deletions
|
@ -3685,96 +3685,44 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Sort vissprites by distance
|
// Sort vissprites by distance
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
static gr_vissprite_t gr_vsprsortedhead;
|
|
||||||
|
gr_vissprite_t* gr_vsprorder[MAXVISSPRITES];
|
||||||
|
|
||||||
|
// For more correct transparency the transparent sprites would need to be
|
||||||
|
// sorted and drawn together with transparent surfaces.
|
||||||
|
static int CompareVisSprites(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
gr_vissprite_t* spr1 = *(gr_vissprite_t*const*)p1;
|
||||||
|
gr_vissprite_t* spr2 = *(gr_vissprite_t*const*)p2;
|
||||||
|
int idiff;
|
||||||
|
float fdiff;
|
||||||
|
|
||||||
|
// make transparent sprites last
|
||||||
|
// "boolean to int"
|
||||||
|
|
||||||
|
int transparency1 = (spr1->mobj->flags2 & MF2_SHADOW) || (spr1->mobj->frame & FF_TRANSMASK);
|
||||||
|
int transparency2 = (spr2->mobj->flags2 & MF2_SHADOW) || (spr2->mobj->frame & FF_TRANSMASK);
|
||||||
|
idiff = transparency1 - transparency2;
|
||||||
|
if (idiff != 0) return idiff;
|
||||||
|
|
||||||
|
fdiff = spr2->tz - spr1->tz;// this order seems correct when checking with apitrace. Back to front.
|
||||||
|
if (fabsf(fdiff) < 1.0E-36f)
|
||||||
|
return spr1->dispoffset - spr2->dispoffset;// smallest dispoffset first if sprites are at (almost) same location.
|
||||||
|
else if (fdiff > 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void HWR_SortVisSprites(void)
|
static void HWR_SortVisSprites(void)
|
||||||
{
|
{
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
gr_vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
|
|
||||||
gr_vissprite_t *best = NULL;
|
|
||||||
gr_vissprite_t unsorted;
|
|
||||||
float bestdist = 0.0f;
|
|
||||||
INT32 bestdispoffset = 0;
|
|
||||||
|
|
||||||
if (!gr_visspritecount)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dsfirst = HWR_GetVisSprite(0);
|
|
||||||
|
|
||||||
for (i = 0, dsnext = dsfirst, ds = NULL; i < gr_visspritecount; i++)
|
|
||||||
{
|
|
||||||
dsprev = ds;
|
|
||||||
ds = dsnext;
|
|
||||||
if (i < gr_visspritecount - 1) dsnext = HWR_GetVisSprite(i + 1);
|
|
||||||
|
|
||||||
ds->next = dsnext;
|
|
||||||
ds->prev = dsprev;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix first and last. ds still points to the last one after the loop
|
|
||||||
dsfirst->prev = &unsorted;
|
|
||||||
unsorted.next = dsfirst;
|
|
||||||
if (ds)
|
|
||||||
ds->next = &unsorted;
|
|
||||||
unsorted.prev = ds;
|
|
||||||
|
|
||||||
// pull the vissprites out by scale
|
|
||||||
gr_vsprsortedhead.next = gr_vsprsortedhead.prev = &gr_vsprsortedhead;
|
|
||||||
for (i = 0; i < gr_visspritecount; i++)
|
for (i = 0; i < gr_visspritecount; i++)
|
||||||
{
|
{
|
||||||
best = NULL;
|
gr_vsprorder[i] = HWR_GetVisSprite(i);
|
||||||
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
|
|
||||||
{
|
|
||||||
if (!best || ds->tz > bestdist)
|
|
||||||
{
|
|
||||||
bestdist = ds->tz;
|
|
||||||
bestdispoffset = ds->dispoffset;
|
|
||||||
best = ds;
|
|
||||||
}
|
|
||||||
// order visprites of same scale by dispoffset, smallest first
|
|
||||||
else if (fabsf(ds->tz - bestdist) < 1.0E-36f && ds->dispoffset < bestdispoffset)
|
|
||||||
{
|
|
||||||
bestdispoffset = ds->dispoffset;
|
|
||||||
best = ds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (best)
|
|
||||||
{
|
|
||||||
best->next->prev = best->prev;
|
|
||||||
best->prev->next = best->next;
|
|
||||||
best->next = &gr_vsprsortedhead;
|
|
||||||
best->prev = gr_vsprsortedhead.prev;
|
|
||||||
}
|
|
||||||
gr_vsprsortedhead.prev->next = best;
|
|
||||||
gr_vsprsortedhead.prev = best;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the
|
|
||||||
// mix and they want to be translucent. So let's place all the translucent sprites and MD2's AFTER
|
|
||||||
// everything else, but still ordered of course, the depth buffer can handle the opaque ones plenty fine.
|
|
||||||
// We just need to move all translucent ones to the end in order
|
|
||||||
// TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that
|
|
||||||
best = gr_vsprsortedhead.next;
|
|
||||||
for (i = 0; i < gr_visspritecount; i++)
|
|
||||||
{
|
|
||||||
if ((best->mobj->flags2 & MF2_SHADOW) || (best->mobj->frame & FF_TRANSMASK))
|
|
||||||
{
|
|
||||||
if (best == gr_vsprsortedhead.next)
|
|
||||||
{
|
|
||||||
gr_vsprsortedhead.next = best->next;
|
|
||||||
}
|
|
||||||
best->prev->next = best->next;
|
|
||||||
best->next->prev = best->prev;
|
|
||||||
best->prev = gr_vsprsortedhead.prev;
|
|
||||||
gr_vsprsortedhead.prev->next = best;
|
|
||||||
gr_vsprsortedhead.prev = best;
|
|
||||||
ds = best;
|
|
||||||
best = best->next;
|
|
||||||
ds->next = &gr_vsprsortedhead;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
best = best->next;
|
|
||||||
}
|
}
|
||||||
|
qsort(gr_vsprorder, gr_visspritecount, sizeof(gr_vissprite_t*), CompareVisSprites);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A drawnode is something that points to a 3D floor, 3D side, or masked
|
// A drawnode is something that points to a 3D floor, 3D side, or masked
|
||||||
|
@ -4068,34 +4016,28 @@ void HWR_RenderDrawNodes(void)
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
void HWR_DrawSprites(void)
|
void HWR_DrawSprites(void)
|
||||||
{
|
{
|
||||||
if (gr_visspritecount > 0)
|
UINT32 i;
|
||||||
|
for (i = 0; i < gr_visspritecount; i++)
|
||||||
{
|
{
|
||||||
gr_vissprite_t *spr;
|
gr_vissprite_t *spr = gr_vsprorder[i];
|
||||||
|
if (spr->precip)
|
||||||
// draw all vissprites back to front
|
HWR_DrawPrecipitationSprite(spr);
|
||||||
for (spr = gr_vsprsortedhead.next;
|
else
|
||||||
spr != &gr_vsprsortedhead;
|
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||||
spr = spr->next)
|
{
|
||||||
{
|
// 8/1/19: Only don't display player models if no default SPR_PLAY is found.
|
||||||
if (spr->precip)
|
if (!cv_grmdls.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && ((!cv_grfallbackplayermodel.value) || md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f)))
|
||||||
HWR_DrawPrecipitationSprite(spr);
|
HWR_DrawSprite(spr);
|
||||||
else
|
|
||||||
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
|
||||||
{
|
|
||||||
// 8/1/19: Only don't display player models if no default SPR_PLAY is found.
|
|
||||||
if (!cv_grmdls.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && ((!cv_grfallbackplayermodel.value) || md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f)))
|
|
||||||
HWR_DrawSprite(spr);
|
|
||||||
else
|
|
||||||
HWR_DrawMD2(spr);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
HWR_DrawMD2(spr);
|
||||||
if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
|
}
|
||||||
HWR_DrawSprite(spr);
|
else
|
||||||
else
|
{
|
||||||
HWR_DrawMD2(spr);
|
if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
|
||||||
}
|
HWR_DrawSprite(spr);
|
||||||
}
|
else
|
||||||
|
HWR_DrawMD2(spr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue