- fixed remaining issues with portal refactoring.

This commit is contained in:
Christoph Oelckers 2018-06-23 23:02:56 +02:00
parent 6ebec37baf
commit e7a0ccf879
9 changed files with 90 additions and 61 deletions

View file

@ -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<HWSectorStackPortal*>(static_cast<GLScenePortal*>(portal)->mScene);
ptl->AddSubsector(sub);

View file

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

View file

@ -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<FDrawInfo*>(di)->DrawScene(DM_PORTAL);
mScene->Shutdown(di);
}
else ClearScreen(di);
}
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
};

View file

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

View file

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

View file

@ -110,6 +110,7 @@ struct HWDrawInfo
Clipper *mClipper;
FRenderViewpoint Viewpoint;
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
TArray<IPortal *> Portals;
TArray<MissingTextureInfo> MissingUpperTextures;
TArray<MissingTextureInfo> 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();

View file

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

View file

@ -79,7 +79,6 @@ public:
struct FPortalSceneState
{
TArray<IPortal *> 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; }

View file

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