- initialize clipper with the view frustum for better performance

- change translucent objects to be pointers for faster sorting
This commit is contained in:
Magnus Norddahl 2017-03-24 22:04:07 +01:00
parent 6760e01a0d
commit 321e2da979
6 changed files with 53 additions and 18 deletions

View file

@ -287,6 +287,23 @@ bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angl
return !IsSegmentCulled(angle1, angle2); return !IsSegmentCulled(angle1, angle2);
} }
void PolyCull::MarkViewFrustum()
{
// Clips things outside the viewing frustum.
auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
auto &viewwindow = PolyRenderer::Instance()->Viewwindow;
double tilt = fabs(viewpoint.Angles.Pitch.Degrees);
if (tilt > 46.0) // If the pitch is larger than this you can look all around
return;
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(viewwindow.WidescreenRatio) / 90.0;
angle_t a1 = DAngle(floatangle).BAMs();
if (a1 < ANGLE_180)
{
MarkSegmentCulled(AngleToPseudo(viewpoint.Angles.Yaw.BAMs() + a1), AngleToPseudo(viewpoint.Angles.Yaw.BAMs() - a1));
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the // ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the
@ -320,3 +337,16 @@ angle_t PolyCull::PointToPseudoAngle(double x, double y)
return xs_Fix<30>::ToFix(result); return xs_Fix<30>::ToFix(result);
} }
} }
angle_t PolyCull::AngleToPseudo(angle_t ang)
{
double vecx = cos(ang * M_PI / ANGLE_180);
double vecy = sin(ang * M_PI / ANGLE_180);
double result = vecy / (fabs(vecx) + fabs(vecy));
if (vecx < 0)
{
result = 2.f - result;
}
return xs_Fix<30>::ToFix(result);
}

View file

@ -35,6 +35,7 @@ public:
void MarkSegmentCulled(angle_t angle1, angle_t angle2); void MarkSegmentCulled(angle_t angle1, angle_t angle2);
bool IsSegmentCulled(angle_t angle1, angle_t angle2) const; bool IsSegmentCulled(angle_t angle1, angle_t angle2) const;
void InvertSegments(); void InvertSegments();
void MarkViewFrustum();
std::vector<subsector_t *> PvsSectors; std::vector<subsector_t *> PvsSectors;
double MaxCeilingHeight = 0.0; double MaxCeilingHeight = 0.0;
@ -64,4 +65,5 @@ private:
Vec4f PortalClipPlane; Vec4f PortalClipPlane;
static angle_t PointToPseudoAngle(double x, double y); static angle_t PointToPseudoAngle(double x, double y);
static angle_t AngleToPseudo(angle_t ang);
}; };

View file

