Create class for draw segment list

This commit is contained in:
Magnus Norddahl 2017-01-26 08:01:44 +01:00
parent 2821c15795
commit 6899b351a2
8 changed files with 104 additions and 86 deletions

View file

@ -321,7 +321,7 @@ namespace swrenderer
I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop); I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop);
#endif #endif
DrawSegment *draw_segment = R_AddDrawSegment(); DrawSegment *draw_segment = DrawSegmentList::Instance()->Add();
if (!rw_prepped) if (!rw_prepped)
{ {
@ -519,8 +519,8 @@ namespace swrenderer
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
{ {
size_t drawsegnum = draw_segment - drawsegs; size_t drawsegnum = draw_segment - DrawSegmentList::Instance()->drawsegs;
InterestingDrawsegs.Push(drawsegnum); DrawSegmentList::Instance()->InterestingDrawsegs.Push(drawsegnum);
} }
} }
} }

View file

@ -93,6 +93,7 @@ namespace swrenderer
numskyboxes = 0; numskyboxes = 0;
VisiblePlaneList *planes = VisiblePlaneList::Instance(); VisiblePlaneList *planes = VisiblePlaneList::Instance();
DrawSegmentList *drawseglist = DrawSegmentList::Instance();
if (!planes->HasPortalPlanes()) if (!planes->HasPortalPlanes())
return; return;
@ -103,8 +104,8 @@ namespace swrenderer
int savedextralight = extralight; int savedextralight = extralight;
DVector3 savedpos = ViewPos; DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle; DAngle savedangle = ViewAngle;
ptrdiff_t savedds_p = ds_p - drawsegs; ptrdiff_t savedds_p = drawseglist->ds_p - drawseglist->drawsegs;
size_t savedinteresting = FirstInterestingDrawseg; size_t savedinteresting = drawseglist->FirstInterestingDrawseg;
double savedvisibility = R_GetVisibility(); double savedvisibility = R_GetVisibility();
AActor *savedcamera = camera; AActor *savedcamera = camera;
sector_t *savedsector = viewsector; sector_t *savedsector = viewsector;
@ -187,7 +188,7 @@ namespace swrenderer
} }
// Create a drawseg to clip sprites to the sky plane // 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->CurrentPortalUniq = CurrentPortalUniq;
draw_segment->siz1 = INT_MAX; draw_segment->siz1 = INT_MAX;
draw_segment->siz2 = 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->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
firstdrawseg = draw_segment; drawseglist->firstdrawseg = draw_segment;
FirstInterestingDrawseg = InterestingDrawsegs.Size(); drawseglist->FirstInterestingDrawseg = drawseglist->InterestingDrawsegs.Size();
interestingStack.Push(FirstInterestingDrawseg); interestingStack.Push(drawseglist->FirstInterestingDrawseg);
ptrdiff_t diffnum = firstdrawseg - drawsegs; ptrdiff_t diffnum = drawseglist->firstdrawseg - drawseglist->drawsegs;
drawsegStack.Push(diffnum); drawsegStack.Push(diffnum);
VisibleSpriteList::Instance()->PushPortal(); VisibleSpriteList::Instance()->PushPortal();
viewposStack.Push(ViewPos); viewposStack.Push(ViewPos);
@ -228,19 +229,19 @@ namespace swrenderer
// Draw all the masked textures in a second pass, in the reverse order they // 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 // were added. This must be done separately from the previous step for the
// sake of nested skyboxes. // sake of nested skyboxes.
while (interestingStack.Pop(FirstInterestingDrawseg)) while (interestingStack.Pop(drawseglist->FirstInterestingDrawseg))
{ {
ptrdiff_t pd = 0; ptrdiff_t pd = 0;
drawsegStack.Pop(pd); drawsegStack.Pop(pd);
firstdrawseg = drawsegs + pd; drawseglist->firstdrawseg = drawseglist->drawsegs + pd;
// Masked textures and planes need the view coordinates restored for proper positioning. // Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(ViewPos); viewposStack.Pop(ViewPos);
RenderTranslucentPass::Render(); RenderTranslucentPass::Render();
ds_p = firstdrawseg; drawseglist->ds_p = drawseglist->firstdrawseg;
VisibleSpriteList::Instance()->PopPortal(); VisibleSpriteList::Instance()->PopPortal();
@ -251,10 +252,10 @@ namespace swrenderer
pl->Render(pl->Alpha, pl->Additive, true); pl->Render(pl->Alpha, pl->Additive, true);
} }
} }
firstdrawseg = drawsegs; drawseglist->firstdrawseg = drawseglist->drawsegs;
ds_p = drawsegs + savedds_p; drawseglist->ds_p = drawseglist->drawsegs + savedds_p;
InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg); drawseglist->InterestingDrawsegs.Resize((unsigned int)drawseglist->FirstInterestingDrawseg);
FirstInterestingDrawseg = savedinteresting; drawseglist->FirstInterestingDrawseg = savedinteresting;
camera = savedcamera; camera = savedcamera;
viewsector = savedsector; viewsector = savedsector;

