mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- improve sector portals rendering in softpoly
- fix a softpoly memory leak and change vertex list to be allocated using the frame allocator
This commit is contained in:
parent
b5720ee1e7
commit
f178646e1a
13 changed files with 98 additions and 131 deletions
|
@ -74,27 +74,3 @@ void PolyStencilBuffer::Clear(int newwidth, int newheight, uint8_t stencil_value
|
|||
m[i] = 0xffffff00 | stencil_value;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
int NextBufferVertex = 0;
|
||||
}
|
||||
|
||||
TriVertex *PolyVertexBuffer::GetVertices(int count)
|
||||
{
|
||||
enum { VertexBufferSize = 256 * 1024 };
|
||||
static TriVertex Vertex[VertexBufferSize];
|
||||
|
||||
if (NextBufferVertex + count > VertexBufferSize)
|
||||
return nullptr;
|
||||
TriVertex *v = Vertex + NextBufferVertex;
|
||||
NextBufferVertex += count;
|
||||
return v;
|
||||
}
|
||||
|
||||
void PolyVertexBuffer::Clear()
|
||||
{
|
||||
NextBufferVertex = 0;
|
||||
}
|
||||
|
|
|
@ -61,10 +61,3 @@ private:
|
|||
std::vector<uint8_t> values;
|
||||
std::vector<uint32_t> masks;
|
||||
};
|
||||
|
||||
class PolyVertexBuffer
|
||||
{
|
||||
public:
|
||||
static TriVertex *GetVertices(int count);
|
||||
static void Clear();
|
||||
};
|
||||
|
|
|
@ -154,7 +154,7 @@ void PolyRenderer::RenderRemainingPlayerSprites()
|
|||
|
||||
void PolyRenderer::ClearBuffers()
|
||||
{
|
||||
PolyVertexBuffer::Clear();
|
||||
FrameMemory.Clear();
|
||||
PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0);
|
||||
PolySubsectorGBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight());
|
||||
NextStencilValue = 0;
|
||||
|
|
|
@ -35,6 +35,7 @@ void PolyCull::CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPl
|
|||
PortalClipPlane = portalClipPlane;
|
||||
|
||||
// Cull front to back
|
||||
FirstSkyHeight = true;
|
||||
MaxCeilingHeight = 0.0;
|
||||
MinFloorHeight = 0.0;
|
||||
if (level.nodes.Size() == 0)
|
||||
|
@ -71,8 +72,17 @@ void PolyCull::CullNode(void *node)
|
|||
void PolyCull::CullSubsector(subsector_t *sub)
|
||||
{
|
||||
// Update sky heights for the scene
|
||||
MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0());
|
||||
MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0());
|
||||
if (!FirstSkyHeight)
|
||||
{
|
||||
MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0());
|
||||
MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0());
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxCeilingHeight = sub->sector->ceilingplane.Zat0();
|
||||
MinFloorHeight = sub->sector->floorplane.Zat0();
|
||||
FirstSkyHeight = false;
|
||||
}
|
||||
|
||||
// Mark that we need to render this
|
||||
PvsSectors.push_back(sub);
|
||||
|
@ -246,6 +256,7 @@ bool PolyCull::CheckBBox(float *bspcoord)
|
|||
|
||||
bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angle_t &angle1, angle_t &angle2) const
|
||||
{
|
||||
#if 0
|
||||
// Clip line to the portal clip plane
|
||||
float distance1 = Vec4f::dot(PortalClipPlane, Vec4f((float)x1, (float)y1, 0.0f, 1.0f));
|
||||
float distance2 = Vec4f::dot(PortalClipPlane, Vec4f((float)x2, (float)y2, 0.0f, 1.0f));
|
||||
|
@ -269,6 +280,7 @@ bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angl
|
|||
y1 = ny1;
|
||||
y2 = ny2;
|
||||
}
|
||||
#endif
|
||||
|
||||
angle2 = PointToPseudoAngle(x1, y1);
|
||||
angle1 = PointToPseudoAngle(x2, y2);
|
||||
|
|
|
@ -58,6 +58,7 @@ private:
|
|||
std::vector<SolidSegment> SolidSegments;
|
||||
std::vector<SolidSegment> TempInvertSolidSegments;
|
||||
const int SolidCullScale = 3000;
|
||||
bool FirstSkyHeight = true;
|
||||
|
||||
FrustumPlanes frustumPlanes;
|
||||
Vec4f PortalClipPlane;
|
||||
|
|
|
@ -102,9 +102,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
|
||||
DVector2 points[2] = { decal_left, decal_right };
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
bool foggy = false;
|
||||
int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4;
|
||||
|
|
|
@ -43,9 +43,7 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const Vec4f &clipP
|
|||
{ pos.X + viewpoint.Sin * psize, pos.Y - viewpoint.Cos * psize }
|
||||
};
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
bool foggy = false;
|
||||
int actualextralight = foggy ? 0 : viewpoint.extralight << 4;
|
||||
|
|
|
@ -119,9 +119,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const Vec4f &c
|
|||
args.uniforms.flags = TriUniforms::nearest_filter;
|
||||
args.uniforms.subsectorDepth = subsectorDepth;
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(sub->numlines);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(sub->numlines);
|
||||
|
||||
if (ceiling)
|
||||
{
|
||||
|
@ -234,16 +232,23 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
if (tex->UseType == FTexture::TEX_Null)
|
||||
return;
|
||||
|
||||
bool isSky = picnum == skyflatnum;
|
||||
|
||||
std::vector<PolyPortalSegment> portalSegments;
|
||||
FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor);
|
||||
PolyDrawSectorPortal *polyportal = nullptr;
|
||||
if (portal && (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into
|
||||
portal = nullptr;
|
||||
|
||||
|
||||
bool isSky = portal || picnum == skyflatnum;
|
||||
|
||||
if (portal)
|
||||
{
|
||||
// Skip portals not facing the camera
|
||||
if ((ceiling && frontsector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) ||
|
||||
(!ceiling && frontsector->floorplane.PointOnSide(viewpoint.Pos) < 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &p : sectorPortals)
|
||||
{
|
||||
if (p->Portal == portal) // To do: what other criteria do we need to check for?
|
||||
|
@ -258,65 +263,30 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
polyportal = sectorPortals.back().get();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Calculate portal clipping
|
||||
|
||||
if (!isSky)
|
||||
portalSegments.reserve(sub->numlines);
|
||||
for (uint32_t i = 0; i < sub->numlines; i++)
|
||||
{
|
||||
DVector2 v;
|
||||
bool inside = true;
|
||||
double vdist = 1.0e10;
|
||||
seg_t *line = &sub->firstline[i];
|
||||
|
||||
portalSegments.reserve(sub->numlines);
|
||||
for (uint32_t i = 0; i < sub->numlines; i++)
|
||||
DVector2 pt1 = line->v1->fPos() - viewpoint.Pos;
|
||||
DVector2 pt2 = line->v2->fPos() - viewpoint.Pos;
|
||||
bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0;
|
||||
if (!backside)
|
||||
{
|
||||
seg_t *line = &sub->firstline[i];
|
||||
|
||||
DVector2 pt1 = line->v1->fPos() - viewpoint.Pos;
|
||||
DVector2 pt2 = line->v2->fPos() - viewpoint.Pos;
|
||||
bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0;
|
||||
if (backside)
|
||||
inside = false;
|
||||
|
||||
double dist = pt1.LengthSquared();
|
||||
if (dist < vdist)
|
||||
{
|
||||
v = line->v1->fPos();
|
||||
vdist = dist;
|
||||
}
|
||||
dist = pt2.LengthSquared();
|
||||
if (dist < vdist)
|
||||
{
|
||||
v = line->v2->fPos();
|
||||
vdist = dist;
|
||||
}
|
||||
|
||||
if (!backside)
|
||||
{
|
||||
angle_t angle1, angle2;
|
||||
if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2))
|
||||
portalSegments.push_back({ angle1, angle2 });
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t angle1, angle2;
|
||||
if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2))
|
||||
portalSegments.push_back({ angle1, angle2 });
|
||||
}
|
||||
angle_t angle1, angle2;
|
||||
if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2))
|
||||
portalSegments.push_back({ angle1, angle2 });
|
||||
}
|
||||
|
||||
if (inside)
|
||||
else
|
||||
{
|
||||
polyportal->PortalPlane = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
else if(polyportal->PortalPlane == Vec4f(0.0f) || Vec4f::dot(polyportal->PortalPlane, Vec4f((float)v.X, (float)v.Y, 0.0f, 1.0f)) > 0.0f)
|
||||
{
|
||||
DVector2 planePos = v;
|
||||
DVector2 planeNormal = v - viewpoint.Pos;
|
||||
planeNormal.MakeUnit();
|
||||
double planeD = -(planeNormal | (planePos + planeNormal * 0.001));
|
||||
polyportal->PortalPlane = Vec4f((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD);
|
||||
angle_t angle1, angle2;
|
||||
if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2))
|
||||
portalSegments.push_back({ angle1, angle2 });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UVTransform transform(ceiling ? frontsector->planes[sector_t::ceiling].xform : frontsector->planes[sector_t::floor].xform, tex);
|
||||
|
@ -331,9 +301,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
args.uniforms.flags = TriUniforms::nearest_filter;
|
||||
args.uniforms.subsectorDepth = isSky ? RenderPolyScene::SkySubsectorDepth : subsectorDepth;
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(sub->numlines);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(sub->numlines);
|
||||
|
||||
if (ceiling)
|
||||
{
|
||||
|
@ -364,21 +332,9 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
|
||||
if (!isSky)
|
||||
{
|
||||
if (!portal)
|
||||
{
|
||||
args.SetTexture(tex);
|
||||
args.blendmode = TriBlendMode::Copy;
|
||||
PolyTriangleDrawer::draw(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.stencilwritevalue = polyportal->StencilValue;
|
||||
args.writeColor = false;
|
||||
args.writeSubsector = false;
|
||||
PolyTriangleDrawer::draw(args);
|
||||
polyportal->Shape.push_back({ args.vinput, args.vcount, args.ccw, subsectorDepth });
|
||||
polyportal->Segments.insert(polyportal->Segments.end(), portalSegments.begin(), portalSegments.end());
|
||||
}
|
||||
args.SetTexture(tex);
|
||||
args.blendmode = TriBlendMode::Copy;
|
||||
PolyTriangleDrawer::draw(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -398,9 +354,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan
|
|||
|
||||
for (uint32_t i = 0; i < sub->numlines; i++)
|
||||
{
|
||||
TriVertex *wallvert = PolyVertexBuffer::GetVertices(4);
|
||||
if (!wallvert)
|
||||
return;
|
||||
TriVertex *wallvert = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
seg_t *line = &sub->firstline[i];
|
||||
|
||||
|
|
|
@ -43,10 +43,51 @@ void PolyDrawSectorPortal::Render(int portalDepth)
|
|||
if (Portal->mType == PORTS_HORIZON || Portal->mType == PORTS_PLANE)
|
||||
return;
|
||||
|
||||
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
|
||||
Vec4f portalPlane = Vec4f(0.0f);
|
||||
if (Portal->mType != PORTS_SKYVIEWPOINT)
|
||||
{
|
||||
float minHeight;
|
||||
float maxHeight;
|
||||
bool first = true;
|
||||
for (const auto &range : Shape)
|
||||
{
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
minHeight = range.Vertices[i].z;
|
||||
maxHeight = range.Vertices[i].z;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
minHeight = MIN(minHeight, range.Vertices[i].z);
|
||||
maxHeight = MAX(maxHeight, range.Vertices[i].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!first && minHeight > viewpoint.Pos.Z)
|
||||
{
|
||||
portalPlane.x = 0.0f;
|
||||
portalPlane.y = 0.0f;
|
||||
portalPlane.z = 1.0f;
|
||||
portalPlane.w = -minHeight;
|
||||
}
|
||||
else if (!first && maxHeight < viewpoint.Pos.Z)
|
||||
{
|
||||
portalPlane.x = 0.0f;
|
||||
portalPlane.y = 0.0f;
|
||||
portalPlane.z = -1.0f;
|
||||
portalPlane.w = maxHeight;
|
||||
}
|
||||
}
|
||||
|
||||
SaveGlobals();
|
||||
|
||||
// To do: get this information from PolyRenderer instead of duplicating the code..
|
||||
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
const auto &viewwindow = PolyRenderer::Instance()->Viewwindow;
|
||||
double radPitch = viewpoint.Angles.Pitch.Normalized180().Radians();
|
||||
double angx = cos(radPitch);
|
||||
|
@ -65,7 +106,7 @@ void PolyDrawSectorPortal::Render(int portalDepth)
|
|||
TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
|
||||
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
||||
|
||||
RenderPortal.SetViewpoint(worldToClip, PortalPlane, StencilValue);
|
||||
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);
|
||||
RenderPortal.SetPortalSegments(Segments);
|
||||
RenderPortal.Render(portalDepth);
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ public:
|
|||
uint32_t StencilValue = 0;
|
||||
std::vector<PolyPortalVertexRange> Shape;
|
||||
std::vector<PolyPortalSegment> Segments;
|
||||
Vec4f PortalPlane = Vec4f(0.0f);
|
||||
|
||||
private:
|
||||
void SaveGlobals();
|
||||
|
|
|
@ -102,9 +102,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const Vec4f &clipPla
|
|||
// Rumor has it that AlterWeaponSprite needs to be called with visstyle passed in somewhere around here..
|
||||
//R_SetColorMapLight(visstyle.BaseColormap, 0, visstyle.ColormapNum << FRACBITS);
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
bool foggy = false;
|
||||
int actualextralight = foggy ? 0 : viewpoint.extralight << 4;
|
||||
|
|
|
@ -120,6 +120,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP
|
|||
double middlefloorz2 = MIN(bottomceilz2, middleceilz2);
|
||||
|
||||
bool bothSkyCeiling = frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum;
|
||||
bool bothSkyFloor = frontsector->GetTexture(sector_t::floor) == skyflatnum && backsector->GetTexture(sector_t::floor) == skyflatnum;
|
||||
|
||||
if ((topceilz1 > topfloorz1 || topceilz2 > topfloorz2) && line->sidedef && !bothSkyCeiling)
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP
|
|||
wall.Render(worldToClip, clipPlane, cull);
|
||||
}
|
||||
|
||||
if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef)
|
||||
if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor)
|
||||
{
|
||||
wall.SetCoords(line->v1->fPos(), line->v2->fPos(), bottomceilz1, bottomfloorz1, bottomceilz2, bottomfloorz2);
|
||||
wall.TopZ = bottomceilz1;
|
||||
|
@ -204,9 +205,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane
|
|||
if (!tex && !Polyportal)
|
||||
return;
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
vertices[0].x = (float)v1.X;
|
||||
vertices[0].y = (float)v1.Y;
|
||||
|
|
|
@ -69,9 +69,7 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const Vec4f &cli
|
|||
|
||||
DVector2 points[2] = { left, right };
|
||||
|
||||
TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
|
||||
if (!vertices)
|
||||
return;
|
||||
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);
|
||||
|
||||
bool foggy = false;
|
||||
int actualextralight = foggy ? 0 : viewpoint.extralight << 4;
|
||||
|
|
Loading…
Reference in a new issue