diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 2fe2223f8f..4dabec3e2d 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -126,13 +126,42 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di HWPortal * best = nullptr; unsigned bestindex = 0; - if (recursion > 0 || outer_di->Portals.Size() != 1 || !outer_di->Portals[0]->IsSky()) return false; + // Find the one with the highest amount of lines. + // Normally this is also the one that saves the largest amount + // of time by drawing it before the scene itself. + auto &portals = outer_di->Portals; + for (int i = portals.Size() - 1; i >= 0; --i) + { + auto p = portals[i]; + if (p->lines.Size() > 0 && p->IsSky()) + { + // Cannot clear the depth buffer inside a portal recursion + if (recursion && p->NeedDepthBuffer()) continue; - best = outer_di->Portals[0]; - outer_di->Portals.Clear(); - RenderPortal(best, state, false, outer_di); - delete best; - return true; + if (!best || p->lines.Size() > best->lines.Size()) + { + best = p; + bestindex = i; + } + + // If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area. + if (p->boundingBox.contains(outer_di->Viewpoint.Pos)) + { + best = p; + bestindex = i; + break; + } + } + } + + if (best) + { + portals.Delete(bestindex); + RenderPortal(best, state, false, outer_di); + delete best; + return true; + } + return false; } diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index a43eb76e89..a08ddceb35 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -279,7 +279,7 @@ protected: bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return origin; } - virtual bool IsSky() { return false; } + virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one. virtual const char *GetName(); FSectorPortalGroup *origin;