View file

@ -132,7 +132,7 @@ namespace swrenderer
// Clear buffers. // Clear buffers.
RenderClipSegment::Instance()->Clear(0, viewwidth); RenderClipSegment::Instance()->Clear(0, viewwidth);
R_ClearDrawSegs(); DrawSegmentList::Instance()->Clear();
VisiblePlaneList::Instance()->Clear(); VisiblePlaneList::Instance()->Clear();
RenderTranslucentPass::Clear(); RenderTranslucentPass::Clear();
@ -269,7 +269,7 @@ namespace swrenderer
{ {
RenderTranslucentPass::Deinit(); RenderTranslucentPass::Deinit();
Clip3DFloors::Instance()->Cleanup(); Clip3DFloors::Instance()->Cleanup();
R_FreeDrawSegs(); DrawSegmentList::Instance()->Deinit();
} }
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////

View file

@ -68,7 +68,8 @@ namespace swrenderer
// a) exit early if no relevant info is found and // a) exit early if no relevant info is found and
// b) skip most of the collected drawsegs which have no portal attached. // b) skip most of the collected drawsegs which have no portal attached.
portaldrawsegs.Clear(); 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...) // 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 // crashes at the first frame of the first map of Action2.wad
@ -133,17 +134,12 @@ namespace swrenderer
// render any remaining masked mid textures // 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) if (renew)
{ {
Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; 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 // [ZZ] the same as above
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
@ -152,7 +148,8 @@ namespace swrenderer
if (ds->fake) continue; if (ds->fake) continue;
if (ds->maskedtexturecol != nullptr || ds->bFogBoundary) if (ds->maskedtexturecol != nullptr || ds->bFogBoundary)
{ {
R_RenderMaskedSegRange(ds, ds->x1, ds->x2); RenderDrawSegment renderer;
renderer.Render(ds, ds->x1, ds->x2);
} }
} }
} }

View file

