Optimize sprite rendering by ignoring completely occluded sprites

This commit is contained in:
Lactozilla 2023-09-03 17:02:35 -03:00
parent 25c220d363
commit b8313ceda2
4 changed files with 77 additions and 53 deletions

View file

@ -41,16 +41,6 @@
#include "hardware/hw_main.h"
#endif
//profile stuff ---------------------------------------------------------
//#define TIMING
#ifdef TIMING
#include "p5prof.h"
INT64 mycount;
INT64 mytotal = 0;
//unsigned long nombre = 100000;
#endif
//profile stuff ---------------------------------------------------------
// Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048
@ -157,7 +147,8 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT,
consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_ffloorclip = CVAR_INIT ("r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_spriteclip = CVAR_INIT ("r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL);
consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL|CV_ALLOWLUA, CV_YesNo, R_SetViewSize);
consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL);
@ -1490,29 +1481,17 @@ void R_RenderPlayerView(player_t *player)
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
//profile stuff ---------------------------------------------------------
#ifdef TIMING
mytotal = 0;
ProfZeroTimer();
#endif
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1);
PS_STOP_TIMING(ps_bsptime);
ps_numsprites.value.i = visspritecount;
#ifdef TIMING
RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add
CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal);
#endif
//profile stuff ---------------------------------------------------------
Mask_Post(&masks[nummasks - 1]);
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
ps_numsprites.value.i = numvisiblesprites;
// Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0])
@ -1603,6 +1582,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_spriteclip);
CV_RegisterVar(&cv_cam_dist);
CV_RegisterVar(&cv_cam_still);

View file

@ -114,7 +114,7 @@ extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow;
extern consvar_t cv_ffloorclip;
extern consvar_t cv_ffloorclip, cv_spriteclip;
extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov;

View file

@ -524,7 +524,8 @@ void R_AddSpriteDefs(UINT16 wadnum)
//
// GAME FUNCTIONS
//
UINT32 visspritecount;
UINT32 visspritecount, numvisiblesprites;
static UINT32 clippedvissprites;
static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL};
@ -598,7 +599,7 @@ void R_InitSprites(void)
//
void R_ClearSprites(void)
{
visspritecount = clippedvissprites = 0;
visspritecount = numvisiblesprites = clippedvissprites = 0;
}
//
@ -2637,6 +2638,14 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// bundle linkdraw
for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev)
{
// Remove this sprite if it was determined to not be visible
if (ds->cut & SC_NOTVISIBLE)
{
ds->next->prev = ds->prev;
ds->prev->next = ds->next;
continue;
}
if (!(ds->cut & SC_LINKDRAW))
continue;
@ -2663,21 +2672,27 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
continue;
// don't connect if the tracer's top is cut off, but lower than the link's top
if ((dsfirst->cut & SC_TOP)
&& dsfirst->szt > ds->szt)
if ((dsfirst->cut & SC_TOP) && dsfirst->szt > ds->szt)
continue;
// don't connect if the tracer's bottom is cut off, but higher than the link's bottom
if ((dsfirst->cut & SC_BOTTOM)
&& dsfirst->sz < ds->sz)
if ((dsfirst->cut & SC_BOTTOM) && dsfirst->sz < ds->sz)
continue;
// If the object isn't visible, then the bounding box isn't either
if (ds->cut & SC_BBOX && dsfirst->cut & SC_NOTVISIBLE)
ds->cut |= SC_NOTVISIBLE;
break;
}
// remove from chain
ds->next->prev = ds->prev;
ds->prev->next = ds->next;
if (ds->cut & SC_NOTVISIBLE)
continue;
linkedvissprites++;
if (dsfirst != &unsorted)
@ -2729,12 +2744,15 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
best = ds;
}
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = vsprsortedhead;
best->prev = vsprsortedhead->prev;
vsprsortedhead->prev->next = best;
vsprsortedhead->prev = best;
if (best)
{
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = vsprsortedhead;
best->prev = vsprsortedhead->prev;
vsprsortedhead->prev->next = best;
vsprsortedhead->prev = best;
}
}
}
@ -3308,8 +3326,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
spr->clipbot[x] = (INT16)viewheight;
if (spr->cliptop[x] == -2)
//Fab : 26-04-98: was -1, now clips against console bottom
spr->cliptop[x] = (INT16)con_clipviewtop;
spr->cliptop[x] = -1;
}
if (portal)
@ -3334,6 +3351,23 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
spr->cliptop[x] = -1;
}
}
// Check if it'll be visible
// Not done for floorsprites.
if (cv_spriteclip.value && (spr->cut & SC_SPLAT) == 0)
{
for (x = x1; x <= x2; x++)
{
if (spr->cliptop[x] < spr->clipbot[x]
&& spr->sz > spr->cliptop[x]
&& spr->szt < spr->clipbot[x])
{
return;
}
}
spr->cut |= SC_NOTVISIBLE;
}
}
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
@ -3402,6 +3436,12 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
{
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
if (spr->szt > vid.height || spr->sz < 0)
{
spr->cut |= SC_NOTVISIBLE;
continue;
}
if (spr->cut & SC_BBOX)
continue;
@ -3425,6 +3465,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
}
R_ClipVisSprite(spr, x1, x2, portal);
if ((spr->cut & SC_NOTVISIBLE) == 0)
numvisiblesprites++;
}
}

View file

@ -123,21 +123,22 @@ typedef enum
SC_NONE = 0,
SC_TOP = 1,
SC_BOTTOM = 1<<1,
SC_NOTVISIBLE = 1<<2,
// other flags
SC_PRECIP = 1<<2,
SC_LINKDRAW = 1<<3,
SC_FULLBRIGHT = 1<<4,
SC_SEMIBRIGHT = 1<<5,
SC_FULLDARK = 1<<6,
SC_VFLIP = 1<<7,
SC_ISSCALED = 1<<8,
SC_ISROTATED = 1<<9,
SC_SHADOW = 1<<10,
SC_SHEAR = 1<<11,
SC_SPLAT = 1<<12,
SC_BBOX = 1<<13,
SC_PRECIP = 1<<3,
SC_LINKDRAW = 1<<4,
SC_FULLBRIGHT = 1<<5,
SC_SEMIBRIGHT = 1<<6,
SC_FULLDARK = 1<<7,
SC_VFLIP = 1<<8,
SC_ISSCALED = 1<<9,
SC_ISROTATED = 1<<10,
SC_SHADOW = 1<<11,
SC_SHEAR = 1<<12,
SC_SPLAT = 1<<13,
SC_BBOX = 1<<14,
// masks
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_CUTMASK = SC_TOP|SC_BOTTOM|SC_NOTVISIBLE,
SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e;
@ -219,7 +220,7 @@ typedef struct vissprite_s
INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing
} vissprite_t;
extern UINT32 visspritecount;
extern UINT32 visspritecount, numvisiblesprites;
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);