From 2c4ac886aa0f71fd30d3ae13a7c826299a6cea8a Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Mon, 17 Feb 2025 19:23:26 -0700 Subject: [PATCH] Stacked sector portals now render for OoB viewpoints. --- src/rendering/hwrenderer/scene/hw_portal.cpp | 27 +++++++++++++++++++- src/rendering/hwrenderer/scene/hw_portal.h | 1 + src/rendering/hwrenderer/scene/hw_sky.cpp | 7 +++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 01ab23b8a..7746aa338 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -805,10 +805,18 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c vp.Pos += origin->mDisplacement; vp.ActorPos += origin->mDisplacement; vp.ViewActor = nullptr; + vp.OffPos += origin->mDisplacement; // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - + if (lines.Size() > 0) + { + flat.plane.GetFromSector(lines[0].sub->sector, + lines[0].sub->sector->GetPortal(sector_t::ceiling)->mType & (PORTS_STACKEDSECTORTHING | PORTS_PORTAL | PORTS_LINKEDPORTAL) ? + sector_t::ceiling : sector_t::floor); + di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos), + flat.plane.plane.Normal().Z > 0 ? -1.f : 1.f); + } di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); SetupCoverage(di); ClearClipper(di, clipper); @@ -816,6 +824,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. subsector_t *sub = di->Level->PointInRenderSubsector(vp.Pos); + if (vp.IsAllowedOoB()) sub = di->Level->PointInRenderSubsector(vp.OffPos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { clipper->SafeAddClipRange(0, ANGLE_MAX); @@ -825,6 +834,22 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c } +void HWSectorStackPortal::DrawPortalStencil(FRenderState &state, int pass) +{ + bool isceiling = planesused & (1 << sector_t::ceiling); + for (unsigned int i = 0; i < lines.Size(); i++) + { + flat.section = lines[i].sub->section; + flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection + + state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); + state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + } +} + + void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { if (origin->plane != -1) screen->instack[origin->plane]--; diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index ab9fec945..50034df6a 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -270,6 +270,7 @@ struct HWSectorStackPortal : public HWScenePortalBase TArray subsectors; protected: bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void DrawPortalStencil(FRenderState &state, int pass) override; void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return origin; } virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one. diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 4610f00da..b39df6695 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -154,12 +154,15 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { - if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Almost works (with planemirrorportal stencil), but no quite + if (di->di && di->di->Viewpoint.IsAllowedOoB()) + { + secplane_t myplane = plane ? sector->ceilingplane : sector->floorplane; + if (di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; + } auto glport = sector->GetPortalGroup(plane); if (glport != NULL) { if (sector->PortalBlocksView(plane)) return; - if (di->di && screen->instack[1 - plane]) return; ptype = PORTALTYPE_SECTORSTACK; portal = glport;