@ -45,35 +45,13 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
namespace swrenderer namespace swrenderer
{ {
DrawSegment *firstdrawseg; DrawSegmentList *DrawSegmentList::Instance()
DrawSegment *ds_p;
DrawSegment *drawsegs;
size_t FirstInterestingDrawseg;
TArray<size_t> InterestingDrawsegs;
namespace
{ {
size_t MaxDrawSegs; static DrawSegmentList instance;
return &instance;
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;
} }
void R_FreeDrawSegs() void DrawSegmentList::Deinit()
{ {
if (drawsegs != nullptr) if (drawsegs != nullptr)
{ {
@ -82,7 +60,7 @@ namespace swrenderer
} }
} }
void R_ClearDrawSegs() void DrawSegmentList::Clear()
{ {
if (drawsegs == nullptr) if (drawsegs == nullptr)
{ {
@ -94,7 +72,7 @@ namespace swrenderer
ds_p = drawsegs; ds_p = drawsegs;
} }
DrawSegment *R_AddDrawSegment() DrawSegment *DrawSegmentList::Add()
{ {
if (ds_p == &drawsegs[MaxDrawSegs]) if (ds_p == &drawsegs[MaxDrawSegs])
{ // [RH] Grab some more drawsegs { // [RH] Grab some more drawsegs
@ -110,8 +88,10 @@ namespace swrenderer
return ds_p++; return ds_p++;
} }
/////////////////////////////////////////////////////////////////////////
// Clip a midtexture to the floor and ceiling of the sector in front of it. // 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; 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 frontcz1 = ds->curline->frontsector->ceilingplane.ZatPoint(ds->curline->v1);
double frontfz1 = ds->curline->frontsector->floorplane.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; float *MaskedSWall = nullptr, MaskedScaleY = 0, rw_scalestep = 0;
fixed_t *maskedtexturecol = nullptr; fixed_t *maskedtexturecol = nullptr;
@ -448,7 +428,7 @@ namespace swrenderer
rw_pic = tex; rw_pic = tex;
double top, bot; double top, bot;
R_GetMaskedWallTopBottom(ds, top, bot); GetMaskedWallTopBottom(ds, top, bot);
RenderWallPart renderWallpart; 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); 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: clearfog:
if (ds->bFakeBoundary & 3) if (ds->bFakeBoundary & 3)
{ {
R_RenderFakeWallRange(ds, x1, x2, wallshade); RenderFakeWallRange(ds, x1, x2, wallshade);
} }
if (!notrelevant) if (!notrelevant)
{ {
@ -478,7 +458,7 @@ namespace swrenderer
} }
// kg3D - render one fake wall // 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; int i;
double xscale; double xscale;
@ -578,14 +558,14 @@ namespace swrenderer
walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT); walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT);
double top, bot; double top, bot;
R_GetMaskedWallTopBottom(ds, top, bot); GetMaskedWallTopBottom(ds, top, bot);
RenderWallPart renderWallpart; 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); 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 // 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); FTexture *const DONT_DRAW = ((FTexture*)(intptr_t)-1);
int i, j; int i, j;
@ -800,7 +780,7 @@ namespace swrenderer
} }
if (rw_pic != DONT_DRAW) 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; else rw_pic = nullptr;
break; break;
@ -975,7 +955,7 @@ namespace swrenderer
if (rw_pic != DONT_DRAW) 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 else
{ {

View file

@ -46,21 +46,53 @@ namespace swrenderer
int fake; // ident fake drawseg, don't draw and clip sprites backups 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. 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<size_t> InterestingDrawsegs; // drawsegs that have something drawn on them class DrawSegmentList
extern size_t FirstInterestingDrawseg; {
public:
void R_ClearDrawSegs(); static DrawSegmentList *Instance();
void R_FreeDrawSegs();
DrawSegment *R_AddDrawSegment(); DrawSegment *firstdrawseg = nullptr;
void ClipMidtex(int x1, int x2); DrawSegment *ds_p = nullptr;
void R_RenderMaskedSegRange(DrawSegment *ds, int x1, int x2); DrawSegment *drawsegs = nullptr;
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); TArray<size_t> InterestingDrawsegs; // drawsegs that have something drawn on them
void R_GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot); 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;
};
} }

View file

@ -261,9 +261,10 @@ namespace swrenderer
{ {
// Draw any masked textures behind this particle so that when the // Draw any masked textures behind this particle so that when the
// particle is drawn, it will be in front of them. // 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 // kg3D - no fake segs
if (ds->fake) continue; if (ds->fake) continue;
if (ds->x1 >= x2 || ds->x2 <= x1) 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 // [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves
if (ds->CurrentPortalUniq == CurrentPortalUniq) if (ds->CurrentPortalUniq == CurrentPortalUniq)
R_RenderMaskedSegRange(ds, MAX<int>(ds->x1, x1), MIN<int>(ds->x2, x2)); {
RenderDrawSegment renderer;
renderer.Render(ds, MAX<int>(ds->x1, x1), MIN<int>(ds->x2, x2));
}
} }
} }
} }

View file

@ -282,7 +282,8 @@ namespace swrenderer
// for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code // 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 // [ZZ] portal handling here
//if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq)
@ -327,7 +328,10 @@ namespace swrenderer
// seg is behind sprite, so draw the mid texture if it has one // 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 if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here
(ds->maskedtexturecol != nullptr || ds->bFogBoundary)) (ds->maskedtexturecol != nullptr || ds->bFogBoundary))
R_RenderMaskedSegRange(ds, r1, r2); {
RenderDrawSegment renderer;
renderer.Render(ds, r1, r2);
}
continue; continue;
} }