- 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
{
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
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
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

View file

@ -142,15 +142,21 @@ void HWDrawInfo::WorkerThread()
front = hw_FakeFlat(job->sub->sector, in_area, false);
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;
}
else
{
back = hw_FakeFlat(seg->backsector, in_area, true);
back = hw_FakeFlat(backsector, in_area, true);
}
}
else back = nullptr;

View file

@ -2046,14 +2046,16 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
return;
}
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
//return;
// [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
SkyNormal(di, frontsector, v1, v2);
if (seg->linedef->isVisualPortal())
if (isportal)
{
lineportal = seg->linedef->getPortal()->mGroup;
ztop[0] = zceil[0];
@ -2139,7 +2141,6 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
/* mid texture */
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector;
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;
if (texture || drawfogboundary)
{
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
}
if (isportal)
{
lineportal = seg->linedef->getPortal()->mGroup;
@ -2171,10 +2166,19 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
zbottom[1] = bfh2;
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
}
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
else
{
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 */
// the back sector's ceiling obstructs part of this wall (specially important for sky sectors)