diff --git a/src/r_poly_plane.cpp b/src/r_poly_plane.cpp index 57db62600..0c19d9832 100644 --- a/src/r_poly_plane.cpp +++ b/src/r_poly_plane.cpp @@ -149,11 +149,24 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, subsector_t *s void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) { FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); - if (portal && sectorPortals.empty()) + PolyDrawSectorPortal *polyportal = nullptr; + if (portal) { - sectorPortals.push_back(std::make_unique(portal, ceiling)); + for (auto &p : sectorPortals) + { + if (p->Portal == portal) // To do: what other criterias do we need to check for? + { + polyportal = p.get(); + break; + } + } + if (!portal) + { + sectorPortals.push_back(std::make_unique(portal, ceiling)); + polyportal = sectorPortals.back().get(); + } } - + sector_t *fakesector = sub->sector->heightsec; if (fakesector && (fakesector == sub->sector || (fakesector->MoreFlags & SECF_IGNOREHEIGHTSEC) == SECF_IGNOREHEIGHTSEC)) fakesector = nullptr; @@ -253,6 +266,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uin { args.stencilwritevalue = 252; PolyTriangleDrawer::draw(args, TriDrawVariant::Stencil, TriBlendMode::Copy); + polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw }); } } else @@ -260,6 +274,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uin if (portal) { args.stencilwritevalue = 252; + polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw }); } else { @@ -335,6 +350,9 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uin args.vinput = wallvert; args.vcount = 4; PolyTriangleDrawer::draw(args, TriDrawVariant::Stencil, TriBlendMode::Copy); + + if (portal) + polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw }); } } } diff --git a/src/r_poly_portal.cpp b/src/r_poly_portal.cpp index aad43986b..e500e24d1 100644 --- a/src/r_poly_portal.cpp +++ b/src/r_poly_portal.cpp @@ -128,7 +128,7 @@ void RenderPolyPortal::RenderSubsector(subsector_t *sub) SpriteRange RenderPolyPortal::GetSpritesForSector(sector_t *sector) { - if (SectorSpriteRanges.size() < sector->sectornum || sector->sectornum < 0) + if ((int)SectorSpriteRanges.size() < sector->sectornum || sector->sectornum < 0) return SpriteRange(); auto &range = SectorSpriteRanges[sector->sectornum]; @@ -191,10 +191,38 @@ void RenderPolyPortal::RenderLine(subsector_t *sub, seg_t *line, sector_t *front void RenderPolyPortal::RenderTranslucent() { for (auto it = SectorPortals.rbegin(); it != SectorPortals.rend(); ++it) + { (*it)->RenderTranslucent(); + + PolyDrawArgs args; + args.objectToClip = &WorldToClip; + args.stenciltestvalue = 253; + args.stencilwritevalue = 1; + for (const auto &verts : (*it)->Shape) + { + args.vinput = verts.Vertices; + args.vcount = verts.Count; + args.ccw = verts.Ccw; + PolyTriangleDrawer::draw(args, TriDrawVariant::Stencil, TriBlendMode::Copy); + } + } for (auto it = LinePortals.rbegin(); it != LinePortals.rend(); ++it) + { (*it)->RenderTranslucent(); + + PolyDrawArgs args; + args.objectToClip = &WorldToClip; + args.stenciltestvalue = 253; + args.stencilwritevalue = 1; + for (const auto &verts : (*it)->Shape) + { + args.vinput = verts.Vertices; + args.vcount = verts.Count; + args.ccw = verts.Ccw; + PolyTriangleDrawer::draw(args, TriDrawVariant::Stencil, TriBlendMode::Copy); + } + } for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) { @@ -237,23 +265,7 @@ void PolyDrawSectorPortal::Render() return; recursion++; - int savedextralight = extralight; - DVector3 savedpos = ViewPos; - DAngle savedangle = ViewAngle; - double savedvisibility = R_GetVisibility(); - AActor *savedcamera = camera; - sector_t *savedsector = viewsector; - - // Don't let gun flashes brighten the sky box - ASkyViewpoint *sky = barrier_cast(Portal->mSkybox); - extralight = 0; - R_SetVisibility(sky->args[0] * 0.25f); - ViewPos = sky->InterpolatedPosition(r_TicFracF); - ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF); - - camera = nullptr; - viewsector = Portal->mDestination; - R_SetViewAngle(); + SaveGlobals(); // To do: get this information from RenderPolyScene instead of duplicating the code.. double radPitch = ViewPitch.Normalized180().Radians(); @@ -275,7 +287,50 @@ void PolyDrawSectorPortal::Render() RenderPortal.SetViewpoint(worldToClip, 252); RenderPortal.Render(); + + RestoreGlobals(); + + recursion--; +} +void PolyDrawSectorPortal::RenderTranslucent() +{ + if (Portal->mType != PORTS_SKYVIEWPOINT) + return; + + static int recursion = 0; + if (recursion >= 1/*r_portal_recursions*/) + return; + recursion++; + + RenderPortal.RenderTranslucent(); + + recursion--; +} + +void PolyDrawSectorPortal::SaveGlobals() +{ + int savedextralight = extralight; + DVector3 savedpos = ViewPos; + DAngle savedangle = ViewAngle; + double savedvisibility = R_GetVisibility(); + AActor *savedcamera = camera; + sector_t *savedsector = viewsector; + + // Don't let gun flashes brighten the sky box + ASkyViewpoint *sky = barrier_cast(Portal->mSkybox); + extralight = 0; + R_SetVisibility(sky->args[0] * 0.25f); + ViewPos = sky->InterpolatedPosition(r_TicFracF); + ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF); + + camera = nullptr; + viewsector = Portal->mDestination; + R_SetViewAngle(); +} + +void PolyDrawSectorPortal::RestoreGlobals() +{ camera = savedcamera; viewsector = savedsector; ViewPos = savedpos; @@ -283,16 +338,6 @@ void PolyDrawSectorPortal::Render() extralight = savedextralight; ViewAngle = savedangle; R_SetViewAngle(); - - recursion--; -} - -void PolyDrawSectorPortal::RenderTranslucent() -{ - /*if (Portal->mType != PORTS_SKYVIEWPOINT) - return; - - RenderPortal.RenderTranslucent();*/ } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/r_poly_portal.h b/src/r_poly_portal.h index 34e4666f7..6042d5938 100644 --- a/src/r_poly_portal.h +++ b/src/r_poly_portal.h @@ -110,6 +110,14 @@ private: std::vector> LinePortals; }; +struct PolyPortalVertexRange +{ + PolyPortalVertexRange(const TriVertex *vertices, int count, bool ccw) : Vertices(vertices), Count(count), Ccw(ccw) { } + const TriVertex *Vertices; + int Count; + bool Ccw; +}; + class PolyDrawSectorPortal { public: @@ -117,11 +125,23 @@ public: void Render(); void RenderTranslucent(); + + FSectorPortal *Portal; + std::vector Shape; private: - FSectorPortal *Portal; + void SaveGlobals(); + void RestoreGlobals(); + bool Ceiling; RenderPolyPortal RenderPortal; + + int savedextralight; + DVector3 savedpos; + DAngle savedangle; + double savedvisibility; + AActor *savedcamera; + sector_t *savedsector; }; class PolyDrawLinePortal @@ -132,6 +152,8 @@ public: void Render(); void RenderTranslucent(); + std::vector Shape; + private: line_t *Src; line_t *Dest; diff --git a/src/r_poly_wall.cpp b/src/r_poly_wall.cpp index a417784d3..8f3fb05d7 100644 --- a/src/r_poly_wall.cpp +++ b/src/r_poly_wall.cpp @@ -312,7 +312,7 @@ void PolyWallTextureCoords::CalcU(FTexture *tex, const seg_t *lineseg, const lin double lineLength = side->TexelLength; double lineStart = 0.0; - bool entireSegment = ((lineseg->v1 == line->v1) && (lineseg->v2 == line->v2) || (lineseg->v2 == line->v1) && (lineseg->v1 == line->v2)); + bool entireSegment = ((lineseg->v1 == line->v1) && (lineseg->v2 == line->v2)) || ((lineseg->v2 == line->v1) && (lineseg->v1 == line->v2)); if (!entireSegment) { lineLength = (lineseg->v2->fPos() - lineseg->v1->fPos()).Length();