diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 1aa3eac57..f143c6795 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -484,10 +484,11 @@ void FDrawInfo::FloodLowerGap(seg_t * seg) // Same here for the dependency on the portal. void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub) { - auto portal = GLRenderer->mPortalState.FindPortal(ptg); + auto portal = FindPortal(ptg); if (!portal) { portal = new GLScenePortal(&GLRenderer->mPortalState, new HWSectorStackPortal(ptg)); + Portals.Push(portal); } auto ptl = static_cast(static_cast(portal)->mScene); ptl->AddSubsector(sub); diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index a4bb2b16b..2aa853d12 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -149,11 +149,11 @@ bool GLPortal::Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDraw else if (gl_noquery) doquery = false; // Use occlusion query to avoid rendering portals that aren't visible - glBeginQuery(GL_SAMPLES_PASSED, GLRenderer->PortalQueryObject); + if (doquery) glBeginQuery(GL_SAMPLES_PASSED, GLRenderer->PortalQueryObject); DrawPortalStencil(); - glEndQuery(GL_SAMPLES_PASSED); + if (doquery) glEndQuery(GL_SAMPLES_PASSED); // Clear Z-buffer glStencilFunc(GL_EQUAL, mState->recursion + 1, ~0); // draw sky into stencil @@ -170,9 +170,9 @@ bool GLPortal::Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDraw gl_RenderState.SetEffect(EFF_NONE); glDepthRange(0, 1); - GLuint sampleCount; + GLuint sampleCount = 1; - glGetQueryObjectuiv(GLRenderer->PortalQueryObject, GL_QUERY_RESULT, &sampleCount); + if (doquery) glGetQueryObjectuiv(GLRenderer->PortalQueryObject, GL_QUERY_RESULT, &sampleCount); if (sampleCount == 0) // not visible { diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 890eb7909..4282f3d0b 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -62,7 +62,6 @@ protected: bool Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi) override; void End(HWDrawInfo *di, bool usestencil) override; - void ClearClipper(HWDrawInfo *di); void ClearScreen(HWDrawInfo *di); }; @@ -88,6 +87,7 @@ public: static_cast(di)->DrawScene(DM_PORTAL); mScene->Shutdown(di); } + else ClearScreen(di); } virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); } }; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index cf48f1348..61f51a1d5 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -347,27 +347,36 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) // Instead they are added to the portal manager case PORTALTYPE_HORIZON: wall->horizon = pstate.UniqueHorizons.Get(wall->horizon); - portal = pstate.FindPortal(wall->horizon); - if (!portal) portal = new GLHorizonPortal(&pstate, wall->horizon, Viewpoint); + portal = FindPortal(wall->horizon); + if (!portal) + { + portal = new GLHorizonPortal(&pstate, wall->horizon, Viewpoint); + Portals.Push(portal); + } portal->AddLine(wall); break; case PORTALTYPE_SKYBOX: - portal = pstate.FindPortal(wall->secportal); + portal = FindPortal(wall->secportal); if (!portal) { // either a regular skybox or an Eternity-style horizon if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(&pstate, wall->secportal); - else portal = new GLScenePortal(&pstate, new HWSkyboxPortal(wall->secportal)); + else + { + portal = new GLScenePortal(&pstate, new HWSkyboxPortal(wall->secportal)); + Portals.Push(portal); + } } portal->AddLine(wall); break; case PORTALTYPE_SECTORSTACK: - portal = pstate.FindPortal(wall->portal); + portal = FindPortal(wall->portal); if (!portal) { portal = new GLScenePortal(&pstate, new HWSectorStackPortal(wall->portal)); + Portals.Push(portal); } portal->AddLine(wall); break; @@ -377,15 +386,23 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) { //@sync-portal wall->planemirror = pstate.UniquePlaneMirrors.Get(wall->planemirror); - portal = pstate.FindPortal(wall->planemirror); - if (!portal) portal = new GLScenePortal(&pstate, new HWPlaneMirrorPortal(wall->planemirror)); + portal = FindPortal(wall->planemirror); + if (!portal) + { + portal = new GLScenePortal(&pstate, new HWPlaneMirrorPortal(wall->planemirror)); + Portals.Push(portal); + } portal->AddLine(wall); } break; case PORTALTYPE_MIRROR: - portal = pstate.FindPortal(wall->seg->linedef); - if (!portal) portal = new GLScenePortal(&pstate, new HWMirrorPortal(wall->seg->linedef)); + portal = FindPortal(wall->seg->linedef); + if (!portal) + { + portal = new GLScenePortal(&pstate, new HWMirrorPortal(wall->seg->linedef)); + Portals.Push(portal); + } portal->AddLine(wall); if (gl_mirror_envmap) { @@ -395,23 +412,28 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) break; case PORTALTYPE_LINETOLINE: - portal = pstate.FindPortal(wall->lineportal); + portal = FindPortal(wall->lineportal); if (!portal) { line_t *otherside = wall->lineportal->lines[0]->mDestination; - if (otherside != NULL && otherside->portalindex < level.linePortals.Size()) + if (otherside != nullptr && otherside->portalindex < level.linePortals.Size()) { ProcessActorsInPortal(otherside->getPortal()->mGroup, in_area); } portal = new GLScenePortal(&pstate, new HWLineToLinePortal(wall->lineportal)); + Portals.Push(portal); } portal->AddLine(wall); break; case PORTALTYPE_SKY: wall->sky = pstate.UniqueSkies.Get(wall->sky); - portal = pstate.FindPortal(wall->sky); - if (!portal) portal = new GLSkyPortal(&pstate, wall->sky); + portal = FindPortal(wall->sky); + if (!portal) + { + portal = new GLSkyPortal(&pstate, wall->sky); + Portals.Push(portal); + } portal->AddLine(wall); break; } diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index 697715f61..b5dce2247 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -32,6 +32,7 @@ #include "g_levellocals.h" #include "hw_fakeflat.h" #include "hw_drawinfo.h" +#include "hw_portal.h" #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_cvars.h" @@ -256,6 +257,20 @@ void HWDrawInfo::SetupView(float vx, float vy, float vz, bool mirror, bool plane // //----------------------------------------------------------------------------- +IPortal * HWDrawInfo::FindPortal(const void * src) +{ + int i = Portals.Size() - 1; + + while (i >= 0 && Portals[i] && Portals[i]->GetSource() != src) i--; + return i >= 0 ? Portals[i] : nullptr; +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + void HWViewpointUniforms::SetDefaults() { mProjectionMatrix.loadIdentity(); @@ -267,4 +282,3 @@ void HWViewpointUniforms::SetDefaults() mClipLine.X = -10000000.0f; } - diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 4c8a303c5..7f403e54d 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -110,6 +110,7 @@ struct HWDrawInfo Clipper *mClipper; FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state + TArray Portals; TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -149,6 +150,7 @@ private: sector_t fakesec; // this is a struct member because it gets used in recursively called functions so it cannot be put on the stack. + void UnclipSubsector(subsector_t *sub); void AddLine(seg_t *seg, bool portalclip); void PolySubsector(subsector_t * sub); @@ -183,6 +185,7 @@ public: return (screen->hwcaps & RFL_NO_CLIP_PLANES) && VPUniforms.mClipLine.X > -1000000.f; } + IPortal * FindPortal(const void * src); void RenderBSPNode(void *node); void ClearBuffers(); diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 248a9c94c..84cca96d7 100644 --- a/src/hwrenderer/scene/hw_portal.cpp +++ b/src/hwrenderer/scene/hw_portal.cpp @@ -35,14 +35,6 @@ EXTERN_CVAR(Int, r_mirror_recursions) -IPortal * FPortalSceneState::FindPortal(const void * src) -{ - int i = portals.Size() - 1; - - while (i >= 0 && portals[i] && portals[i]->GetSource() != src) i--; - return i >= 0 ? portals[i] : nullptr; -} - //----------------------------------------------------------------------------- // // StartFrame @@ -51,8 +43,6 @@ IPortal * FPortalSceneState::FindPortal(const void * src) void FPortalSceneState::StartFrame() { - IPortal * p = nullptr; - portals.Push(p); if (renderdepth == 0) { inskybox = false; @@ -82,22 +72,22 @@ static FString indent; // //----------------------------------------------------------------------------- -void FPortalSceneState::EndFrame(HWDrawInfo *outer_di) +void FPortalSceneState::EndFrame(HWDrawInfo *di) { IPortal * p; if (gl_portalinfo) { - Printf("%s%d portals, depth = %d\n%s{\n", indent.GetChars(), portals.Size(), renderdepth, indent.GetChars()); + Printf("%s%d portals, depth = %d\n%s{\n", indent.GetChars(), di->Portals.Size(), renderdepth, indent.GetChars()); indent += " "; } // Only use occlusion query if there are more than 2 portals. // Otherwise there's too much overhead. // (And don't forget to consider the separating null pointers!) - bool usequery = portals.Size() > 2 + (unsigned)renderdepth; + bool usequery = di->Portals.Size() > 2 + (unsigned)renderdepth; - while (portals.Pop(p) && p) + while (di->Portals.Pop(p) && p) { if (gl_portalinfo) { @@ -105,7 +95,7 @@ void FPortalSceneState::EndFrame(HWDrawInfo *outer_di) } if (p->lines.Size() > 0) { - p->RenderPortal(true, usequery, outer_di); + p->RenderPortal(true, usequery, di); } delete p; } @@ -115,7 +105,7 @@ void FPortalSceneState::EndFrame(HWDrawInfo *outer_di) { indent.Truncate(long(indent.Len()-2)); Printf("%s}\n", indent.GetChars()); - if (portals.Size() == 0) gl_portalinfo = false; + if (indent.Len() == 0) gl_portalinfo = false; } } @@ -131,23 +121,24 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di { IPortal * p; IPortal * best = nullptr; - unsigned bestindex=0; + unsigned bestindex = 0; // 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. - for(int i = portals.Size()-1; i >= 0 && portals[i] != nullptr; --i) + auto &portals = outer_di->Portals; + for (int i = portals.Size() - 1; i >= 0; --i) { - p=portals[i]; + p = portals[i]; if (p->lines.Size() > 0 && p->IsSky()) { // Cannot clear the depth buffer inside a portal recursion if (recursion && p->NeedDepthBuffer()) continue; - if (!best || p->lines.Size()>best->lines.Size()) + if (!best || p->lines.Size() > best->lines.Size()) { - best=p; - bestindex=i; + best = p; + bestindex = i; } } } @@ -168,16 +159,16 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di // //----------------------------------------------------------------------------- -void HWScenePortalBase::ClearClipper(HWDrawInfo *di) +void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) { auto outer_di = di->outer; DAngle angleOffset = deltaangle(outer_di->Viewpoint.Angles.Yaw, di->Viewpoint.Angles.Yaw); - di->mClipper->Clear(); + clipper->Clear(); auto &lines = mOwner->lines; // Set the clipper to the minimal visible area - di->mClipper->SafeAddClipRange(0, 0xffffffff); + clipper->SafeAddClipRange(0, 0xffffffff); for (unsigned int i = 0; i < lines.Size(); i++) { DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset; @@ -185,16 +176,16 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di) if (deltaangle(endAngle, startAngle) < 0) { - di->mClipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); + clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); } } // and finally clip it to the visible area angle_t a1 = di->FrustumAngle(); - if (a1 < ANGLE_180) di->mClipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); + if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); // lock the parts that have just been clipped out. - di->mClipper->SetSilhouette(); + clipper->SetSilhouette(); } @@ -406,7 +397,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper) di->SetClipLine(glport->lines[0]->mDestination); di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); - ClearClipper(di); + ClearClipper(di, clipper); return true; } @@ -469,7 +460,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper) di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetViewArea(); - ClearClipper(di); + ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; } @@ -559,15 +550,15 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper) di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); SetupCoverage(di); - ClearClipper(di); + ClearClipper(di, clipper); // 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 = R_PointInSubsector(vp.Pos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { - di->mClipper->SafeAddClipRange(0, ANGLE_MAX); - di->mClipper->SetBlocked(true); + clipper->SafeAddClipRange(0, ANGLE_MAX); + clipper->SetBlocked(true); } return true; } @@ -607,7 +598,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); auto &vp = di->Viewpoint; - int old_pm = state->PlaneMirrorMode; + old_pm = state->PlaneMirrorMode; // the player is always visible in a mirror. vp.showviewer = true; @@ -620,7 +611,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) state->PlaneMirrorFlag++; di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f); di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); - ClearClipper(di); + ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; @@ -634,4 +625,4 @@ void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di) std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); } -const char *HWPlaneMirrorPortal::GetName() { return "Planemirror"; } +const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirror ceiling" : "Planemirror floor"; } diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index 39b451530..d3228ab1d 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -79,7 +79,6 @@ public: struct FPortalSceneState { - TArray portals; int recursion = 0; int MirrorFlag = 0; @@ -112,7 +111,6 @@ struct FPortalSceneState return !!((MirrorFlag ^ PlaneMirrorFlag) & 1); } - IPortal * FindPortal(const void * src); void StartFrame(); bool RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di); void EndFrame(HWDrawInfo *outer_di); @@ -122,7 +120,7 @@ struct FPortalSceneState inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s) { - if (!local) s->portals.Push(this); + //if (!local) s->portals.Push(this); } @@ -134,7 +132,7 @@ public: HWScenePortalBase() {} virtual ~HWScenePortalBase() {} void SetOwner(IPortal *p) { mOwner = p; } - void ClearClipper(HWDrawInfo *di); + void ClearClipper(HWDrawInfo *di, Clipper *clipper); virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; } virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 6c22e560a..1cd924aaf 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -1458,7 +1458,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ sector_t * segback; #ifdef _DEBUG - if (seg->linedef->Index() == 10) + if (seg->linedef->Index() == 3407) { int a = 0; }