mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-21 11:21:11 +00:00
Merge branch 'sprite-clip-optimization' into 'next'
Optimize sprite rendering by ignoring completely occluded sprites See merge request STJr/SRB2!2131
This commit is contained in:
commit
afee1cb687
4 changed files with 123 additions and 60 deletions
28
src/r_main.c
28
src/r_main.c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
124
src/r_things.c
124
src/r_things.c
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -896,7 +897,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
frac = vis->startfrac;
|
||||
windowtop = windowbottom = sprbotscreen = INT32_MAX;
|
||||
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
|
||||
if (vis->cut & SC_SHADOW && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
|
||||
this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale);
|
||||
if (this_scale <= 0)
|
||||
this_scale = 1;
|
||||
|
@ -906,10 +907,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
{
|
||||
vis->scale = FixedMul(vis->scale, this_scale);
|
||||
vis->scalestep = FixedMul(vis->scalestep, this_scale);
|
||||
vis->xiscale = FixedDiv(vis->xiscale,this_scale);
|
||||
vis->xiscale = FixedDiv(vis->xiscale, this_scale);
|
||||
vis->cut |= SC_ISSCALED;
|
||||
}
|
||||
dc_texturemid = FixedDiv(dc_texturemid,this_scale);
|
||||
dc_texturemid = FixedDiv(dc_texturemid, this_scale);
|
||||
}
|
||||
|
||||
spryscale = vis->scale;
|
||||
|
@ -1768,9 +1769,6 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
I_Assert(lump < max_spritelumps);
|
||||
|
||||
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||
this_scale = FixedMul(this_scale, ((skin_t *)thing->skin)->highresscale);
|
||||
|
||||
spr_width = spritecachedinfo[lump].width;
|
||||
spr_height = spritecachedinfo[lump].height;
|
||||
spr_offset = spritecachedinfo[lump].offset;
|
||||
|
@ -1820,6 +1818,14 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
// calculate edges of the shape
|
||||
spritexscale = interp.spritexscale;
|
||||
spriteyscale = interp.spriteyscale;
|
||||
|
||||
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||
{
|
||||
fixed_t highresscale = ((skin_t *)thing->skin)->highresscale;
|
||||
spritexscale = FixedMul(spritexscale, highresscale);
|
||||
spriteyscale = FixedMul(spriteyscale, highresscale);
|
||||
}
|
||||
|
||||
if (spritexscale < 1 || spriteyscale < 1)
|
||||
return;
|
||||
|
||||
|
@ -2645,6 +2651,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;
|
||||
|
||||
|
@ -2671,21 +2685,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)
|
||||
|
@ -2737,12 +2757,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3173,6 +3196,44 @@ static void R_HeightSecClip(vissprite_t *spr, INT32 x1, INT32 x2)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2)
|
||||
{
|
||||
INT16 sz = spr->sz;
|
||||
INT16 szt = spr->szt;
|
||||
|
||||
fixed_t texturemid, yscale, scalestep = spr->scalestep;
|
||||
INT32 height;
|
||||
|
||||
if (scalestep)
|
||||
{
|
||||
height = spr->patch->height;
|
||||
yscale = spr->scale;
|
||||
scalestep = FixedMul(scalestep, spr->spriteyscale);
|
||||
|
||||
if (spr->thingscale != FRACUNIT)
|
||||
texturemid = FixedDiv(spr->texturemid, max(spr->thingscale, 1));
|
||||
else
|
||||
texturemid = spr->texturemid;
|
||||
}
|
||||
|
||||
for (INT32 x = x1; x <= x2; x++)
|
||||
{
|
||||
if (scalestep)
|
||||
{
|
||||
fixed_t top = centeryfrac - FixedMul(texturemid, yscale);
|
||||
fixed_t bottom = top + (height * yscale);
|
||||
szt = (INT16)(top >> FRACBITS);
|
||||
sz = (INT16)(bottom >> FRACBITS);
|
||||
yscale += scalestep;
|
||||
}
|
||||
|
||||
if (spr->cliptop[x] < spr->clipbot[x] && sz > spr->cliptop[x] && szt < spr->clipbot[x])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// R_ClipVisSprite
|
||||
// Clips vissprites without drawing, so that portals can work. -Red
|
||||
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
|
||||
|
@ -3316,8 +3377,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)
|
||||
|
@ -3342,6 +3402,14 @@ 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)
|
||||
{
|
||||
if (!R_CheckSpriteVisible(spr, x1, x2))
|
||||
spr->cut |= SC_NOTVISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
||||
|
@ -3410,8 +3478,19 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
|||
{
|
||||
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
|
||||
|
||||
if (spr->cut & SC_BBOX)
|
||||
if (cv_spriteclip.value
|
||||
&& (spr->szt > vid.height || spr->sz < 0)
|
||||
&& !((spr->cut & SC_SPLAT) || spr->scalestep))
|
||||
{
|
||||
spr->cut |= SC_NOTVISIBLE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spr->cut & SC_BBOX)
|
||||
{
|
||||
numvisiblesprites++;
|
||||
continue;
|
||||
}
|
||||
|
||||
INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1;
|
||||
INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2;
|
||||
|
@ -3433,6 +3512,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
|||
}
|
||||
|
||||
R_ClipVisSprite(spr, x1, x2, portal);
|
||||
|
||||
if ((spr->cut & SC_NOTVISIBLE) == 0)
|
||||
numvisiblesprites++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue