From 54a120d61247c699405b22c6a55ae606735e1041 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 23 Jul 2016 10:23:34 +0200 Subject: [PATCH] - do not process subsectors if rendering a stacked sector portal and the clipper is set to 'blocked', i.e. no visible parts are present. This solves the most severe occurences of sprites being drawn in front of a portal's contents. It is not a full fix, though, there's still some extreme cases where portals may glitch if some stuff gets between the camera and the actual portal area. Normally this has to perform a full check of the subsector against the portal's camera-facing linedefs but that's too costly for those rare cases where it may be an issue. --- src/gl/scene/gl_bsp.cpp | 2 ++ src/gl/scene/gl_clipper.cpp | 1 + src/gl/scene/gl_clipper.h | 12 ++++++++++++ src/gl/scene/gl_portal.cpp | 1 + 4 files changed, 16 insertions(+) diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index b9915dd72..5f95902a3 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -79,6 +79,7 @@ static void UnclipSubsector(subsector_t *sub) if (startAngle-endAngle >= ANGLE_180) { clipper.SafeRemoveClipRange(startAngle, endAngle); + clipper.SetBlocked(false); } seg++; } @@ -444,6 +445,7 @@ static void DoSubsector(subsector_t * sub) // range this subsector spans before going on. UnclipSubsector(sub); } + if (clipper.IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet. fakesector=gl_FakeFlat(sector, &fake, false); diff --git a/src/gl/scene/gl_clipper.cpp b/src/gl/scene/gl_clipper.cpp index a523b27fd..cd076d58a 100644 --- a/src/gl/scene/gl_clipper.cpp +++ b/src/gl/scene/gl_clipper.cpp @@ -92,6 +92,7 @@ void Clipper::Clear() ClipNode *node = cliphead; ClipNode *temp; + blocked = false; while (node != NULL) { temp = node; diff --git a/src/gl/scene/gl_clipper.h b/src/gl/scene/gl_clipper.h index d09a82147..8da75080e 100644 --- a/src/gl/scene/gl_clipper.h +++ b/src/gl/scene/gl_clipper.h @@ -54,6 +54,7 @@ class Clipper ClipNode * clipnodes; ClipNode * cliphead; ClipNode * silhouette; // will be preserved even when RemoveClipRange is called + bool blocked; static angle_t AngleToPseudo(angle_t ang); bool IsRangeVisible(angle_t startangle, angle_t endangle); @@ -68,6 +69,7 @@ public: Clipper() { + blocked = false; clipnodes=cliphead=NULL; } @@ -129,6 +131,16 @@ public: SafeRemoveClipRange(AngleToPseudo(startangle), AngleToPseudo(endangle)); } + void SetBlocked(bool on) + { + blocked = on; + } + + bool IsBlocked() const + { + return blocked; + } + bool CheckBox(const float *bspcoord); }; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index b95e1fee0..2cca5c1f0 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -763,6 +763,7 @@ void GLSectorStackPortal::DrawContents() if (!(gl_drawinfo->ss_renderflags[sub - ::subsectors] & SSRF_SEEN)) { clipper.SafeAddClipRange(0, ANGLE_MAX); + clipper.SetBlocked(true); } GLRenderer->DrawScene(DM_PORTAL);