mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- 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:
parent
a23d1c2d25
commit
9f6091519f
7 changed files with 83 additions and 24 deletions
|
@ -201,7 +201,7 @@ public:
|
||||||
//private:
|
//private:
|
||||||
|
|
||||||
void PutWall(HWDrawInfo *di, bool translucent);
|
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 CheckTexturePosition(FTexCoordInfo *tci);
|
||||||
|
|
||||||
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);
|
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);
|
||||||
|
|
|
@ -140,6 +140,14 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
||||||
best = p;
|
best = p;
|
||||||
bestindex = i;
|
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.
|
// 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);
|
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);
|
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,10 @@ class HWPortal
|
||||||
public:
|
public:
|
||||||
FPortalSceneState * mState;
|
FPortalSceneState * mState;
|
||||||
TArray<GLWall> lines;
|
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() {}
|
virtual ~HWPortal() {}
|
||||||
|
@ -83,6 +85,8 @@ public:
|
||||||
void AddLine(GLWall * l)
|
void AddLine(GLWall * l)
|
||||||
{
|
{
|
||||||
lines.Push(*l);
|
lines.Push(*l);
|
||||||
|
boundingBox.addVertex(l->glseg.x1, l->glseg.y1);
|
||||||
|
boundingBox.addVertex(l->glseg.x2, l->glseg.y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
|
||||||
skyinfo.init(sector->sky, Colormap.FadeColor);
|
skyinfo.init(sector->sky, Colormap.FadeColor);
|
||||||
ptype = PORTALTYPE_SKY;
|
ptype = PORTALTYPE_SKY;
|
||||||
sky = &skyinfo;
|
sky = &skyinfo;
|
||||||
PutPortal(di, ptype);
|
PutPortal(di, ptype, plane);
|
||||||
}
|
}
|
||||||
else if (sportal != nullptr)
|
else if (sportal != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -162,7 +162,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
|
||||||
}
|
}
|
||||||
if (ptype != -1)
|
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];
|
ztop[1] = zceil[1];
|
||||||
zbottom[0] = zfloor[0];
|
zbottom[0] = zfloor[0];
|
||||||
zbottom[1] = zfloor[1];
|
zbottom[1] = zfloor[1];
|
||||||
PutPortal(di, ptype);
|
PutPortal(di, ptype, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
auto pstate = screen->mPortalState;
|
||||||
HWPortal * portal;
|
HWPortal * portal = nullptr;
|
||||||
|
|
||||||
MakeVertices(di, false);
|
MakeVertices(di, false);
|
||||||
switch (ptype)
|
switch (ptype)
|
||||||
|
@ -532,7 +532,6 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
case PORTALTYPE_PLANEMIRROR:
|
case PORTALTYPE_PLANEMIRROR:
|
||||||
if (pstate->PlaneMirrorMode * planemirror->fC() <= 0)
|
if (pstate->PlaneMirrorMode * planemirror->fC() <= 0)
|
||||||
{
|
{
|
||||||
//@sync-portal
|
|
||||||
planemirror = pstate->UniquePlaneMirrors.Get(planemirror);
|
planemirror = pstate->UniquePlaneMirrors.Get(planemirror);
|
||||||
portal = di->FindPortal(planemirror);
|
portal = di->FindPortal(planemirror);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
|
@ -588,6 +587,11 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vertcount = 0;
|
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();
|
if (di->isFullbrightScene()) hi.colormap.Clear();
|
||||||
horizon = &hi;
|
horizon = &hi;
|
||||||
PutPortal(di, PORTALTYPE_HORIZON);
|
PutPortal(di, PORTALTYPE_HORIZON, -1);
|
||||||
}
|
}
|
||||||
ztop[1] = ztop[0] = zbottom[0];
|
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();
|
if (di->isFullbrightScene()) hi.colormap.Clear();
|
||||||
horizon = &hi;
|
horizon = &hi;
|
||||||
PutPortal(di, PORTALTYPE_HORIZON);
|
PutPortal(di, PORTALTYPE_HORIZON, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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)
|
if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors)
|
||||||
{
|
{
|
||||||
PutPortal(di, PORTALTYPE_MIRROR);
|
PutPortal(di, PORTALTYPE_MIRROR, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1970,7 +1974,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
||||||
ztop[1] = zceil[1];
|
ztop[1] = zceil[1];
|
||||||
zbottom[0] = zfloor[0];
|
zbottom[0] = zfloor[0];
|
||||||
zbottom[1] = zfloor[1];
|
zbottom[1] = zfloor[1];
|
||||||
PutPortal(di, PORTALTYPE_LINETOLINE);
|
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
|
||||||
}
|
}
|
||||||
else if (seg->linedef->GetTransferredPortal())
|
else if (seg->linedef->GetTransferredPortal())
|
||||||
{
|
{
|
||||||
|
@ -2077,7 +2081,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
||||||
ztop[1] = bch2;
|
ztop[1] = bch2;
|
||||||
zbottom[0] = bfh1;
|
zbottom[0] = bfh1;
|
||||||
zbottom[1] = bfh2;
|
zbottom[1] = bfh2;
|
||||||
PutPortal(di, PORTALTYPE_LINETOLINE);
|
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
|
||||||
}
|
}
|
||||||
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
||||||
{
|
{
|
||||||
|
|
|
@ -495,9 +495,9 @@ public:
|
||||||
auto §ion = sections[i];
|
auto §ion = sections[i];
|
||||||
auto &work = triangles[i];
|
auto &work = triangles[i];
|
||||||
|
|
||||||
BoundingRect bounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect bounds(false);
|
||||||
BoundingRect loopBounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect loopBounds(false);
|
||||||
BoundingRect outermostBounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect outermostBounds(false);
|
||||||
unsigned outermoststart = ~0u;
|
unsigned outermoststart = ~0u;
|
||||||
unsigned loopstart = 0;
|
unsigned loopstart = 0;
|
||||||
bool ispolyorg = false;
|
bool ispolyorg = false;
|
||||||
|
@ -519,7 +519,7 @@ public:
|
||||||
outermoststart = loopstart;
|
outermoststart = loopstart;
|
||||||
loopstart = i + 1;
|
loopstart = i + 1;
|
||||||
}
|
}
|
||||||
loopBounds = { 1e32, 1e32, -1e32, -1e32 };
|
loopBounds.setEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
work.boundingLoopStart = outermoststart;
|
work.boundingLoopStart = outermoststart;
|
||||||
|
@ -716,7 +716,7 @@ public:
|
||||||
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
|
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
|
||||||
dest.vertexindex = -1;
|
dest.vertexindex = -1;
|
||||||
dest.vertexcount = 0;
|
dest.vertexcount = 0;
|
||||||
dest.bounds = {1e32, 1e32, -1e32, -1e32};
|
dest.bounds.setEmpty();
|
||||||
numsegments += group.segments.Size();
|
numsegments += group.segments.Size();
|
||||||
|
|
||||||
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)
|
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)
|
||||||
|
|
|
@ -25,12 +25,35 @@ struct BoundingRect
|
||||||
{
|
{
|
||||||
double left, top, right, bottom;
|
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;
|
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 ||
|
return !(other.left > right ||
|
||||||
other.right < left ||
|
other.right < left ||
|
||||||
|
@ -46,7 +69,7 @@ struct BoundingRect
|
||||||
if (other.bottom > bottom) bottom = other.bottom;
|
if (other.bottom > bottom) bottom = other.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
double distanceTo(const BoundingRect &other)
|
double distanceTo(const BoundingRect &other) const
|
||||||
{
|
{
|
||||||
if (intersects(other)) return 0;
|
if (intersects(other)) return 0;
|
||||||
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
|
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
|
||||||
|
@ -61,10 +84,11 @@ struct BoundingRect
|
||||||
if (y > bottom) bottom = y;
|
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;
|
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue