Merge branch 'optimize-clip-sprites' into 'master'

Optimize sprite sorting by excluding sprites that are completely obscured by geometry

See merge request KartKrew/Kart!1146
This commit is contained in:
Oni 2023-04-08 03:24:05 +00:00
commit 7ed6332e2d
2 changed files with 37 additions and 25 deletions

View file

@ -2713,39 +2713,41 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
// //
static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end) static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end)
{ {
UINT32 i, linkedvissprites = 0; UINT32 i, count = 0;
vissprite_t *ds, *dsprev, *dsnext, *dsfirst; vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
vissprite_t *best = NULL; vissprite_t *best = NULL;
vissprite_t unsorted; vissprite_t unsorted;
fixed_t bestscale; fixed_t bestscale;
INT32 bestdispoffset; INT32 bestdispoffset;
unsorted.next = unsorted.prev = &unsorted; dsfirst = &unsorted;
dsprev = dsfirst;
dsnext = dsfirst;
dsfirst = R_GetVisSprite(start); I_Assert(start <= end);
// The first's prev and last's next will be set to for (i = start; i < end; ++i)
// nonsense, but are fixed in a moment
for (i = start, dsnext = dsfirst, ds = NULL; i < end; i++)
{ {
dsprev = ds; ds = R_GetVisSprite(i);
ds = dsnext;
if (i < end - 1) dsnext = R_GetVisSprite(i + 1);
ds->next = dsnext; // Do not include this sprite, since it is completely obscured
ds->prev = dsprev; if (ds->cut & SC_CULL)
ds->linkdraw = NULL; {
continue;
} }
// Fix first and last. ds still points to the last one after the loop dsnext = ds;
dsfirst->prev = &unsorted; dsnext->linkdraw = NULL;
unsorted.next = dsfirst;
if (ds) dsprev->next = dsnext;
{ dsnext->prev = dsprev;
ds->next = &unsorted; dsprev = dsnext;
ds->linkdraw = NULL;
count++;
} }
unsorted.prev = ds;
dsnext->next = dsfirst;
dsfirst->prev = dsnext;
// bundle linkdraw // bundle linkdraw
for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev) for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev)
@ -2791,7 +2793,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// remove from chain // remove from chain
ds->next->prev = ds->prev; ds->next->prev = ds->prev;
ds->prev->next = ds->next; ds->prev->next = ds->next;
linkedvissprites++; count--;
if (dsfirst != &unsorted) if (dsfirst != &unsorted)
{ {
@ -2820,7 +2822,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// pull the vissprites out by scale // pull the vissprites out by scale
vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead; vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead;
for (i = start; i < end-linkedvissprites; i++) for (i = 0; i < count; i++)
{ {
bestscale = bestdispoffset = INT32_MAX; bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next) for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
@ -3265,6 +3267,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
fixed_t scale; fixed_t scale;
fixed_t lowscale; fixed_t lowscale;
INT32 silhouette; INT32 silhouette;
INT32 xclip;
if ((spr->renderflags & RF_ALWAYSONTOP) || cv_debugrender_spriteclip.value) if ((spr->renderflags & RF_ALWAYSONTOP) || cv_debugrender_spriteclip.value)
{ {
@ -3447,7 +3450,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
// all clipping has been performed, so store the values - what, did you think we were drawing them NOW? // all clipping has been performed, so store the values - what, did you think we were drawing them NOW?
// check for unclipped columns // check for unclipped columns
for (x = x1; x <= x2; x++) for (xclip = x = x1; x <= x2; x++)
{ {
if (spr->clipbot[x] == CLIP_UNDEF) if (spr->clipbot[x] == CLIP_UNDEF)
spr->clipbot[x] = (INT16)viewheight; spr->clipbot[x] = (INT16)viewheight;
@ -3455,9 +3458,17 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
if (spr->cliptop[x] == CLIP_UNDEF) if (spr->cliptop[x] == CLIP_UNDEF)
//Fab : 26-04-98: was -1, now clips against console bottom //Fab : 26-04-98: was -1, now clips against console bottom
spr->cliptop[x] = (INT16)con_clipviewtop; spr->cliptop[x] = (INT16)con_clipviewtop;
// Sprite is completely above or below clip plane
if (spr->szt >= spr->clipbot[x] || spr->sz <= spr->cliptop[x])
xclip++;
} }
if (portal) if (xclip == x)
{
spr->cut |= SC_CULL; // completely skip this sprite going forward
}
else if (portal)
{ {
INT32 start_index = max(portal->start, x1); INT32 start_index = max(portal->start, x1);
INT32 end_index = min(portal->start + portal->end - portal->start, x2); INT32 end_index = min(portal->start + portal->end - portal->start, x2);

View file

@ -142,6 +142,7 @@ typedef enum
// srb2kart // srb2kart
SC_SEMIBRIGHT = 1<<12, SC_SEMIBRIGHT = 1<<12,
SC_BBOX = 1<<13, SC_BBOX = 1<<13,
SC_CULL = 1<<14,
// masks // masks
SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK SC_FLAGMASK = ~SC_CUTMASK