Stacked sector portals now render for OoB viewpoints.

This commit is contained in:
Dileep V. Reddy 2025-02-17 19:23:26 -07:00 committed by Rachael Alexanderson
parent dc5a250797
commit 2c4ac886aa
3 changed files with 32 additions and 3 deletions

View file

@ -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]--;

View file

@ -270,6 +270,7 @@ struct HWSectorStackPortal : public HWScenePortalBase
TArray<subsector_t *> 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.

View file

@ -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;