diff --git a/src/swrenderer/r_main.cpp b/src/swrenderer/r_main.cpp index e6a67473f..f90690d49 100644 --- a/src/swrenderer/r_main.cpp +++ b/src/swrenderer/r_main.cpp @@ -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 (); diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 5ca458b30..d22777eea 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -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(); diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index 4ad74b250..8ec92569f 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -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(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(dest, yl, spacing, ycount, fg, alpha, fracposx); diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index d5766611c..7751f859e 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -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; diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index 9f327003b..36ee18432 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -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 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 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; diff --git a/src/swrenderer/things/r_visiblesprite.h b/src/swrenderer/things/r_visiblesprite.h index 6a540d1ab..b9405dc19 100644 --- a/src/swrenderer/things/r_visiblesprite.h +++ b/src/swrenderer/things/r_visiblesprite.h @@ -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 portaldrawsegs; + }; } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index d3ae84128..2d81f2e62 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -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 diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 7158197a1..307f1bdf0 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -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++;