Convert r_visiblesprite to classes

This commit is contained in:
Magnus Norddahl 2017-01-11 19:33:02 +01:00
parent 8ed66791e7
commit 32b91dd978
8 changed files with 170 additions and 139 deletions

View file

@ -92,7 +92,6 @@ namespace swrenderer
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void R_SpanInitData ();
void R_DeinitSprites();
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -385,7 +384,7 @@ void R_InitRenderer()
static void R_ShutdownRenderer()
{
R_DeinitSprites();
RenderTranslucent::Deinit();
R_DeinitPlanes();
Clip3DFloors::Instance()->Cleanup();
R_DeinitOpenings();
@ -528,7 +527,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
R_ClearClipSegs (0, viewwidth);
R_ClearDrawSegs ();
R_ClearPlanes (true);
R_ClearSprites ();
RenderTranslucent::Clear();
// opening / clipping determination
RenderBSP::Instance()->ClearClip();
@ -577,7 +576,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
NetUpdate ();
MaskedCycles.Clock();
R_DrawMasked ();
RenderTranslucent::Render();
MaskedCycles.Unclock();
NetUpdate ();

View file

@ -96,7 +96,7 @@ namespace swrenderer
int savedextralight = extralight;
DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle;
ptrdiff_t savedvissprite_p = vissprite_p - vissprites;
ptrdiff_t savedvissprite_p = VisibleSpriteList::vissprite_p - VisibleSpriteList::vissprites;
ptrdiff_t savedds_p = ds_p - drawsegs;
size_t savedinteresting = FirstInterestingDrawseg;
double savedvisibility = R_GetVisibility();
@ -212,14 +212,14 @@ namespace swrenderer
memcpy(openings + draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
memcpy(openings + draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
firstvissprite = vissprite_p;
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprite_p;
firstdrawseg = draw_segment;
FirstInterestingDrawseg = InterestingDrawsegs.Size();
interestingStack.Push(FirstInterestingDrawseg);
ptrdiff_t diffnum = firstdrawseg - drawsegs;
drawsegStack.Push(diffnum);
diffnum = firstvissprite - vissprites;
diffnum = VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites;
visspriteStack.Push(diffnum);
viewposStack.Push(ViewPos);
visplaneStack.Push(pl);
@ -242,15 +242,15 @@ namespace swrenderer
drawsegStack.Pop(pd);
firstdrawseg = drawsegs + pd;
visspriteStack.Pop(pd);
firstvissprite = vissprites + pd;
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites + pd;
// Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(ViewPos);
R_DrawMasked();
RenderTranslucent::Render();
ds_p = firstdrawseg;
vissprite_p = firstvissprite;
VisibleSpriteList::vissprite_p = VisibleSpriteList::firstvissprite;
visplaneStack.Pop(pl);
if (pl->Alpha > 0 && pl->picnum != skyflatnum)
@ -260,8 +260,8 @@ namespace swrenderer
*freehead = pl;
freehead = &pl->next;
}
firstvissprite = vissprites;
vissprite_p = vissprites + savedvissprite_p;
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites;
VisibleSpriteList::vissprite_p = VisibleSpriteList::vissprites + savedvissprite_p;
firstdrawseg = drawsegs;
ds_p = drawsegs + savedds_p;
InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg);
@ -469,7 +469,7 @@ namespace swrenderer
NetUpdate();
MaskedCycles.Clock(); // [ZZ] count sprites in portals/mirrors along with normal ones.
R_DrawMasked(); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal.
RenderTranslucent::Render(); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal.
MaskedCycles.Unclock();
NetUpdate();

View file

@ -177,7 +177,7 @@ namespace swrenderer
return;
// store information in a vissprite
vis = R_NewVisSprite();
vis = VisibleSpriteList::Add();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->heightsec = heightsec;
vis->xscale = FLOAT2FIXED(xscale);
@ -253,7 +253,7 @@ namespace swrenderer
{
for (int x = x1; x < (x1 + countbase); x++, fracposx += fracstepx)
{
if (R_ClipSpriteColumnWithPortals(x, vis))
if (RenderTranslucent::ClipSpriteColumnWithPortals(x, vis))
continue;
uint32_t *dest = ylookup[yl] + x + (uint32_t*)dc_destorg;
DrawerCommandQueue::QueueCommand<DrawParticleColumnRGBACommand>(dest, yl, spacing, ycount, fg, alpha, fracposx);
@ -263,7 +263,7 @@ namespace swrenderer
{
for (int x = x1; x < (x1 + countbase); x++, fracposx += fracstepx)
{
if (R_ClipSpriteColumnWithPortals(x, vis))
if (RenderTranslucent::ClipSpriteColumnWithPortals(x, vis))
continue;
uint8_t *dest = ylookup[yl] + x + dc_destorg;
DrawerCommandQueue::QueueCommand<DrawParticleColumnPalCommand>(dest, yl, spacing, ycount, fg, alpha, fracposx);

View file

@ -153,7 +153,7 @@ namespace swrenderer
double yscale = spriteScale.Y / tex->Scale.Y;
// store information in a vissprite
vissprite_t *vis = R_NewVisSprite();
vissprite_t *vis = VisibleSpriteList::Add();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->xscale = FLOAT2FIXED(xscale);
@ -330,7 +330,7 @@ namespace swrenderer
{
while (x < x2)
{
if (ispsprite || !R_ClipSpriteColumnWithPortals(x, vis))
if (ispsprite || !RenderTranslucent::ClipSpriteColumnWithPortals(x, vis))
R_DrawMaskedColumn(x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false);
x++;
frac += xiscale;

View file

@ -43,24 +43,7 @@ CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE)
namespace swrenderer
{
int MaxVisSprites;
vissprite_t **vissprites;
vissprite_t **firstvissprite;
vissprite_t **vissprite_p;
vissprite_t **lastvissprite;
bool DrewAVoxel;
namespace
{
vissprite_t **spritesorter;
int spritesortersize = 0;
int vsprcount;
TArray<drawseg_t *> portaldrawsegs;
}
void R_DeinitVisSprites()
void VisibleSpriteList::Deinit()
{
// Free vissprites
for (int i = 0; i < MaxVisSprites; ++i)
@ -73,12 +56,12 @@ namespace swrenderer
MaxVisSprites = 0;
}
void R_ClearVisSprites()
void VisibleSpriteList::Clear()
{
vissprite_p = firstvissprite;
}
vissprite_t *R_NewVisSprite()
vissprite_t *VisibleSpriteList::Add()
{
if (vissprite_p == lastvissprite)
{
@ -103,27 +86,97 @@ namespace swrenderer
return *(vissprite_p - 1);
}
void R_DeinitSprites()
{
R_DeinitVisSprites();
RenderVoxel::Deinit();
int VisibleSpriteList::MaxVisSprites;
vissprite_t **VisibleSpriteList::vissprites;
vissprite_t **VisibleSpriteList::firstvissprite;
vissprite_t **VisibleSpriteList::vissprite_p;
vissprite_t **VisibleSpriteList::lastvissprite;
// Free vissprites sorter
if (spritesorter != nullptr)
{
delete[] spritesorter;
spritesortersize = 0;
spritesorter = nullptr;
}
/////////////////////////////////////////////////////////////////////////
void SortedVisibleSpriteList::Deinit()
{
delete[] spritesorter;
spritesortersize = 0;
spritesorter = nullptr;
}
void R_ClearSprites()
// This is the standard version, which does a simple test based on depth.
bool SortedVisibleSpriteList::sv_compare(vissprite_t *a, vissprite_t *b)
{
R_ClearVisSprites();
return a->idepth > b->idepth;
}
// This is an alternate version, for when one or more voxel is in view.
// It does a 2D distance test based on whichever one is furthest from
// the viewpoint.
bool SortedVisibleSpriteList::sv_compare2d(vissprite_t *a, vissprite_t *b)
{
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
}
void SortedVisibleSpriteList::Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first)
{
int i;
vissprite_t **spr;
vsprcount = int(VisibleSpriteList::vissprite_p - &VisibleSpriteList::vissprites[first]);
if (vsprcount == 0)
return;
if (spritesortersize < VisibleSpriteList::MaxVisSprites)
{
if (spritesorter != nullptr)
delete[] spritesorter;
spritesorter = new vissprite_t *[VisibleSpriteList::MaxVisSprites];
spritesortersize = VisibleSpriteList::MaxVisSprites;
}
if (!(i_compatflags & COMPATF_SPRITESORT))
{
for (i = 0, spr = VisibleSpriteList::firstvissprite; i < vsprcount; i++, spr++)
{
spritesorter[i] = *spr;
}
}
else
{
// If the compatibility option is on sprites of equal distance need to
// be sorted in inverse order. This is most easily achieved by
// filling the sort array backwards before the sort.
for (i = 0, spr = VisibleSpriteList::firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--)
{
spritesorter[i] = *spr;
}
}
std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare);
}
vissprite_t **SortedVisibleSpriteList::spritesorter;
int SortedVisibleSpriteList::spritesortersize = 0;
int SortedVisibleSpriteList::vsprcount;
/////////////////////////////////////////////////////////////////////////
bool RenderTranslucent::DrewAVoxel;
TArray<drawseg_t *> RenderTranslucent::portaldrawsegs;
void RenderTranslucent::Deinit()
{
VisibleSpriteList::Deinit();
SortedVisibleSpriteList::Deinit();
RenderVoxel::Deinit();
}
void RenderTranslucent::Clear()
{
VisibleSpriteList::Clear();
DrewAVoxel = false;
}
void R_CollectPortals()
void RenderTranslucent::CollectPortals()
{
// This function collects all drawsegs that may be of interest to R_ClipSpriteColumnWithPortals
// Having that function over the entire list of drawsegs can break down performance quite drastically.
@ -153,7 +206,7 @@ namespace swrenderer
}
}
bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr)
bool RenderTranslucent::ClipSpriteColumnWithPortals(int x, vissprite_t* spr)
{
RenderPortal *renderportal = RenderPortal::Instance();
@ -181,60 +234,7 @@ namespace swrenderer
return false;
}
// This is the standard version, which does a simple test based on depth.
bool sv_compare(vissprite_t *a, vissprite_t *b)
{
return a->idepth > b->idepth;
}
// This is an alternate version, for when one or more voxel is in view.
// It does a 2D distance test based on whichever one is furthest from
// the viewpoint.
bool sv_compare2d(vissprite_t *a, vissprite_t *b)
{
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
}
void R_SortVisSprites(bool(*compare)(vissprite_t *, vissprite_t *), size_t first)
{
int i;
vissprite_t **spr;
vsprcount = int(vissprite_p - &vissprites[first]);
if (vsprcount == 0)
return;
if (spritesortersize < MaxVisSprites)
{
if (spritesorter != nullptr)
delete[] spritesorter;
spritesorter = new vissprite_t *[MaxVisSprites];
spritesortersize = MaxVisSprites;
}
if (!(i_compatflags & COMPATF_SPRITESORT))
{
for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++)
{
spritesorter[i] = *spr;
}
}
else
{
// If the compatibility option is on sprites of equal distance need to
// be sorted in inverse order. This is most easily achieved by
// filling the sort array backwards before the sort.
for (i = 0, spr = firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--)
{
spritesorter[i] = *spr;
}
}
std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare);
}
void R_DrawSprite(vissprite_t *spr)
void RenderTranslucent::DrawSprite(vissprite_t *spr)
{
static short clipbot[MAXWIDTH];
static short cliptop[MAXWIDTH];
@ -639,15 +639,15 @@ namespace swrenderer
spr->Style.ColormapNum = colormapnum;
}
void R_DrawMaskedSingle(bool renew)
void RenderTranslucent::DrawMaskedSingle(bool renew)
{
RenderPortal *renderportal = RenderPortal::Instance();
for (int i = vsprcount; i > 0; i--)
for (int i = SortedVisibleSpriteList::vsprcount; i > 0; i--)
{
if (spritesorter[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
if (SortedVisibleSpriteList::spritesorter[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
continue; // probably another time
R_DrawSprite(spritesorter[i - 1]);
DrawSprite(SortedVisibleSpriteList::spritesorter[i - 1]);
}
// render any remaining masked mid textures
@ -676,15 +676,15 @@ namespace swrenderer
}
}
void R_DrawMasked()
void RenderTranslucent::Render()
{
R_CollectPortals();
R_SortVisSprites(DrewAVoxel ? sv_compare2d : sv_compare, firstvissprite - vissprites);
CollectPortals();
SortedVisibleSpriteList::Sort(DrewAVoxel ? SortedVisibleSpriteList::sv_compare2d : SortedVisibleSpriteList::sv_compare, VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites);
Clip3DFloors *clip3d = Clip3DFloors::Instance();
if (clip3d->height_top == nullptr)
{ // kg3D - no visible 3D floors, normal rendering
R_DrawMaskedSingle(false);
DrawMaskedSingle(false);
}
else
{ // kg3D - correct sorting
@ -701,14 +701,14 @@ namespace swrenderer
clip3d->fake3D = FAKE3D_CLIPBOTTOM;
}
clip3d->sclipBottom = hl->height;
R_DrawMaskedSingle(true);
DrawMaskedSingle(true);
R_DrawHeightPlanes(hl->height);
}
// floors
clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP;
clip3d->sclipTop = clip3d->height_top->height;
R_DrawMaskedSingle(true);
DrawMaskedSingle(true);
for (HeightLevel *hl = clip3d->height_top; hl != nullptr && hl->height < ViewPos.Z; hl = hl->next)
{
R_DrawHeightPlanes(hl->height);
@ -722,7 +722,7 @@ namespace swrenderer
clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPBOTTOM;
}
clip3d->sclipBottom = hl->height;
R_DrawMaskedSingle(true);
DrawMaskedSingle(true);
}
clip3d->DeleteHeights();
clip3d->fake3D = 0;

View file

@ -23,6 +23,8 @@ struct FVoxel;
namespace swrenderer
{
struct drawseg_t;
struct vissprite_t
{
struct posang
@ -88,25 +90,55 @@ namespace swrenderer
vissprite_t() {}
};
extern int MaxVisSprites;
extern vissprite_t **vissprites, **firstvissprite;
extern vissprite_t **vissprite_p;
class VisibleSpriteList
{
public:
static int MaxVisSprites;
static vissprite_t **vissprites;
static vissprite_t **firstvissprite;
static vissprite_t **vissprite_p;
extern bool DrewAVoxel;
static void Deinit();
static void Clear();
static vissprite_t *Add();
void R_DeinitVisSprites();
void R_ClearVisSprites();
vissprite_t *R_NewVisSprite();
private:
static vissprite_t **lastvissprite;
};
void R_DeinitSprites();
void R_ClearSprites();
void R_CollectPortals();
bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr);
void R_SortVisSprites(bool(*compare)(vissprite_t *, vissprite_t *), size_t first);
void R_DrawSprite(vissprite_t *spr);
void R_DrawMaskedSingle(bool renew);
void R_DrawMasked();
class SortedVisibleSpriteList
{
public:
static void Deinit();
bool sv_compare(vissprite_t *a, vissprite_t *b);
bool sv_compare2d(vissprite_t *a, vissprite_t *b);
static void Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first);
static bool sv_compare(vissprite_t *a, vissprite_t *b);
static bool sv_compare2d(vissprite_t *a, vissprite_t *b);
static vissprite_t **spritesorter;
static int vsprcount;
private:
static int spritesortersize;
};
class RenderTranslucent
{
public:
static void Deinit();
static void Clear();
static void Render();
static bool DrewAVoxel;
static bool ClipSpriteColumnWithPortals(int x, vissprite_t* spr);
private:
static void CollectPortals();
static void DrawSprite(vissprite_t *spr);
static void DrawMaskedSingle(bool renew);
static TArray<drawseg_t *> portaldrawsegs;
};
}

View file

@ -101,7 +101,7 @@ namespace swrenderer
}
}
vissprite_t *vis = R_NewVisSprite();
vissprite_t *vis = VisibleSpriteList::Add();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->xscale = FLOAT2FIXED(xscale);
@ -152,7 +152,7 @@ namespace swrenderer
vis->voxel = voxel->Voxel;
vis->bIsVoxel = true;
vis->bWallSprite = false;
DrewAVoxel = true;
RenderTranslucent::DrewAVoxel = true;
// The software renderer cannot invert the source without inverting the overlay
// too. That means if the source is inverted, we need to do the reverse of what

View file

@ -102,7 +102,7 @@ namespace swrenderer
gzt = pos.Z + scale.Y * scaled_to;
gzb = pos.Z + scale.Y * scaled_bo;
vis = R_NewVisSprite();
vis = VisibleSpriteList::Add();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1;
vis->x2 = wallc.sx2 >= renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2;
@ -222,7 +222,7 @@ namespace swrenderer
{ // calculate lighting
R_SetColorMapLight(usecolormap, light, shade);
}
if (!R_ClipSpriteColumnWithPortals(x, spr))
if (!RenderTranslucent::ClipSpriteColumnWithPortals(x, spr))
DrawColumn(x, WallSpriteTile, maskedScaleY, sprflipvert, mfloorclip, mceilingclip);
light += lightstep;
x++;