diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 2547ee48b..8f7dfd0a7 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -321,7 +321,7 @@ namespace swrenderer I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop); #endif - DrawSegment *draw_segment = R_AddDrawSegment(); + DrawSegment *draw_segment = DrawSegmentList::Instance()->Add(); if (!rw_prepped) { @@ -519,8 +519,8 @@ namespace swrenderer if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) { - size_t drawsegnum = draw_segment - drawsegs; - InterestingDrawsegs.Push(drawsegnum); + size_t drawsegnum = draw_segment - DrawSegmentList::Instance()->drawsegs; + DrawSegmentList::Instance()->InterestingDrawsegs.Push(drawsegnum); } } } diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 74d4eb246..c6685ddae 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -93,6 +93,7 @@ namespace swrenderer numskyboxes = 0; VisiblePlaneList *planes = VisiblePlaneList::Instance(); + DrawSegmentList *drawseglist = DrawSegmentList::Instance(); if (!planes->HasPortalPlanes()) return; @@ -103,8 +104,8 @@ namespace swrenderer int savedextralight = extralight; DVector3 savedpos = ViewPos; DAngle savedangle = ViewAngle; - ptrdiff_t savedds_p = ds_p - drawsegs; - size_t savedinteresting = FirstInterestingDrawseg; + ptrdiff_t savedds_p = drawseglist->ds_p - drawseglist->drawsegs; + size_t savedinteresting = drawseglist->FirstInterestingDrawseg; double savedvisibility = R_GetVisibility(); AActor *savedcamera = camera; sector_t *savedsector = viewsector; @@ -187,7 +188,7 @@ namespace swrenderer } // Create a drawseg to clip sprites to the sky plane - DrawSegment *draw_segment = R_AddDrawSegment(); + DrawSegment *draw_segment = drawseglist->Add(); draw_segment->CurrentPortalUniq = CurrentPortalUniq; draw_segment->siz1 = INT_MAX; draw_segment->siz2 = INT_MAX; @@ -207,11 +208,11 @@ namespace swrenderer memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short)); - firstdrawseg = draw_segment; - FirstInterestingDrawseg = InterestingDrawsegs.Size(); + drawseglist->firstdrawseg = draw_segment; + drawseglist->FirstInterestingDrawseg = drawseglist->InterestingDrawsegs.Size(); - interestingStack.Push(FirstInterestingDrawseg); - ptrdiff_t diffnum = firstdrawseg - drawsegs; + interestingStack.Push(drawseglist->FirstInterestingDrawseg); + ptrdiff_t diffnum = drawseglist->firstdrawseg - drawseglist->drawsegs; drawsegStack.Push(diffnum); VisibleSpriteList::Instance()->PushPortal(); viewposStack.Push(ViewPos); @@ -228,19 +229,19 @@ namespace swrenderer // Draw all the masked textures in a second pass, in the reverse order they // were added. This must be done separately from the previous step for the // sake of nested skyboxes. - while (interestingStack.Pop(FirstInterestingDrawseg)) + while (interestingStack.Pop(drawseglist->FirstInterestingDrawseg)) { ptrdiff_t pd = 0; drawsegStack.Pop(pd); - firstdrawseg = drawsegs + pd; + drawseglist->firstdrawseg = drawseglist->drawsegs + pd; // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(ViewPos); RenderTranslucentPass::Render(); - ds_p = firstdrawseg; + drawseglist->ds_p = drawseglist->firstdrawseg; VisibleSpriteList::Instance()->PopPortal(); @@ -251,10 +252,10 @@ namespace swrenderer pl->Render(pl->Alpha, pl->Additive, true); } } - firstdrawseg = drawsegs; - ds_p = drawsegs + savedds_p; - InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg); - FirstInterestingDrawseg = savedinteresting; + drawseglist->firstdrawseg = drawseglist->drawsegs; + drawseglist->ds_p = drawseglist->drawsegs + savedds_p; + drawseglist->InterestingDrawsegs.Resize((unsigned int)drawseglist->FirstInterestingDrawseg); + drawseglist->FirstInterestingDrawseg = savedinteresting; camera = savedcamera; viewsector = savedsector; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index be23aae32..2d1e1d7bb 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -132,7 +132,7 @@ namespace swrenderer // Clear buffers. RenderClipSegment::Instance()->Clear(0, viewwidth); - R_ClearDrawSegs(); + DrawSegmentList::Instance()->Clear(); VisiblePlaneList::Instance()->Clear(); RenderTranslucentPass::Clear(); @@ -269,7 +269,7 @@ namespace swrenderer { RenderTranslucentPass::Deinit(); Clip3DFloors::Instance()->Cleanup(); - R_FreeDrawSegs(); + DrawSegmentList::Instance()->Deinit(); } ///////////////////////////////////////////////////////////////////////// diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index 8330852b0..d95fda1e0 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -68,7 +68,8 @@ namespace swrenderer // a) exit early if no relevant info is found and // b) skip most of the collected drawsegs which have no portal attached. portaldrawsegs.Clear(); - for (DrawSegment* seg = ds_p; seg-- > firstdrawseg; ) // copied code from killough below + DrawSegmentList *drawseglist = DrawSegmentList::Instance(); + for (DrawSegment* seg = drawseglist->ds_p; seg-- > drawseglist->firstdrawseg; ) { // I don't know what makes this happen (some old top-down portal code or possibly skybox code? something adds null lines...) // crashes at the first frame of the first map of Action2.wad @@ -133,17 +134,12 @@ namespace swrenderer // render any remaining masked mid textures - // Modified by Lee Killough: - // (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 - if (renew) { Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; } - for (DrawSegment *ds = ds_p; ds-- > firstdrawseg; ) // new -- killough + DrawSegmentList *drawseglist = DrawSegmentList::Instance(); + for (DrawSegment *ds = drawseglist->ds_p; ds-- > drawseglist->firstdrawseg; ) { // [ZZ] the same as above if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) @@ -152,7 +148,8 @@ namespace swrenderer if (ds->fake) continue; if (ds->maskedtexturecol != nullptr || ds->bFogBoundary) { - R_RenderMaskedSegRange(ds, ds->x1, ds->x2); + RenderDrawSegment renderer; + renderer.Render(ds, ds->x1, ds->x2); } } } diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index ff3842293..586195aa4 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -45,35 +45,13 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - DrawSegment *firstdrawseg; - DrawSegment *ds_p; - DrawSegment *drawsegs; - - size_t FirstInterestingDrawseg; - TArray InterestingDrawsegs; - - namespace + DrawSegmentList *DrawSegmentList::Instance() { - size_t MaxDrawSegs; - - sector_t *frontsector; - sector_t *backsector; - - seg_t *curline; - - FWallCoords WallC; - FWallTmapVals WallT; - - float rw_light; - float rw_lightstep; - fixed_t rw_offset; - FTexture *rw_pic; - - ProjectedWallLine wallupper; - ProjectedWallLine walllower; + static DrawSegmentList instance; + return &instance; } - void R_FreeDrawSegs() + void DrawSegmentList::Deinit() { if (drawsegs != nullptr) { @@ -82,7 +60,7 @@ namespace swrenderer } } - void R_ClearDrawSegs() + void DrawSegmentList::Clear() { if (drawsegs == nullptr) { @@ -94,7 +72,7 @@ namespace swrenderer ds_p = drawsegs; } - DrawSegment *R_AddDrawSegment() + DrawSegment *DrawSegmentList::Add() { if (ds_p == &drawsegs[MaxDrawSegs]) { // [RH] Grab some more drawsegs @@ -110,8 +88,10 @@ namespace swrenderer return ds_p++; } + ///////////////////////////////////////////////////////////////////////// + // Clip a midtexture to the floor and ceiling of the sector in front of it. - void ClipMidtex(int x1, int x2) + void RenderDrawSegment::ClipMidtex(int x1, int x2) { ProjectedWallLine most; @@ -131,7 +111,7 @@ namespace swrenderer } } - void R_GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot) + void RenderDrawSegment::GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot) { double frontcz1 = ds->curline->frontsector->ceilingplane.ZatPoint(ds->curline->v1); double frontfz1 = ds->curline->frontsector->floorplane.ZatPoint(ds->curline->v1); @@ -151,7 +131,7 @@ namespace swrenderer } } - void R_RenderMaskedSegRange(DrawSegment *ds, int x1, int x2) + void RenderDrawSegment::Render(DrawSegment *ds, int x1, int x2) { float *MaskedSWall = nullptr, MaskedScaleY = 0, rw_scalestep = 0; fixed_t *maskedtexturecol = nullptr; @@ -448,7 +428,7 @@ namespace swrenderer rw_pic = tex; double top, bot; - R_GetMaskedWallTopBottom(ds, top, bot); + GetMaskedWallTopBottom(ds, top, bot); RenderWallPart renderWallpart; renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); @@ -457,7 +437,7 @@ namespace swrenderer clearfog: if (ds->bFakeBoundary & 3) { - R_RenderFakeWallRange(ds, x1, x2, wallshade); + RenderFakeWallRange(ds, x1, x2, wallshade); } if (!notrelevant) { @@ -478,7 +458,7 @@ namespace swrenderer } // kg3D - render one fake wall - void R_RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap) + void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap) { int i; double xscale; @@ -578,14 +558,14 @@ namespace swrenderer walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT); double top, bot; - R_GetMaskedWallTopBottom(ds, top, bot); + GetMaskedWallTopBottom(ds, top, bot); RenderWallPart renderWallpart; renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); } // kg3D - walls of fake floors - void R_RenderFakeWallRange(DrawSegment *ds, int x1, int x2, int wallshade) + void RenderDrawSegment::RenderFakeWallRange(DrawSegment *ds, int x1, int x2, int wallshade) { FTexture *const DONT_DRAW = ((FTexture*)(intptr_t)-1); int i, j; @@ -800,7 +780,7 @@ namespace swrenderer } if (rw_pic != DONT_DRAW) { - R_RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); + RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); } else rw_pic = nullptr; break; @@ -975,7 +955,7 @@ namespace swrenderer if (rw_pic != DONT_DRAW) { - R_RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); + RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); } else { diff --git a/src/swrenderer/segments/r_drawsegment.h b/src/swrenderer/segments/r_drawsegment.h index 65af091cb..a56dae772 100644 --- a/src/swrenderer/segments/r_drawsegment.h +++ b/src/swrenderer/segments/r_drawsegment.h @@ -46,21 +46,53 @@ namespace swrenderer int fake; // ident fake drawseg, don't draw and clip sprites backups int CurrentPortalUniq; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping. }; - - extern DrawSegment *firstdrawseg; - extern DrawSegment *ds_p; - extern DrawSegment *drawsegs; - extern TArray InterestingDrawsegs; // drawsegs that have something drawn on them - extern size_t FirstInterestingDrawseg; - - void R_ClearDrawSegs(); - void R_FreeDrawSegs(); + class DrawSegmentList + { + public: + static DrawSegmentList *Instance(); - DrawSegment *R_AddDrawSegment(); - void ClipMidtex(int x1, int x2); - void R_RenderMaskedSegRange(DrawSegment *ds, int x1, int x2); - void R_RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap); - void R_RenderFakeWallRange(DrawSegment *ds, int x1, int x2, int wallshade); - void R_GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot); + DrawSegment *firstdrawseg = nullptr; + DrawSegment *ds_p = nullptr; + DrawSegment *drawsegs = nullptr; + + TArray InterestingDrawsegs; // drawsegs that have something drawn on them + size_t FirstInterestingDrawseg = 0; + + void Clear(); + void Deinit(); + + DrawSegment *Add(); + + private: + size_t MaxDrawSegs = 0; + }; + + class RenderDrawSegment + { + public: + void Render(DrawSegment *ds, int x1, int x2); + + private: + void ClipMidtex(int x1, int x2); + void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap); + void RenderFakeWallRange(DrawSegment *ds, int x1, int x2, int wallshade); + void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot); + + sector_t *frontsector = nullptr; + sector_t *backsector = nullptr; + + seg_t *curline = nullptr; + + FWallCoords WallC; + FWallTmapVals WallT; + + float rw_light = 0.0f; + float rw_lightstep = 0.0f; + fixed_t rw_offset = 0; + FTexture *rw_pic = nullptr; + + ProjectedWallLine wallupper; + ProjectedWallLine walllower; + }; } diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index 2867708b7..919f1c08c 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -261,9 +261,10 @@ namespace swrenderer { // Draw any masked textures behind this particle so that when the // particle is drawn, it will be in front of them. - for (unsigned int p = InterestingDrawsegs.Size(); p-- > FirstInterestingDrawseg; ) + DrawSegmentList *segmentlist = DrawSegmentList::Instance(); + for (unsigned int p = segmentlist->InterestingDrawsegs.Size(); p-- > segmentlist->FirstInterestingDrawseg; ) { - DrawSegment *ds = &drawsegs[InterestingDrawsegs[p]]; + DrawSegment *ds = &segmentlist->drawsegs[segmentlist->InterestingDrawsegs[p]]; // kg3D - no fake segs if (ds->fake) continue; if (ds->x1 >= x2 || ds->x2 <= x1) @@ -274,7 +275,10 @@ namespace swrenderer { // [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves if (ds->CurrentPortalUniq == CurrentPortalUniq) - R_RenderMaskedSegRange(ds, MAX(ds->x1, x1), MIN(ds->x2, x2)); + { + RenderDrawSegment renderer; + renderer.Render(ds, MAX(ds->x1, x1), MIN(ds->x2, x2)); + } } } } diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index f1e8faadd..ff70344f5 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -282,7 +282,8 @@ namespace swrenderer // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code - for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough + DrawSegmentList *segmentlist = DrawSegmentList::Instance(); + for (ds = segmentlist->ds_p; ds-- > segmentlist->firstdrawseg; ) // new -- killough { // [ZZ] portal handling here //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) @@ -327,7 +328,10 @@ namespace swrenderer // seg is behind sprite, so draw the mid texture if it has one if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here (ds->maskedtexturecol != nullptr || ds->bFogBoundary)) - R_RenderMaskedSegRange(ds, r1, r2); + { + RenderDrawSegment renderer; + renderer.Render(ds, r1, r2); + } continue; }