- restrict the sky portal shortcut to skies in scenes where there are no other portals.

This entire setup does not work with sector portals, causing various render glitches in Shadow Warrior's portals. This also applies to skies within portals so it is now restricted to single sky setups.
This commit is contained in:
Christoph Oelckers 2021-05-03 00:52:17 +02:00
parent 56fcf904b5
commit d8b808576f
2 changed files with 8 additions and 41 deletions

View file

@ -110,53 +110,21 @@ void FPortalSceneState::EndFrame(HWDrawInfo *di, FRenderState &state)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Renders one sky portal without a stencil. // Renders one sky portal without a stencil. Only useful if this is the only portal in view.
// In more complex scenes using a stencil for skies can severely stall
// the GPU and there's rarely more than one sky visible at a time.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di, FRenderState &state) bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di, FRenderState &state)
{ {
HWPortal * p; HWPortal* best = nullptr;
HWPortal * best = nullptr;
unsigned bestindex = 0; unsigned bestindex = 0;
// Find the one with the highest amount of lines. if (recursion > 0 || outer_di->Portals.Size() != 1 || !outer_di->Portals[0]->IsSky()) return false;
// 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)
{
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()) best = outer_di->Portals[0];
{ outer_di->Portals.Clear();
best = p; RenderPortal(best, state, false, outer_di);
bestindex = i; delete best;
} return true;
// 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;
} }

View file

@ -352,7 +352,6 @@ protected:
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
virtual void * GetSource() const { return origin; } virtual void * GetSource() const { return origin; }
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
virtual const char *GetName(); virtual const char *GetName();
virtual int GetType() { return PORTAL_SECTOR_CEILING; } virtual int GetType() { return PORTAL_SECTOR_CEILING; }
PortalDesc *origin; PortalDesc *origin;