- fixed rendering of one-sided line portals in the hardware renderer

# draw upper and lower textures when the back sector does not properly match
# do not draw middle textures on portal lines
# minor optimization to 'is***Portal' functions to avoid memory access in the most common case of no portal being present.
This commit is contained in:
Timothy Quinn 2021-03-05 10:04:18 +01:00 committed by Christoph Oelckers
parent 16b0dd2fe8
commit a15216c90f
3 changed files with 27 additions and 17 deletions

View file

@ -801,19 +801,19 @@ inline FLevelLocals *line_t::GetLevel() const
} }
inline FLinePortal *line_t::getPortal() const inline FLinePortal *line_t::getPortal() const
{ {
return portalindex >= GetLevel()->linePortals.Size() ? (FLinePortal*)nullptr : &GetLevel()->linePortals[portalindex]; return portalindex == UINT_MAX && portalindex >= GetLevel()->linePortals.Size() ? (FLinePortal*)nullptr : &GetLevel()->linePortals[portalindex];
} }
// returns true if the portal is crossable by actors // returns true if the portal is crossable by actors
inline bool line_t::isLinePortal() const inline bool line_t::isLinePortal() const
{ {
return portalindex >= GetLevel()->linePortals.Size() ? false : !!(GetLevel()->linePortals[portalindex].mFlags & PORTF_PASSABLE); return portalindex == UINT_MAX && portalindex >= GetLevel()->linePortals.Size() ? false : !!(GetLevel()->linePortals[portalindex].mFlags & PORTF_PASSABLE);
} }
// returns true if the portal needs to be handled by the renderer // returns true if the portal needs to be handled by the renderer
inline bool line_t::isVisualPortal() const inline bool line_t::isVisualPortal() const
{ {
return portalindex >= GetLevel()->linePortals.Size() ? false : !!(GetLevel()->linePortals[portalindex].mFlags & PORTF_VISIBLE); return portalindex == UINT_MAX && portalindex >= GetLevel()->linePortals.Size() ? false : !!(GetLevel()->linePortals[portalindex].mFlags & PORTF_VISIBLE);
} }
inline line_t *line_t::getPortalDestination() const inline line_t *line_t::getPortalDestination() const

View file

@ -142,15 +142,21 @@ void HWDrawInfo::WorkerThread()
front = hw_FakeFlat(job->sub->sector, in_area, false); front = hw_FakeFlat(job->sub->sector, in_area, false);
auto seg = job->seg; auto seg = job->seg;
if (seg->backsector) auto backsector = seg->backsector;
if (!backsector && seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) // For one-sided portals use the portal's destination sector as backsector.
{ {
if (front->sectornum == seg->backsector->sectornum || (seg->sidedef->Flags & WALLF_POLYOBJ)) auto portal = seg->linedef->getPortal();
backsector = portal->mDestination->frontsector;
}
if (backsector)
{
if (front->sectornum == backsector->sectornum || ((seg->sidedef->Flags & WALLF_POLYOBJ) && !seg->linedef->isVisualPortal()))
{ {
back = front; back = front;
} }
else else
{ {
back = hw_FakeFlat(seg->backsector, in_area, true); back = hw_FakeFlat(backsector, in_area, true);
} }
} }
else back = nullptr; else back = nullptr;

View file

@ -2046,14 +2046,16 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
return; return;
} }
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
//return; //return;
// [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag // [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag
if (!backsector || !(seg->linedef->flags&(ML_TWOSIDED | ML_3DMIDTEX))) // one sided if (!backsector || (!(seg->linedef->flags&(ML_TWOSIDED | ML_3DMIDTEX)) && !isportal)) // one sided
{ {
// sector's sky // sector's sky
SkyNormal(di, frontsector, v1, v2); SkyNormal(di, frontsector, v1, v2);
if (seg->linedef->isVisualPortal()) if (isportal)
{ {
lineportal = seg->linedef->getPortal()->mGroup; lineportal = seg->linedef->getPortal()->mGroup;
ztop[0] = zceil[0]; ztop[0] = zceil[0];
@ -2139,7 +2141,6 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
/* mid texture */ /* mid texture */
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector; sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector;
bool drawfogboundary = !di->isFullbrightScene() && di->CheckFog(frontsector, backsec); bool drawfogboundary = !di->isFullbrightScene() && di->CheckFog(frontsector, backsec);
@ -2156,12 +2157,6 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
} }
else texture = nullptr; else texture = nullptr;
if (texture || drawfogboundary)
{
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
}
if (isportal) if (isportal)
{ {
lineportal = seg->linedef->getPortal()->mGroup; lineportal = seg->linedef->getPortal()->mGroup;
@ -2171,9 +2166,18 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
zbottom[1] = bfh2; zbottom[1] = bfh2;
PutPortal(di, PORTALTYPE_LINETOLINE, -1); PutPortal(di, PORTALTYPE_LINETOLINE, -1);
} }
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size()) else
{ {
DoFFloorBlocks(di, seg, frontsector, backsector, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2); if (texture || drawfogboundary)
{
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
}
if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
{
DoFFloorBlocks(di, seg, frontsector, backsector, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
}
} }
/* bottom texture */ /* bottom texture */