mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 06:12:19 +00:00
- fixed remaining issues with portal refactoring.
This commit is contained in:
parent
6ebec37baf
commit
e7a0ccf879
9 changed files with 90 additions and 61 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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); }
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue