diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index ccf65ef26..805f6aac5 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -537,7 +537,7 @@ namespace swrenderer { if (ceilingplane) { // killough 4/11/98: add NULL ptr checks - ceilingplane = R_CheckPlane(ceilingplane, start, stop); + ceilingplane = VisiblePlaneList::Instance()->GetRange(ceilingplane, start, stop); } else { @@ -549,7 +549,7 @@ namespace swrenderer { if (floorplane) { // killough 4/11/98: add NULL ptr checks - floorplane = R_CheckPlane(floorplane, start, stop); + floorplane = VisiblePlaneList::Instance()->GetRange(floorplane, start, stop); } else { @@ -559,7 +559,8 @@ namespace swrenderer RenderWallSegmentTextures(start, stop); - if (clip3d->fake3D & FAKE3D_FAKEMASK) { + if (clip3d->fake3D & FAKE3D_FAKEMASK) + { return (clip3d->fake3D & FAKE3D_FAKEMASK) == 0; } diff --git a/src/swrenderer/plane/r_visibleplane.cpp b/src/swrenderer/plane/r_visibleplane.cpp index be530aae3..2f84e18a3 100644 --- a/src/swrenderer/plane/r_visibleplane.cpp +++ b/src/swrenderer/plane/r_visibleplane.cpp @@ -29,6 +29,7 @@ #include "g_level.h" #include "gl/dynlights/gl_dynlight.h" #include "swrenderer/r_main.h" +#include "swrenderer/r_memory.h" #include "swrenderer/scene/r_opaque_pass.h" #include "swrenderer/scene/r_3dfloors.h" #include "swrenderer/scene/r_portal.h" @@ -42,19 +43,101 @@ CVAR(Bool, tilt, false, 0); namespace swrenderer { - // [RH] Allocate one extra for sky box planes. - visplane_t *visplanes[MAXVISPLANES + 1]; - visplane_t *freetail; - visplane_t **freehead = &freetail; - - namespace + void visplane_t::AddLights(FLightNode *node) { - enum { max_plane_lights = 32 * 1024 }; - visplane_light plane_lights[max_plane_lights]; - int next_plane_light = 0; + if (!r_dynlights) + return; + + while (node) + { + if (!(node->lightsource->flags2&MF2_DORMANT)) + { + bool found = false; + visplane_light *light_node = lights; + while (light_node) + { + if (light_node->lightsource == node->lightsource) + { + found = true; + break; + } + light_node = light_node->next; + } + if (!found) + { + visplane_light *newlight = R_NewPlaneLight(); + if (!newlight) + return; + + newlight->next = lights; + newlight->lightsource = node->lightsource; + lights = newlight; + } + } + node = node->nextLight; + } } - void R_DeinitPlanes() + void visplane_t::Render(fixed_t alpha, bool additive, bool masked) + { + if (left >= right) + return; + + if (picnum == skyflatnum) // sky flat + { + RenderSkyPlane::Render(this); + } + else // regular flat + { + FTexture *tex = TexMan(picnum, true); + + if (tex->UseType == FTexture::TEX_Null) + { + return; + } + + if (!masked && !additive) + { // If we're not supposed to see through this plane, draw it opaque. + alpha = OPAQUE; + } + else if (!tex->bMasked) + { // Don't waste time on a masked texture if it isn't really masked. + masked = false; + } + R_SetSpanTexture(tex); + double xscale = xform.xScale * tex->Scale.X; + double yscale = xform.yScale * tex->Scale.Y; + + basecolormap = colormap; + + if (!height.isSlope() && !tilt) + { + RenderFlatPlane renderer; + renderer.Render(this, xscale, yscale, alpha, additive, masked); + } + else + { + RenderSlopePlane renderer; + renderer.Render(this, xscale, yscale, alpha, additive, masked); + } + } + NetUpdate(); + } + + VisiblePlaneList *VisiblePlaneList::Instance() + { + static VisiblePlaneList instance; + return &instance; + } + + VisiblePlaneList::VisiblePlaneList() + { + for (auto &plane : visplanes) + plane = nullptr; + freehead = &freetail; + } + + void VisiblePlaneList::Deinit() { // do not use R_ClearPlanes because at this point the screen pointer is no longer valid. for (int i = 0; i <= MAXVISPLANES; i++) // new code -- killough @@ -72,7 +155,7 @@ namespace swrenderer } } - visplane_t *new_visplane(unsigned hash) + visplane_t *VisiblePlaneList::Add(unsigned hash) { visplane_t *check = freetail; @@ -94,7 +177,7 @@ namespace swrenderer return check; } - void R_PlaneInitData() + void VisiblePlaneList::Init() { int i; visplane_t *pl; @@ -124,7 +207,7 @@ namespace swrenderer } } - void R_ClearPlanes(bool fullclear) + void VisiblePlaneList::Clear(bool fullclear) { int i; @@ -159,47 +242,10 @@ namespace swrenderer freehead = &(*freehead)->next; } } - - next_plane_light = 0; } } - void R_AddPlaneLights(visplane_t *plane, FLightNode *node) - { - if (!r_dynlights) - return; - - while (node) - { - if (!(node->lightsource->flags2&MF2_DORMANT)) - { - bool found = false; - visplane_light *light_node = plane->lights; - while (light_node) - { - if (light_node->lightsource == node->lightsource) - { - found = true; - break; - } - light_node = light_node->next; - } - if (!found) - { - if (next_plane_light == max_plane_lights) - return; - - visplane_light *newlight = &plane_lights[next_plane_light++]; - newlight->next = plane->lights; - newlight->lightsource = node->lightsource; - plane->lights = newlight; - } - } - node = node->nextLight; - } - } - - visplane_t *R_FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal) + visplane_t *VisiblePlaneList::FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal) { secplane_t plane; visplane_t *check; @@ -246,7 +292,7 @@ namespace swrenderer } // New visplane algorithm uses hash table -- killough - hash = isskybox ? MAXVISPLANES : visplane_hash(picnum.GetIndex(), lightlevel, height); + hash = isskybox ? MAXVISPLANES : CalcHash(picnum.GetIndex(), lightlevel, height); RenderPortal *renderportal = RenderPortal::Instance(); @@ -307,7 +353,7 @@ namespace swrenderer } } - check = new_visplane(hash); // killough + check = Add(hash); // killough check->height = plane; check->picnum = picnum; @@ -333,7 +379,7 @@ namespace swrenderer return check; } - visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) + visplane_t *VisiblePlaneList::GetRange(visplane_t *pl, int start, int stop) { int intrl, intrh; int unionl, unionh; @@ -384,9 +430,9 @@ namespace swrenderer } else { - hash = visplane_hash(pl->picnum.GetIndex(), pl->lightlevel, pl->height); + hash = CalcHash(pl->picnum.GetIndex(), pl->lightlevel, pl->height); } - visplane_t *new_pl = new_visplane(hash); + visplane_t *new_pl = Add(hash); new_pl->height = pl->height; new_pl->picnum = pl->picnum; @@ -413,7 +459,7 @@ namespace swrenderer return pl; } - int R_DrawPlanes() + int VisiblePlaneList::Render() { visplane_t *pl; int i; @@ -433,14 +479,14 @@ namespace swrenderer // kg3D - draw only real planes now if (pl->sky >= 0) { vpcount++; - R_DrawSinglePlane(pl, OPAQUE, false, false); + pl->Render(OPAQUE, false, false); } } } return vpcount; } - void R_DrawHeightPlanes(double height) + void VisiblePlaneList::RenderHeight(double height) { visplane_t *pl; int i; @@ -465,7 +511,7 @@ namespace swrenderer ViewAngle = pl->viewangle; renderportal->MirrorFlags = pl->MirrorFlags; - R_DrawSinglePlane(pl, pl->sky & 0x7FFFFFFF, pl->Additive, true); + pl->Render(pl->sky & 0x7FFFFFFF, pl->Additive, true); } } } @@ -473,52 +519,6 @@ namespace swrenderer ViewAngle = oViewAngle; } - void R_DrawSinglePlane(visplane_t *pl, fixed_t alpha, bool additive, bool masked) - { - if (pl->left >= pl->right) - return; - - if (pl->picnum == skyflatnum) // sky flat - { - RenderSkyPlane::Render(pl); - } - else // regular flat - { - FTexture *tex = TexMan(pl->picnum, true); - - if (tex->UseType == FTexture::TEX_Null) - { - return; - } - - if (!masked && !additive) - { // If we're not supposed to see through this plane, draw it opaque. - alpha = OPAQUE; - } - else if (!tex->bMasked) - { // Don't waste time on a masked texture if it isn't really masked. - masked = false; - } - R_SetSpanTexture(tex); - double xscale = pl->xform.xScale * tex->Scale.X; - double yscale = pl->xform.yScale * tex->Scale.Y; - - basecolormap = pl->colormap; - - if (!pl->height.isSlope() && !tilt) - { - RenderFlatPlane renderer; - renderer.Render(pl, xscale, yscale, alpha, additive, masked); - } - else - { - RenderSlopePlane renderer; - renderer.Render(pl, xscale, yscale, alpha, additive, masked); - } - } - NetUpdate(); - } - void PlaneRenderer::RenderLines(visplane_t *pl) { // t1/b1 are at x diff --git a/src/swrenderer/plane/r_visibleplane.h b/src/swrenderer/plane/r_visibleplane.h index 41f7d7bda..ca4da0754 100644 --- a/src/swrenderer/plane/r_visibleplane.h +++ b/src/swrenderer/plane/r_visibleplane.h @@ -64,29 +64,37 @@ namespace swrenderer unsigned short *bottom; // [RH] bottom and top arrays are dynamically unsigned short pad; // allocated immediately after the unsigned short top[]; // visplane. + + void AddLights(FLightNode *node); + void Render(fixed_t alpha, bool additive, bool masked); }; - #define MAXVISPLANES 128 /* must be a power of 2 */ - #define visplane_hash(picnum,lightlevel,height) ((unsigned)((picnum)*3+(lightlevel)+(FLOAT2FIXED((height).fD()))*7) & (MAXVISPLANES-1)) + class VisiblePlaneList + { + public: + static VisiblePlaneList *Instance(); - extern visplane_t *visplanes[MAXVISPLANES + 1]; - extern visplane_t *freetail; - extern visplane_t **freehead; + void Init(); + void Deinit(); + void Clear(bool fullclear); - void R_DeinitPlanes(); - visplane_t *new_visplane(unsigned hash); + visplane_t *FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal); + visplane_t *GetRange(visplane_t *pl, int start, int stop); - void R_PlaneInitData(); - void R_ClearPlanes(bool fullclear); + int Render(); + void RenderHeight(double height); - void R_AddPlaneLights(visplane_t *plane, FLightNode *node); + enum { MAXVISPLANES = 128 }; // must be a power of 2 + visplane_t *visplanes[MAXVISPLANES + 1]; + visplane_t *freetail = nullptr; + visplane_t **freehead = nullptr; - visplane_t *R_FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal); - visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop); + private: + VisiblePlaneList(); + visplane_t *Add(unsigned hash); - int R_DrawPlanes(); - void R_DrawHeightPlanes(double height); - void R_DrawSinglePlane(visplane_t *pl, fixed_t alpha, bool additive, bool masked); + static unsigned CalcHash(int picnum, int lightlevel, const secplane_t &height) { return (unsigned)((picnum) * 3 + (lightlevel)+(FLOAT2FIXED((height).fD())) * 7) & (MAXVISPLANES - 1); } + }; class PlaneRenderer { diff --git a/src/swrenderer/r_main.cpp b/src/swrenderer/r_main.cpp index e2f034b4c..cdbc083d5 100644 --- a/src/swrenderer/r_main.cpp +++ b/src/swrenderer/r_main.cpp @@ -386,7 +386,7 @@ void R_InitRenderer() static void R_ShutdownRenderer() { RenderTranslucentPass::Deinit(); - R_DeinitPlanes(); + VisiblePlaneList::Instance()->Deinit(); Clip3DFloors::Instance()->Cleanup(); R_DeinitOpenings(); R_FreeDrawSegs(); @@ -527,7 +527,8 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) // Clear buffers. R_ClearClipSegs (0, viewwidth); R_ClearDrawSegs (); - R_ClearPlanes (true); + VisiblePlaneList::Instance()->Clear(true); + R_FreePlaneLights(); RenderTranslucentPass::Clear(); // opening / clipping determination @@ -568,7 +569,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) if (viewactive) { PlaneCycles.Clock(); - R_DrawPlanes(); + VisiblePlaneList::Instance()->Render(); RenderPortal::Instance()->RenderPlanePortals(); PlaneCycles.Unclock(); @@ -655,7 +656,7 @@ void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas, void R_MultiresInit () { - R_PlaneInitData (); + VisiblePlaneList::Instance()->Init(); } diff --git a/src/swrenderer/r_memory.cpp b/src/swrenderer/r_memory.cpp index 0b3d3c1d4..c77cada56 100644 --- a/src/swrenderer/r_memory.cpp +++ b/src/swrenderer/r_memory.cpp @@ -20,6 +20,7 @@ #include "p_setup.h" #include "swrenderer/r_main.h" #include "swrenderer/drawers/r_draw.h" +#include "swrenderer/plane/r_visibleplane.h" #include "a_sharedglobal.h" #include "g_level.h" #include "p_effect.h" @@ -70,4 +71,25 @@ namespace swrenderer openings = nullptr; } } + + ///////////////////////////////////////////////////////////////////////// + + namespace + { + enum { max_plane_lights = 32 * 1024 }; + visplane_light plane_lights[max_plane_lights]; + int next_plane_light = 0; + } + + visplane_light *R_NewPlaneLight() + { + if (next_plane_light == max_plane_lights) + return nullptr; + return &plane_lights[next_plane_light++]; + } + + void R_FreePlaneLights() + { + next_plane_light = 0; + } } diff --git a/src/swrenderer/r_memory.h b/src/swrenderer/r_memory.h index 5df750480..7914cdfcf 100644 --- a/src/swrenderer/r_memory.h +++ b/src/swrenderer/r_memory.h @@ -15,9 +15,14 @@ namespace swrenderer { + struct visplane_light; + extern short *openings; ptrdiff_t R_NewOpening(ptrdiff_t len); void R_FreeOpenings(); void R_DeinitOpenings(); + + visplane_light *R_NewPlaneLight(); + void R_FreePlaneLights(); } diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index 337942cc4..99d79f10d 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -501,7 +501,7 @@ namespace swrenderer (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ? - R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 + VisiblePlaneList::Instance()->FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + r_actualextralight, // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), @@ -512,7 +512,7 @@ namespace swrenderer ) : nullptr; if (ceilingplane) - R_AddPlaneLights(ceilingplane, frontsector->lighthead); + ceilingplane->AddLights(frontsector->lighthead); if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size()) { @@ -541,7 +541,7 @@ namespace swrenderer (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ? - R_FindPlane(frontsector->floorplane, + VisiblePlaneList::Instance()->FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + r_actualextralight, // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), @@ -552,7 +552,7 @@ namespace swrenderer ) : nullptr; if (floorplane) - R_AddPlaneLights(floorplane, frontsector->lighthead); + floorplane->AddLights(frontsector->lighthead); // kg3D - fake planes rendering if (r_3dfloors && frontsector->e && frontsector->e->XFloor.ffloors.Size()) @@ -606,7 +606,7 @@ namespace swrenderer } ceilingplane = nullptr; - floorplane = R_FindPlane(frontsector->floorplane, + floorplane = VisiblePlaneList::Instance()->FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + r_actualextralight, // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), @@ -616,7 +616,7 @@ namespace swrenderer nullptr); if (floorplane) - R_AddPlaneLights(floorplane, frontsector->lighthead); + floorplane->AddLights(frontsector->lighthead); FakeDrawLoop(sub, floorplane, ceilingplane); clip3d->fake3D = 0; @@ -671,7 +671,7 @@ namespace swrenderer tempsec.ceilingplane.ChangeHeight(1 / 65536.); floorplane = nullptr; - ceilingplane = R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 + ceilingplane = VisiblePlaneList::Instance()->FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + r_actualextralight, // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), @@ -681,7 +681,7 @@ namespace swrenderer nullptr); if (ceilingplane) - R_AddPlaneLights(ceilingplane, frontsector->lighthead); + ceilingplane->AddLights(frontsector->lighthead); FakeDrawLoop(sub, floorplane, ceilingplane); clip3d->fake3D = 0; diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 88b9415ce..b235944d8 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -88,7 +88,9 @@ namespace swrenderer { numskyboxes = 0; - if (visplanes[MAXVISPLANES] == nullptr) + VisiblePlaneList *planes = VisiblePlaneList::Instance(); + + if (planes->visplanes[VisiblePlaneList::MAXVISPLANES] == nullptr) return; Clip3DFloors::Instance()->EnterSkybox(); @@ -107,19 +109,19 @@ namespace swrenderer int i; visplane_t *pl; - for (pl = visplanes[MAXVISPLANES]; pl != nullptr; pl = visplanes[MAXVISPLANES]) + for (pl = planes->visplanes[VisiblePlaneList::MAXVISPLANES]; pl != nullptr; pl = planes->visplanes[VisiblePlaneList::MAXVISPLANES]) { // Pop the visplane off the list now so that if this skybox adds more // skyboxes to the list, they will be drawn instead of skipped (because // new skyboxes go to the beginning of the list instead of the end). - visplanes[MAXVISPLANES] = pl->next; + planes->visplanes[VisiblePlaneList::MAXVISPLANES] = pl->next; pl->next = nullptr; if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == nullptr) { - R_DrawSinglePlane(pl, OPAQUE, false, false); - *freehead = pl; - freehead = &pl->next; + pl->Render(OPAQUE, false, false); + *planes->freehead = pl; + planes->freehead = &pl->next; continue; } @@ -158,9 +160,9 @@ namespace swrenderer // not implemented yet default: - R_DrawSinglePlane(pl, OPAQUE, false, false); - *freehead = pl; - freehead = &pl->next; + pl->Render(OPAQUE, false, false); + *planes->freehead = pl; + planes->freehead = &pl->next; numskyboxes--; continue; } @@ -173,7 +175,7 @@ namespace swrenderer R_SetViewAngle(); validcount++; // Make sure we see all sprites - R_ClearPlanes(false); + planes->Clear(false); R_ClearClipSegs(pl->left, pl->right); WindowLeft = pl->left; WindowRight = pl->right; @@ -227,7 +229,7 @@ namespace swrenderer RenderOpaquePass::Instance()->RenderScene(); Clip3DFloors::Instance()->ResetClip(); // reset clips (floor/ceiling) - R_DrawPlanes(); + planes->Render(); port->mFlags &= ~PORTSF_INSKYBOX; if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX; @@ -256,10 +258,10 @@ namespace swrenderer visplaneStack.Pop(pl); if (pl->Alpha > 0 && pl->picnum != skyflatnum) { - R_DrawSinglePlane(pl, pl->Alpha, pl->Additive, true); + pl->Render(pl->Alpha, pl->Additive, true); } - *freehead = pl; - freehead = &pl->next; + *planes->freehead = pl; + planes->freehead = &pl->next; } VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites; VisibleSpriteList::vissprite_p = VisibleSpriteList::vissprites + savedvissprite_p; @@ -281,8 +283,8 @@ namespace swrenderer if (Clip3DFloors::Instance()->fakeActive) return; - for (*freehead = visplanes[MAXVISPLANES], visplanes[MAXVISPLANES] = nullptr; *freehead; ) - freehead = &(*freehead)->next; + for (*planes->freehead = planes->visplanes[VisiblePlaneList::MAXVISPLANES], planes->visplanes[VisiblePlaneList::MAXVISPLANES] = nullptr; *planes->freehead; ) + planes->freehead = &(*planes->freehead)->next; } void RenderPortal::RenderLinePortals() @@ -421,7 +423,7 @@ namespace swrenderer PortalDrawseg* prevpds = CurrentPortal; CurrentPortal = pds; - R_ClearPlanes(false); + VisiblePlaneList::Instance()->Clear(false); R_ClearClipSegs(pds->x1, pds->x2); WindowLeft = pds->x1; @@ -451,7 +453,7 @@ namespace swrenderer if (!savedvisibility && camera) camera->renderflags &= ~RF_INVISIBLE; PlaneCycles.Clock(); - R_DrawPlanes(); + VisiblePlaneList::Instance()->Render(); RenderPlanePortals(); PlaneCycles.Unclock(); diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index 3f5d69e03..48cf627dc 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -586,7 +586,7 @@ namespace swrenderer } clip3d->sclipBottom = hl->height; DrawMaskedSingle(true); - R_DrawHeightPlanes(hl->height); + VisiblePlaneList::Instance()->RenderHeight(hl->height); } // floors @@ -595,7 +595,7 @@ namespace swrenderer DrawMaskedSingle(true); for (HeightLevel *hl = clip3d->height_top; hl != nullptr && hl->height < ViewPos.Z; hl = hl->next) { - R_DrawHeightPlanes(hl->height); + VisiblePlaneList::Instance()->RenderHeight(hl->height); if (hl->next) { clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP | FAKE3D_CLIPBOTTOM;