Distance sort sprites

This commit is contained in:
Magnus Norddahl 2016-11-09 11:38:07 +01:00
parent 83b3169ed5
commit dc0e6d40a4
2 changed files with 51 additions and 1 deletions

View file

@ -47,6 +47,10 @@ void RenderPolyBsp::Render()
SolidSegments.push_back({ -0x7fff, 0 }); SolidSegments.push_back({ -0x7fff, 0 });
SolidSegments.push_back({ viewwidth, 0x7fff }); SolidSegments.push_back({ viewwidth, 0x7fff });
SectorSpriteRanges.clear();
SectorSpriteRanges.resize(numsectors);
SortedSprites.clear();
// Perspective correct: // Perspective correct:
float ratio = WidescreenRatio; float ratio = WidescreenRatio;
float fovratio = (WidescreenRatio >= 1.3f) ? 1.333333f : ratio; float fovratio = (WidescreenRatio >= 1.3f) ? 1.333333f : ratio;
@ -174,8 +178,10 @@ void RenderPolyBsp::RenderSubsector(subsector_t *sub)
PolyTriangleDrawer::draw(uniforms, vertices, sub->numlines, TriangleDrawMode::Fan, true, 0, viewwidth, 0, viewheight, ceiltex); PolyTriangleDrawer::draw(uniforms, vertices, sub->numlines, TriangleDrawMode::Fan, true, 0, viewwidth, 0, viewheight, ceiltex);
} }
for (AActor *thing = sub->sector->thinglist; thing != nullptr; thing = thing->snext) SpriteRange sprites = GetSpritesForSector(sub->sector);
for (int i = 0; i < sprites.Count; i++)
{ {
AActor *thing = SortedSprites[sprites.Start + i].Thing;
if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
AddWallSprite(thing, sub); AddWallSprite(thing, sub);
else else
@ -183,6 +189,26 @@ void RenderPolyBsp::RenderSubsector(subsector_t *sub)
} }
} }
SpriteRange RenderPolyBsp::GetSpritesForSector(sector_t *sector)
{
if (SectorSpriteRanges.size() < sector->sectornum || sector->sectornum < 0)
return SpriteRange();
auto &range = SectorSpriteRanges[sector->sectornum];
if (range.Start == -1)
{
range.Start = (int)SortedSprites.size();
range.Count = 0;
for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext)
{
SortedSprites.push_back({ thing, (thing->Pos() - ViewPos).LengthSquared() });
range.Count++;
}
std::stable_sort(SortedSprites.begin() + range.Start, SortedSprites.begin() + range.Start + range.Count);
}
return range;
}
void RenderPolyBsp::AddLine(seg_t *line, sector_t *frontsector) void RenderPolyBsp::AddLine(seg_t *line, sector_t *frontsector)
{ {
// Reject lines not facing viewer // Reject lines not facing viewer

View file

@ -49,6 +49,26 @@ public:
FDynamicColormap *Colormap = nullptr; FDynamicColormap *Colormap = nullptr;
}; };
// Used for sorting things by distance to the camera
class PolySortedSprite
{
public:
PolySortedSprite(AActor *thing, double distanceSquared) : Thing(thing), DistanceSquared(distanceSquared) { }
bool operator<(const PolySortedSprite &other) const { return DistanceSquared > other.DistanceSquared; }
AActor *Thing;
double DistanceSquared;
};
class SpriteRange
{
public:
SpriteRange() = default;
SpriteRange(int start, int count) : Start(start), Count(count) { }
int Start = -1;
int Count = 0;
};
// Renders a GL BSP tree in a scene // Renders a GL BSP tree in a scene
class RenderPolyBsp class RenderPolyBsp
{ {
@ -67,6 +87,7 @@ private:
bool IsThingCulled(AActor *thing); bool IsThingCulled(AActor *thing);
visstyle_t GetSpriteVisStyle(AActor *thing, double z); visstyle_t GetSpriteVisStyle(AActor *thing, double z);
FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX); FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX);
SpriteRange GetSpritesForSector(sector_t *sector);
void RenderPlayerSprites(); void RenderPlayerSprites();
void RenderPlayerSprite(DPSprite *sprite, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac); void RenderPlayerSprite(DPSprite *sprite, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac);
@ -85,6 +106,9 @@ private:
std::vector<subsector_t *> PvsSectors; std::vector<subsector_t *> PvsSectors;
TriMatrix worldToClip; TriMatrix worldToClip;
std::vector<SpriteRange> SectorSpriteRanges;
std::vector<PolySortedSprite> SortedSprites;
std::vector<PolyScreenSprite> ScreenSprites; std::vector<PolyScreenSprite> ScreenSprites;
const int BaseXCenter = 160; const int BaseXCenter = 160;