@ -73,6 +73,7 @@ void RenderPolyScene::Render(int portalDepth)
ClearBuffers(); ClearBuffers();
if (!PortalSegmentsAdded) if (!PortalSegmentsAdded)
Cull.ClearSolidSegments(); Cull.ClearSolidSegments();
Cull.MarkViewFrustum();
Cull.CullScene(WorldToClip, PortalPlane); Cull.CullScene(WorldToClip, PortalPlane);
Cull.ClearSolidSegments(); Cull.ClearSolidSegments();
RenderSectors(); RenderSectors();
@ -124,6 +125,8 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub)
} }
} }
RenderMemory &memory = PolyRenderer::Instance()->FrameMemory;
bool mainBSP = ((unsigned int)(sub->Index()) < level.subsectors.Size()); bool mainBSP = ((unsigned int)(sub->Index()) < level.subsectors.Size());
if (mainBSP) if (mainBSP)
{ {
@ -131,7 +134,7 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub)
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
{ {
particle_t *particle = Particles + i; particle_t *particle = Particles + i;
TranslucentObjects.push_back({ particle, sub, subsectorDepth }); TranslucentObjects.push_back(memory.NewObject<PolyTranslucentObject>(particle, sub, subsectorDepth));
} }
} }
@ -146,7 +149,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVe
subsector_t *sub = &level.subsectors[0]; subsector_t *sub = &level.subsectors[0];
auto it = SubsectorDepths.find(sub); auto it = SubsectorDepths.find(sub);
if (it != SubsectorDepths.end()) if (it != SubsectorDepths.end())
TranslucentObjects.push_back({ thing, sub, it->second, sortDistance, 0.0f, 1.0f }); TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject<PolyTranslucentObject>(thing, sub, it->second, sortDistance, 0.0f, 1.0f));
} }
else else
{ {
@ -187,7 +190,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2
auto it = SubsectorDepths.find(sub); auto it = SubsectorDepths.find(sub);
if (it != SubsectorDepths.end()) if (it != SubsectorDepths.end())
TranslucentObjects.push_back({ thing, sub, it->second, sortDistance, (float)t1, (float)t2 }); TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject<PolyTranslucentObject>(thing, sub, it->second, sortDistance, (float)t1, (float)t2));
} }
void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth)
@ -347,29 +350,29 @@ void RenderPolyScene::RenderTranslucent(int portalDepth)
} }
} }
std::stable_sort(TranslucentObjects.begin(), TranslucentObjects.end()); std::stable_sort(TranslucentObjects.begin(), TranslucentObjects.end(), [](auto a, auto b) { return *a < *b; });
for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it)
{ {
auto &obj = *it; PolyTranslucentObject *obj = *it;
if (obj.particle) if (obj->particle)
{ {
RenderPolyParticle spr; RenderPolyParticle spr;
spr.Render(WorldToClip, PortalPlane, obj.particle, obj.sub, obj.subsectorDepth, StencilValue + 1); spr.Render(WorldToClip, PortalPlane, obj->particle, obj->sub, obj->subsectorDepth, StencilValue + 1);
} }
else if (!obj.thing) else if (!obj->thing)
{ {
obj.wall.Render(WorldToClip, PortalPlane, Cull); obj->wall.Render(WorldToClip, PortalPlane, Cull);
} }
else if ((obj.thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) else if ((obj->thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
{ {
RenderPolyWallSprite wallspr; RenderPolyWallSprite wallspr;
wallspr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1); wallspr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, obj->subsectorDepth, StencilValue + 1);
} }
else else
{ {
RenderPolySprite spr; RenderPolySprite spr;
spr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1, obj.SpriteLeft, obj.SpriteRight); spr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, obj->subsectorDepth, StencilValue + 1, obj->SpriteLeft, obj->SpriteRight);
} }
} }
} }

View file

@ -97,7 +97,7 @@ private:
uint32_t NextSubsectorDepth = 0; uint32_t NextSubsectorDepth = 0;
std::set<sector_t *> SeenSectors; std::set<sector_t *> SeenSectors;
std::unordered_map<subsector_t *, uint32_t> SubsectorDepths; std::unordered_map<subsector_t *, uint32_t> SubsectorDepths;
std::vector<PolyTranslucentObject> TranslucentObjects; std::vector<PolyTranslucentObject *> TranslucentObjects;
std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals; std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals;
std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals; std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals;

View file

@ -37,7 +37,7 @@
EXTERN_CVAR(Bool, r_drawmirrors) EXTERN_CVAR(Bool, r_drawmirrors)
bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals) bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals)
{ {
PolyDrawLinePortal *polyportal = nullptr; PolyDrawLinePortal *polyportal = nullptr;
if (line->backsector == nullptr && line->linedef && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors)) if (line->backsector == nullptr && line->linedef && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors))
@ -153,7 +153,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP
FTexture *midtex = TexMan(line->sidedef->GetTexture(side_t::mid), true); FTexture *midtex = TexMan(line->sidedef->GetTexture(side_t::mid), true);
if (midtex && midtex->UseType != FTexture::TEX_Null) if (midtex && midtex->UseType != FTexture::TEX_Null)
translucentWallsOutput.push_back({ wall }); translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject<PolyTranslucentObject>(wall));
if (polyportal) if (polyportal)
{ {
@ -165,7 +165,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipP
return polyportal != nullptr; return polyportal != nullptr;
} }
void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput) void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput)
{ {
double frontceilz1 = fakeFloor->top.plane->ZatPoint(line->v1); double frontceilz1 = fakeFloor->top.plane->ZatPoint(line->v1);
double frontfloorz1 = fakeFloor->bottom.plane->ZatPoint(line->v1); double frontfloorz1 = fakeFloor->bottom.plane->ZatPoint(line->v1);

View file

@ -32,8 +32,8 @@ class Vec4f;
class RenderPolyWall class RenderPolyWall
{ {
public: public:
static bool RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals); static bool RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals);
static void Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput); static void Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput);
void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull); void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, PolyCull &cull);