mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-12 07:01:09 +00:00
Merge branch 'ogl-sprite-qsort' into 'next'
Faster OGL sprite sorting algorithm See merge request STJr/SRB2!1008
This commit is contained in:
commit
7317bbb692
2 changed files with 56 additions and 117 deletions
|
@ -61,9 +61,6 @@ typedef struct
|
||||||
// equivalent of the software renderer's vissprites
|
// equivalent of the software renderer's vissprites
|
||||||
typedef struct gr_vissprite_s
|
typedef struct gr_vissprite_s
|
||||||
{
|
{
|
||||||
// Doubly linked list
|
|
||||||
struct gr_vissprite_s *prev;
|
|
||||||
struct gr_vissprite_s *next;
|
|
||||||
float x1, x2;
|
float x1, x2;
|
||||||
float tz, ty;
|
float tz, ty;
|
||||||
//lumpnum_t patchlumpnum;
|
//lumpnum_t patchlumpnum;
|
||||||
|
|
|
@ -4179,96 +4179,45 @@ 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];
|
||||||
|
|
||||||
static void HWR_SortVisSprites(void)
|
// Note: 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)
|
||||||
{
|
{
|
||||||
UINT32 i;
|
gr_vissprite_t* spr1 = *(gr_vissprite_t*const*)p1;
|
||||||
gr_vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
|
gr_vissprite_t* spr2 = *(gr_vissprite_t*const*)p2;
|
||||||
gr_vissprite_t *best = NULL;
|
int idiff;
|
||||||
gr_vissprite_t unsorted;
|
float fdiff;
|
||||||
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++)
|
|
||||||
{
|
|
||||||
best = NULL;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Make transparent sprites last. Comment from the previous sort implementation:
|
||||||
// Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the
|
// 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
|
// 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.
|
// 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
|
// 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
|
// TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that
|
||||||
best = gr_vsprsortedhead.next;
|
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)
|
||||||
|
{
|
||||||
|
UINT32 i;
|
||||||
for (i = 0; i < gr_visspritecount; i++)
|
for (i = 0; i < gr_visspritecount; i++)
|
||||||
{
|
{
|
||||||
if ((best->mobj->flags2 & MF2_SHADOW) || (best->mobj->frame & FF_TRANSMASK))
|
gr_vsprorder[i] = HWR_GetVisSprite(i);
|
||||||
{
|
|
||||||
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
|
||||||
|
@ -4575,16 +4524,11 @@ static void HWR_CreateDrawNodes(void)
|
||||||
// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other
|
// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other
|
||||||
static void HWR_DrawSprites(void)
|
static void HWR_DrawSprites(void)
|
||||||
{
|
{
|
||||||
if (gr_visspritecount > 0)
|
UINT32 i;
|
||||||
{
|
|
||||||
gr_vissprite_t *spr;
|
|
||||||
HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value);
|
HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value);
|
||||||
|
for (i = 0; i < gr_visspritecount; i++)
|
||||||
// draw all vissprites back to front
|
|
||||||
for (spr = gr_vsprsortedhead.next;
|
|
||||||
spr != &gr_vsprsortedhead;
|
|
||||||
spr = spr->next)
|
|
||||||
{
|
{
|
||||||
|
gr_vissprite_t *spr = gr_vsprorder[i];
|
||||||
#ifdef HWPRECIP
|
#ifdef HWPRECIP
|
||||||
if (spr->precip)
|
if (spr->precip)
|
||||||
HWR_DrawPrecipitationSprite(spr);
|
HWR_DrawPrecipitationSprite(spr);
|
||||||
|
@ -4618,9 +4562,7 @@ static void HWR_DrawSprites(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 0);
|
HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue