From a15216c90fbcd936adc29c07159fd132dd2d31d6 Mon Sep 17 00:00:00 2001 From: Timothy Quinn Date: Fri, 5 Mar 2021 10:04:18 +0100 Subject: [PATCH] - 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. --- src/g_levellocals.h | 6 ++--- src/rendering/hwrenderer/scene/hw_bsp.cpp | 12 +++++++--- src/rendering/hwrenderer/scene/hw_walls.cpp | 26 ++++++++++++--------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index d7c3ad770..c19b55d14 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -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 diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 7006e0592..488638203 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -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; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 6a2d3ea9f..94901093b 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -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,9 +2166,18 @@ 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 { - 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 */