- changed the stencil cap drawer to only cover the area which is actually used by the portal.

This will now both exclude floor caps when only ceiling elements are used and everything outside the bounding box of active portal lines.
Hopefully this is enough to fix the issues with portal caps but of course it is not foolproof if someone just makes the right setup.
This commit is contained in:
Christoph Oelckers 2018-11-14 23:30:46 +01:00
parent a23d1c2d25
commit 9f6091519f
7 changed files with 83 additions and 24 deletions

View file

@ -201,7 +201,7 @@ public:
//private:
void PutWall(HWDrawInfo *di, bool translucent);
void PutPortal(HWDrawInfo *di, int ptype);
void PutPortal(HWDrawInfo *di, int ptype, int plane);
void CheckTexturePosition(FTexCoordInfo *tci);
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);

View file

@ -140,6 +140,14 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
best = p;
bestindex = i;
}
// 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;
}
}
}
@ -187,8 +195,27 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
{
// The cap's depth handling needs special treatment so that it won't block further portal caps.
if (pass == STP_DepthRestore) state.SetDepthRange(1, 1);
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4, false);
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4, false);
if (planesused & (1 << sector_t::floor))
{
auto verts = screen->mVertexData->AllocVertices(4);
auto ptr = verts.first;
ptr[0].Set((float)boundingBox.left, -32767.f, (float)boundingBox.top, 0, 0);
ptr[1].Set((float)boundingBox.right, -32767.f, (float)boundingBox.top, 0, 0);
ptr[2].Set((float)boundingBox.left, -32767.f, (float)boundingBox.bottom, 0, 0);
ptr[3].Set((float)boundingBox.right, -32767.f, (float)boundingBox.bottom, 0, 0);
state.Draw(DT_TriangleStrip, verts.second, 4, false);
}
if (planesused & (1 << sector_t::ceiling))
{
auto verts = screen->mVertexData->AllocVertices(4);
auto ptr = verts.first;
ptr[0].Set((float)boundingBox.left, 32767.f, (float)boundingBox.top, 0, 0);
ptr[1].Set((float)boundingBox.right, 32767.f, (float)boundingBox.top, 0, 0);
ptr[2].Set((float)boundingBox.left, 32767.f, (float)boundingBox.bottom, 0, 0);
ptr[3].Set((float)boundingBox.right, 32767.f, (float)boundingBox.bottom, 0, 0);
state.Draw(DT_TriangleStrip, verts.second, 4, false);
}
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
}
}

View file

@ -61,8 +61,10 @@ class HWPortal
public:
FPortalSceneState * mState;
TArray<GLWall> lines;
BoundingRect boundingBox;
int planesused = 0;
HWPortal(FPortalSceneState *s, bool local = false) : mState(s)
HWPortal(FPortalSceneState *s, bool local = false) : mState(s), boundingBox(false)
{
}
virtual ~HWPortal() {}
@ -83,6 +85,8 @@ public:
void AddLine(GLWall * l)
{
lines.Push(*l);
boundingBox.addVertex(l->glseg.x1, l->glseg.y1);
boundingBox.addVertex(l->glseg.x2, l->glseg.y2);
}

View file

@ -122,7 +122,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
skyinfo.init(sector->sky, Colormap.FadeColor);
ptype = PORTALTYPE_SKY;
sky = &skyinfo;
PutPortal(di, ptype);
PutPortal(di, ptype, plane);
}
else if (sportal != nullptr)
{
@ -162,7 +162,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
}
if (ptype != -1)
{
PutPortal(di, ptype);
PutPortal(di, ptype, plane);
}
}
@ -197,7 +197,7 @@ void GLWall::SkyLine(HWDrawInfo *di, sector_t *fs, line_t *line)
ztop[1] = zceil[1];
zbottom[0] = zfloor[0];
zbottom[1] = zfloor[1];
PutPortal(di, ptype);
PutPortal(di, ptype, -1);
}

View file

