mirror of
https://github.com/DrBeef/Raze.git
synced 2025-02-20 18:52:43 +00:00
- do some better sorting of slope sprites.
Splitting by translucent floor plane is essential, splitting by wall not that much - sorting by center point should be sufficient here.
This commit is contained in:
parent
9f83fd3575
commit
e2e3b4482d
6 changed files with 155 additions and 21 deletions
|
@ -110,6 +110,7 @@ struct HWDrawInfo
|
|||
TArray<HWPortal *> Portals;
|
||||
tspritetype tsprite[MAXSPRITESONSCREEN];
|
||||
int spritesortcnt;
|
||||
TArray<FFlatVertex> SlopeSpriteVertices; // we need to cache these in system memory in case of translucency splits.
|
||||
|
||||
// This is needed by the BSP traverser.
|
||||
bool multithread;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "hw_renderstate.h"
|
||||
#include "hw_drawinfo.h"
|
||||
|
||||
#define MIN_EQ (0.0005f)
|
||||
|
||||
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.
|
||||
|
||||
void ResetRenderDataAllocator()
|
||||
|
@ -385,7 +387,51 @@ void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort)
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
#define MIN_EQ (0.0005f)
|
||||
void HWDrawList::SortSlopeIntoPlane(HWDrawInfo* di, SortNode* head, SortNode* sort)
|
||||
{
|
||||
HWFlat* fh = flats[drawitems[head->itemindex].index];
|
||||
HWFlat* ss = flats[drawitems[sort->itemindex].index];
|
||||
|
||||
bool ceiling = fh->z > SortZ;
|
||||
auto svp = &di->SlopeSpriteVertices[ss->slopeindex];
|
||||
|
||||
float hiz = -FLT_MAX;
|
||||
float loz = FLT_MAX;
|
||||
for (int i = 0; i < ss->slopecount; i++)
|
||||
{
|
||||
if (svp[i].z < loz) loz = svp[i].z;
|
||||
if (svp[i].z > hiz) hiz = svp[i].z;
|
||||
}
|
||||
|
||||
if ((hiz > fh->z && loz < fh->z))
|
||||
{
|
||||
// We have to split this sprite
|
||||
auto s = NewFlat(true);
|
||||
*s = *ss;
|
||||
|
||||
SortNode* sort2 = SortNodes.GetNew();
|
||||
memset(sort2, 0, sizeof(SortNode));
|
||||
sort2->itemindex = drawitems.Size() - 1;
|
||||
|
||||
head->AddToLeft(sort);
|
||||
head->AddToRight(sort2);
|
||||
}
|
||||
else if ((loz < fh->z && !ceiling) || (hiz > fh->z && ceiling)) // completely on the left side
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// Lines start-end and fdiv must intersect.
|
||||
inline double CalcIntersectionVertex(HWWall *w1, HWWall * w2)
|
||||
|
@ -579,6 +625,55 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * s
|
|||
}
|
||||
}
|
||||
|
||||
static TArray<float> onside; // static to avoid reallocation.
|
||||
void HWDrawList::SortSlopeIntoWall(HWDrawInfo* di, SortNode* head, SortNode* sort)
|
||||
{
|
||||
HWWall* wh = walls[drawitems[head->itemindex].index];
|
||||
HWFlat* ss = flats[drawitems[sort->itemindex].index];
|
||||
|
||||
auto svp = &di->SlopeSpriteVertices[ss->slopeindex];
|
||||
|
||||
onside.Resize(ss->slopecount);
|
||||
float hiz = -FLT_MAX;
|
||||
float loz = FLT_MAX;
|
||||
for (int i = 0; i < ss->slopecount; i++)
|
||||
{
|
||||
onside[i] = wh->PointOnSide(svp[i].x, svp[i].y);
|
||||
if (onside[i] < loz) loz = onside[i];
|
||||
if (onside[i] > hiz) hiz = onside[i];
|
||||
}
|
||||
|
||||
|
||||
if (fabs(loz) < MIN_EQ && fabs(hiz) < MIN_EQ)
|
||||
{
|
||||
head->AddToEqual(sort);
|
||||
}
|
||||
else if (loz < MIN_EQ && hiz < MIN_EQ)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else if (hiz > -MIN_EQ && loz > -MIN_EQ)
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool drawWithXYBillboard = false;//
|
||||
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool rotated = false;//
|
||||
|
||||
// Proper splitting should not be necessary here and can be added once a map shows up that needs it.
|
||||
if (fabs(hiz) > fabs(loz))
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -588,8 +683,8 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * s
|
|||
|
||||
inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b)
|
||||
{
|
||||
HWSprite * s1= sprites[drawitems[a->itemindex].index];
|
||||
HWSprite * s2= sprites[drawitems[b->itemindex].index];
|
||||
HWFlatOrSprite* s1 = drawitems[a->itemindex].rendertype == DrawType_SPRITE ? (HWFlatOrSprite*)sprites[drawitems[a->itemindex].index] : flats[drawitems[a->itemindex].index];
|
||||
HWFlatOrSprite* s2 = drawitems[b->itemindex].rendertype == DrawType_SPRITE ? (HWFlatOrSprite*)sprites[drawitems[b->itemindex].index] : flats[drawitems[b->itemindex].index];
|
||||
|
||||
if (s1->depth < s2->depth) return 1;
|
||||
if (s1->depth > s2->depth) return -1;
|
||||
|
@ -659,6 +754,10 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head)
|
|||
case DrawType_SPRITE:
|
||||
SortSpriteIntoPlane(head,node);
|
||||
break;
|
||||
|
||||
case DrawType_SLOPE:
|
||||
SortSlopeIntoPlane(di, head, node);
|
||||
break;
|
||||
}
|
||||
node=next;
|
||||
}
|
||||
|
@ -685,6 +784,10 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head)
|
|||
SortSpriteIntoWall(di, head, node);
|
||||
break;
|
||||
|
||||
case DrawType_SLOPE:
|
||||
SortSlopeIntoWall(di, head, node);
|
||||
break;
|
||||
|
||||
case DrawType_FLAT: break;
|
||||
}
|
||||
node=next;
|
||||
|
@ -873,10 +976,10 @@ HWWall *HWDrawList::NewWall()
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
HWFlat *HWDrawList::NewFlat()
|
||||
HWFlat *HWDrawList::NewFlat(bool slopespr)
|
||||
{
|
||||
auto flat = (HWFlat*)RenderDataAllocator.Alloc(sizeof(HWFlat));
|
||||
drawitems.Push(HWDrawItem(DrawType_FLAT,flats.Push(flat)));
|
||||
drawitems.Push(HWDrawItem(slopespr? DrawType_SLOPE : DrawType_FLAT,flats.Push(flat)));
|
||||
return flat;
|
||||
}
|
||||
|
||||
|
@ -901,6 +1004,7 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i
|
|||
{
|
||||
switch(drawitems[i].rendertype)
|
||||
{
|
||||
case DrawType_SLOPE:
|
||||
case DrawType_FLAT:
|
||||
{
|
||||
HWFlat * f= flats[drawitems[i].index];
|
||||
|
|
|
@ -24,6 +24,7 @@ enum HWDrawItemType
|
|||
DrawType_WALL,
|
||||
DrawType_FLAT,
|
||||
DrawType_SPRITE,
|
||||
DrawType_SLOPE,
|
||||
};
|
||||
|
||||
struct HWDrawItem
|
||||
|
@ -89,7 +90,7 @@ public:
|
|||
}
|
||||
|
||||
HWWall *NewWall();
|
||||
HWFlat *NewFlat();
|
||||
HWFlat *NewFlat(bool slopespr = false);
|
||||
HWSprite *NewSprite();
|
||||
void Reset();
|
||||
void SortWallsHorz(HWDrawInfo* di);
|
||||
|
@ -103,8 +104,10 @@ public:
|
|||
void SortPlaneIntoPlane(SortNode * head,SortNode * sort);
|
||||
void SortWallIntoPlane(HWDrawInfo* di, SortNode * head,SortNode * sort);
|
||||
void SortSpriteIntoPlane(SortNode * head,SortNode * sort);
|
||||
void SortSlopeIntoPlane(HWDrawInfo* di, SortNode* head, SortNode* sort);
|
||||
void SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort);
|
||||
void SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort);
|
||||
void SortSlopeIntoWall(HWDrawInfo* di, SortNode* head, SortNode* sort);
|
||||
int CompareSprites(SortNode * a,SortNode * b);
|
||||
SortNode * SortSpriteList(SortNode * head);
|
||||
SortNode * DoSort(HWDrawInfo *di, SortNode * head);
|
||||
|
|
|
@ -94,17 +94,19 @@ void HWDrawInfo::AddMirrorSurface(HWWall *w)
|
|||
void HWDrawInfo::AddFlat(HWFlat *flat)
|
||||
{
|
||||
int list;;
|
||||
bool slopespr = false;
|
||||
|
||||
if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON || checkTranslucentReplacement(flat->texture->GetID(), flat->palette))
|
||||
{
|
||||
// translucent portals go into the translucent border list.
|
||||
list = flat->Sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
||||
slopespr = (flat->Sprite && flat->Sprite->clipdist & TSPR_SLOPESPRITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
list = flat->Sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
||||
}
|
||||
auto newflat = drawlists[list].NewFlat();
|
||||
auto newflat = drawlists[list].NewFlat(slopespr);
|
||||
*newflat = *flat;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,20 +248,32 @@ public:
|
|||
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Common fields needed by the sprite sorter.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class HWFlatOrSprite
|
||||
{
|
||||
public:
|
||||
float depth;
|
||||
tspritetype* Sprite; // for flat sprites.
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// One flat plane in the draw list
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class HWFlat
|
||||
class HWFlat : public HWFlatOrSprite
|
||||
{
|
||||
public:
|
||||
int section;
|
||||
sectortype * sec;
|
||||
tspritetype* Sprite; // for flat sprites.
|
||||
FGameTexture *texture;
|
||||
sectortype* sec;
|
||||
FGameTexture* texture;
|
||||
|
||||
int section;
|
||||
float z; // the z position of the flat (only valid for non-sloped planes)
|
||||
|
||||
PalEntry fade;
|
||||
|
@ -271,10 +283,12 @@ public:
|
|||
FRenderStyle RenderStyle;
|
||||
int iboindex;
|
||||
bool stack;
|
||||
uint8_t plane;
|
||||
short slopecount;
|
||||
FVector2 geoofs;
|
||||
//int vboheight;
|
||||
|
||||
int plane;
|
||||
int slopeindex;
|
||||
int vertindex, vertcount; // this should later use a static vertex buffer, but that'd hinder the development phase, so for now vertex data gets created on the fly.
|
||||
void MakeVertices(HWDrawInfo* di);
|
||||
|
||||
|
@ -298,11 +312,10 @@ public:
|
|||
//==========================================================================
|
||||
|
||||
|
||||
class HWSprite
|
||||
class HWSprite : public HWFlatOrSprite
|
||||
{
|
||||
public:
|
||||
|
||||
tspritetype* Sprite;
|
||||
PalEntry fade;
|
||||
int shade, palette;
|
||||
float visibility;
|
||||
|
@ -312,7 +325,6 @@ public:
|
|||
voxmodel_t* voxel;
|
||||
|
||||
int index;
|
||||
float depth;
|
||||
int vertexindex;
|
||||
|
||||
float x,y,z; // needed for sorting!
|
||||
|
|
|
@ -165,15 +165,27 @@ void HWFlat::MakeVertices(HWDrawInfo* di)
|
|||
if (minofs < 0 && maxofs <= -ONPLANE_THRESHOLD && minofs >= ONPLANE_THRESHOLD) z -= minofs;
|
||||
}
|
||||
}
|
||||
unsigned svi = di->SlopeSpriteVertices.Reserve(4);
|
||||
auto svp = &di->SlopeSpriteVertices[svi];
|
||||
|
||||
auto& vpt = di->Viewpoint;
|
||||
depth = (float)((Sprite->pos.X * (1/16.f) - vpt.Pos.X) * vpt.TanCos + (Sprite->pos.Y * (1 / -16.f) - vpt.Pos.Y) * vpt.TanSin);
|
||||
|
||||
for (unsigned j = 0; j < 4; j++)
|
||||
{
|
||||
svp->SetVertex(pos[j].X * (1 / 16.f), z + ofsz[j] * (1 / -256.f), pos[j].Y * (1 / -16.f));
|
||||
if (!canvas) svp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? 1.f - y : y);
|
||||
else svp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? y : 1.f - y);
|
||||
svp++;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 6; i++)
|
||||
{
|
||||
const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||
int j = indices[i];
|
||||
vp->SetVertex(pos[j].X * (1 / 16.f), z + ofsz[j] * (1 / -256.f), pos[j].Y * (1 / -16.f));
|
||||
if (!canvas) vp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? 1.f - y : y);
|
||||
else vp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? y : 1.f - y);
|
||||
vp++;
|
||||
*vp++ = di->SlopeSpriteVertices[svi + indices[i]];
|
||||
}
|
||||
slopeindex = svi;
|
||||
slopecount = 4;
|
||||
vertindex = ret.second;
|
||||
vertcount = 6;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue