mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-03-10 03:12:10 +00:00
Merge branch 'clip-sprites-optimize' into 'master'
Drawseg clipping optimized, from prboom-plus See merge request KartKrew/Kart-Public!304
This commit is contained in:
commit
4555f3240e
2 changed files with 223 additions and 99 deletions
142
src/r_things.c
142
src/r_things.c
|
@ -80,6 +80,33 @@ static spriteframe_t sprtemp[64];
|
|||
static size_t maxframe;
|
||||
static const char *spritename;
|
||||
|
||||
//
|
||||
// Clipping against drawsegs optimization, from prboom-plus
|
||||
//
|
||||
// TODO: This should be done with proper subsector pass through
|
||||
// sprites which would ideally remove the need to do it at all.
|
||||
// Unfortunately, SRB2's drawing loop has lots of annoying
|
||||
// changes from Doom for portals, which make it hard to implement.
|
||||
|
||||
typedef struct drawseg_xrange_item_s
|
||||
{
|
||||
INT16 x1, x2;
|
||||
drawseg_t *user;
|
||||
} drawseg_xrange_item_t;
|
||||
|
||||
typedef struct drawsegs_xrange_s
|
||||
{
|
||||
drawseg_xrange_item_t *items;
|
||||
INT32 count;
|
||||
} drawsegs_xrange_t;
|
||||
|
||||
#define DS_RANGES_COUNT 3
|
||||
static drawsegs_xrange_t drawsegs_xranges[DS_RANGES_COUNT];
|
||||
|
||||
static drawseg_xrange_item_t *drawsegs_xrange;
|
||||
static size_t drawsegs_xrange_size = 0;
|
||||
static INT32 drawsegs_xrange_count = 0;
|
||||
|
||||
// ==========================================================================
|
||||
//
|
||||
// Sprite loading routines: support sprites in pwad, dehacked sprite renaming,
|
||||
|
@ -548,7 +575,7 @@ void R_DelSpriteDefs(UINT16 wadnum)
|
|||
//
|
||||
// GAME FUNCTIONS
|
||||
//
|
||||
static UINT32 visspritecount;
|
||||
UINT32 visspritecount;
|
||||
static UINT32 clippedvissprites;
|
||||
static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL};
|
||||
|
||||
|
@ -2274,10 +2301,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
|
|||
|
||||
// R_ClipSprites
|
||||
// Clips vissprites without drawing, so that portals can work. -Red
|
||||
void R_ClipSprites(void)
|
||||
{
|
||||
vissprite_t *spr;
|
||||
for (;clippedvissprites < visspritecount; clippedvissprites++)
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
|
||||
{
|
||||
drawseg_t *ds;
|
||||
INT32 x;
|
||||
|
@ -2287,10 +2311,10 @@ void R_ClipSprites(void)
|
|||
fixed_t lowscale;
|
||||
INT32 silhouette;
|
||||
|
||||
spr = R_GetVisSprite(clippedvissprites);
|
||||
|
||||
for (x = spr->x1; x <= spr->x2; x++)
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
spr->clipbot[x] = spr->cliptop[x] = -2;
|
||||
}
|
||||
|
||||
// Scan drawsegs from end to start for obscuring segs.
|
||||
// The first drawseg that has a greater scale
|
||||
|
@ -2299,19 +2323,23 @@ void R_ClipSprites(void)
|
|||
// Pointer check was originally nonportable
|
||||
// and buggy, by going past LEFT end of array:
|
||||
|
||||
// for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code
|
||||
for (ds = ds_p; ds-- > drawsegs ;)
|
||||
// e6y: optimization
|
||||
if (drawsegs_xrange_size)
|
||||
{
|
||||
const drawseg_xrange_item_t *last = &drawsegs_xrange[drawsegs_xrange_count - 1];
|
||||
drawseg_xrange_item_t *curr = &drawsegs_xrange[-1];
|
||||
|
||||
while (++curr <= last)
|
||||
{
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 > spr->x2 ||
|
||||
ds->x2 < spr->x1 ||
|
||||
(!ds->silhouette
|
||||
&& !ds->maskedtexturecol))
|
||||
if (curr->x1 > spr->x2 || curr->x2 < spr->x1)
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
}
|
||||
|
||||
ds = curr->user;
|
||||
|
||||
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
|
||||
continue; // is a portal
|
||||
|
||||
|
@ -2375,6 +2403,7 @@ void R_ClipSprites(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//SoM: 3/17/2000: Clip sprites in water.
|
||||
if (spr->heightsec != -1) // only things in specially marked sectors
|
||||
{
|
||||
|
@ -2457,6 +2486,91 @@ void R_ClipSprites(void)
|
|||
spr->cliptop[x] = (INT16)con_clipviewtop;
|
||||
}
|
||||
}
|
||||
|
||||
void R_ClipSprites(void)
|
||||
{
|
||||
const size_t maxdrawsegs = ds_p - drawsegs;
|
||||
const INT32 cx = viewwidth / 2;
|
||||
drawseg_t* ds;
|
||||
INT32 i;
|
||||
|
||||
// e6y
|
||||
// Reducing of cache misses in the following R_DrawSprite()
|
||||
// Makes sense for scenes with huge amount of drawsegs.
|
||||
// ~12% of speed improvement on epic.wad map05
|
||||
for (i = 0; i < DS_RANGES_COUNT; i++)
|
||||
{
|
||||
drawsegs_xranges[i].count = 0;
|
||||
}
|
||||
|
||||
if (visspritecount - clippedvissprites <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawsegs_xrange_size < maxdrawsegs)
|
||||
{
|
||||
drawsegs_xrange_size = 2 * maxdrawsegs;
|
||||
|
||||
for (i = 0; i < DS_RANGES_COUNT; i++)
|
||||
{
|
||||
drawsegs_xranges[i].items = Z_Realloc(
|
||||
drawsegs_xranges[i].items,
|
||||
drawsegs_xrange_size * sizeof(drawsegs_xranges[i].items[0]),
|
||||
PU_STATIC, NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (ds = ds_p; ds-- > drawsegs;)
|
||||
{
|
||||
if (ds->silhouette || ds->maskedtexturecol)
|
||||
{
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].x1 = ds->x1;
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].x2 = ds->x2;
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].user = ds;
|
||||
|
||||
// e6y: ~13% of speed improvement on sunder.wad map10
|
||||
if (ds->x1 < cx)
|
||||
{
|
||||
drawsegs_xranges[1].items[drawsegs_xranges[1].count] =
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count];
|
||||
drawsegs_xranges[1].count++;
|
||||
}
|
||||
|
||||
if (ds->x2 >= cx)
|
||||
{
|
||||
drawsegs_xranges[2].items[drawsegs_xranges[2].count] =
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count];
|
||||
drawsegs_xranges[2].count++;
|
||||
}
|
||||
|
||||
drawsegs_xranges[0].count++;
|
||||
}
|
||||
}
|
||||
|
||||
for (; clippedvissprites < visspritecount; clippedvissprites++)
|
||||
{
|
||||
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
|
||||
|
||||
if (spr->x2 < cx)
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[1].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[1].count;
|
||||
}
|
||||
else if (spr->x1 >= cx)
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[2].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[2].count;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[0].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[0].count;
|
||||
}
|
||||
|
||||
R_ClipVisSprite(spr, spr->x1, spr->x2);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -58,7 +58,6 @@ void R_DelSpriteDefs(UINT16 wadnum);
|
|||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||
void R_InitSprites(void);
|
||||
void R_ClearSprites(void);
|
||||
void R_ClipSprites(void);
|
||||
void R_DrawMasked(void);
|
||||
|
||||
// -----------
|
||||
|
@ -163,6 +162,17 @@ typedef struct vissprite_s
|
|||
fixed_t thingscale;
|
||||
} vissprite_t;
|
||||
|
||||
extern UINT32 visspritecount;
|
||||
|
||||
void R_ClipSprites(void);
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2);
|
||||
|
||||
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
|
||||
|
||||
// ----------
|
||||
// DRAW NODES
|
||||
// ----------
|
||||
|
||||
// A drawnode is something that points to a 3D floor, 3D side, or masked
|
||||
// middle texture. This is used for sorting with sprites.
|
||||
typedef struct drawnode_s
|
||||
|
|
Loading…
Reference in a new issue