@ -483,10 +483,10 @@ void GLWall::PutWall(HWDrawInfo *di, bool translucent)
//
//==========================================================================
void GLWall::PutPortal(HWDrawInfo *di, int ptype)
void GLWall::PutPortal(HWDrawInfo *di, int ptype, int plane)
{
auto pstate = screen->mPortalState;
HWPortal * portal;
HWPortal * portal = nullptr;
MakeVertices(di, false);
switch (ptype)
@ -532,7 +532,6 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
case PORTALTYPE_PLANEMIRROR:
if (pstate->PlaneMirrorMode * planemirror->fC() <= 0)
{
//@sync-portal
planemirror = pstate->UniquePlaneMirrors.Get(planemirror);
portal = di->FindPortal(planemirror);
if (!portal)
@ -588,6 +587,11 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
break;
}
vertcount = 0;
if (plane != -1 && portal)
{
portal->planesused |= (1<<plane);
}
}
//==========================================================================
@ -849,7 +853,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
if (di->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON);
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
ztop[1] = ztop[0] = zbottom[0];
}
@ -878,7 +882,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
if (di->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON);
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
}
return true;
@ -1135,7 +1139,7 @@ void GLWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg,
if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors)
{
PutPortal(di, PORTALTYPE_MIRROR);
PutPortal(di, PORTALTYPE_MIRROR, -1);
}
else
{
@ -1970,7 +1974,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
ztop[1] = zceil[1];
zbottom[0] = zfloor[0];
zbottom[1] = zfloor[1];
PutPortal(di, PORTALTYPE_LINETOLINE);
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
}
else if (seg->linedef->GetTransferredPortal())
{
@ -2077,7 +2081,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
ztop[1] = bch2;
zbottom[0] = bfh1;
zbottom[1] = bfh2;
PutPortal(di, PORTALTYPE_LINETOLINE);
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
}
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
{

View file

@ -495,9 +495,9 @@ public:
auto &section = sections[i];
auto &work = triangles[i];
BoundingRect bounds = { 1e32, 1e32, -1e32, -1e32 };
BoundingRect loopBounds = { 1e32, 1e32, -1e32, -1e32 };
BoundingRect outermostBounds = { 1e32, 1e32, -1e32, -1e32 };
BoundingRect bounds(false);
BoundingRect loopBounds(false);
BoundingRect outermostBounds(false);
unsigned outermoststart = ~0u;
unsigned loopstart = 0;
bool ispolyorg = false;
@ -519,7 +519,7 @@ public:
outermoststart = loopstart;
loopstart = i + 1;
}
loopBounds = { 1e32, 1e32, -1e32, -1e32 };
loopBounds.setEmpty();
}
}
work.boundingLoopStart = outermoststart;
@ -716,7 +716,7 @@ public:
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
dest.vertexindex = -1;
dest.vertexcount = 0;
dest.bounds = {1e32, 1e32, -1e32, -1e32};
dest.bounds.setEmpty();
numsegments += group.segments.Size();
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)

View file

@ -25,12 +25,35 @@ struct BoundingRect
{
double left, top, right, bottom;
bool contains(const BoundingRect & other)
BoundingRect() = default;
BoundingRect(bool)
{
setEmpty();
}
void setEmpty()
{
left = top = 1e38;
bottom = right = -1e38;
}
bool contains(const BoundingRect & other) const
{
return left <= other.left && top <= other.top && right >= other.right && bottom >= other.bottom;
}
bool intersects(const BoundingRect & other)
bool contains(double x, double y) const
{
return left <= x && top <= y && right >= x && bottom >= y;
}
template <class T>
bool contains(const T &vec) const
{
return left <= vec.X && top <= vec.Y && right >= vec.X && bottom >= vec.Y;
}
bool intersects(const BoundingRect & other) const
{
return !(other.left > right ||
other.right < left ||
@ -46,7 +69,7 @@ struct BoundingRect
if (other.bottom > bottom) bottom = other.bottom;
}
double distanceTo(const BoundingRect &other)
double distanceTo(const BoundingRect &other) const
{
if (intersects(other)) return 0;
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
@ -61,10 +84,11 @@ struct BoundingRect
if (y > bottom) bottom = y;
}
bool operator == (const BoundingRect &other)
bool operator == (const BoundingRect &other) const
{
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
}
};