mirror of
https://github.com/DrBeef/Raze.git
synced 2025-02-22 11:41:08 +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;
|
TArray<HWPortal *> Portals;
|
||||||
tspritetype tsprite[MAXSPRITESONSCREEN];
|
tspritetype tsprite[MAXSPRITESONSCREEN];
|
||||||
int spritesortcnt;
|
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.
|
// This is needed by the BSP traverser.
|
||||||
bool multithread;
|
bool multithread;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "hw_renderstate.h"
|
#include "hw_renderstate.h"
|
||||||
#include "hw_drawinfo.h"
|
#include "hw_drawinfo.h"
|
||||||
|
|
||||||
|
#define MIN_EQ (0.0005f)
|
||||||
|
|
||||||
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.
|
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.
|
||||||
|
|
||||||
void ResetRenderDataAllocator()
|
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.
|
// Lines start-end and fdiv must intersect.
|
||||||
inline double CalcIntersectionVertex(HWWall *w1, HWWall * w2)
|
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)
|
inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b)
|
||||||
{
|
{
|
||||||
HWSprite * s1= sprites[drawitems[a->itemindex].index];
|
HWFlatOrSprite* s1 = drawitems[a->itemindex].rendertype == DrawType_SPRITE ? (HWFlatOrSprite*)sprites[drawitems[a->itemindex].index] : flats[drawitems[a->itemindex].index];
|
||||||
HWSprite * s2= sprites[drawitems[b->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;
|
||||||
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:
|
case DrawType_SPRITE:
|
||||||
SortSpriteIntoPlane(head,node);
|
SortSpriteIntoPlane(head,node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DrawType_SLOPE:
|
||||||
|
SortSlopeIntoPlane(di, head, node);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
node=next;
|
node=next;
|
||||||
}
|
}
|
||||||
|
@ -685,6 +784,10 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head)
|
||||||
SortSpriteIntoWall(di, head, node);
|
SortSpriteIntoWall(di, head, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DrawType_SLOPE:
|
||||||
|
SortSlopeIntoWall(di, head, node);
|
||||||
|
break;
|
||||||
|
|
||||||
case DrawType_FLAT: break;
|
case DrawType_FLAT: break;
|
||||||
}
|
}
|
||||||
node=next;
|
node=next;
|
||||||
|
@ -873,10 +976,10 @@ HWWall *HWDrawList::NewWall()
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
HWFlat *HWDrawList::NewFlat()
|
HWFlat *HWDrawList::NewFlat(bool slopespr)
|
||||||
{
|
{
|
||||||
auto flat = (HWFlat*)RenderDataAllocator.Alloc(sizeof(HWFlat));
|
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;
|
return flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,6 +1004,7 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i
|
||||||
{
|
{
|
||||||
switch(drawitems[i].rendertype)
|
switch(drawitems[i].rendertype)
|
||||||
{
|
{
|
||||||
|
case DrawType_SLOPE:
|
||||||
case DrawType_FLAT:
|
case DrawType_FLAT:
|
||||||
{
|
{
|
||||||
HWFlat * f= flats[drawitems[i].index];
|
HWFlat * f= flats[drawitems[i].index];
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum HWDrawItemType
|
||||||
DrawType_WALL,
|
DrawType_WALL,
|
||||||
DrawType_FLAT,
|
DrawType_FLAT,
|
||||||
DrawType_SPRITE,
|
DrawType_SPRITE,
|
||||||
|
DrawType_SLOPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HWDrawItem
|
struct HWDrawItem
|
||||||
|
@ -89,7 +90,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
HWWall *NewWall();
|
HWWall *NewWall();
|
||||||
HWFlat *NewFlat();
|
HWFlat *NewFlat(bool slopespr = false);
|
||||||
HWSprite *NewSprite();
|
HWSprite *NewSprite();
|
||||||
void Reset();
|
void Reset();
|
||||||
void SortWallsHorz(HWDrawInfo* di);
|
void SortWallsHorz(HWDrawInfo* di);
|
||||||
|
@ -103,8 +104,10 @@ public:
|
||||||
void SortPlaneIntoPlane(SortNode * head,SortNode * sort);
|
void SortPlaneIntoPlane(SortNode * head,SortNode * sort);
|
||||||
void SortWallIntoPlane(HWDrawInfo* di, SortNode * head,SortNode * sort);
|
void SortWallIntoPlane(HWDrawInfo* di, SortNode * head,SortNode * sort);
|
||||||
void SortSpriteIntoPlane(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 SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort);
|
||||||
void SortSpriteIntoWall(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);
|
int CompareSprites(SortNode * a,SortNode * b);
|
||||||
SortNode * SortSpriteList(SortNode * head);
|
SortNode * SortSpriteList(SortNode * head);
|
||||||
SortNode * DoSort(HWDrawInfo *di, SortNode * head);
|
SortNode * DoSort(HWDrawInfo *di, SortNode * head);
|
||||||
|
|
|
@ -94,17 +94,19 @@ void HWDrawInfo::AddMirrorSurface(HWWall *w)
|
||||||
void HWDrawInfo::AddFlat(HWFlat *flat)
|
void HWDrawInfo::AddFlat(HWFlat *flat)
|
||||||
{
|
{
|
||||||
int list;;
|
int list;;
|
||||||
|
bool slopespr = false;
|
||||||
|
|
||||||
if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON || checkTranslucentReplacement(flat->texture->GetID(), flat->palette))
|
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.
|
// translucent portals go into the translucent border list.
|
||||||
list = flat->Sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
list = flat->Sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
||||||
|
slopespr = (flat->Sprite && flat->Sprite->clipdist & TSPR_SLOPESPRITE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
list = flat->Sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
list = flat->Sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
||||||
}
|
}
|
||||||
auto newflat = drawlists[list].NewFlat();
|
auto newflat = drawlists[list].NewFlat(slopespr);
|
||||||
*newflat = *flat;
|
*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
|
// One flat plane in the draw list
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
class HWFlat
|
class HWFlat : public HWFlatOrSprite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int section;
|
sectortype* sec;
|
||||||
sectortype * sec;
|
FGameTexture* texture;
|
||||||
tspritetype* Sprite; // for flat sprites.
|
|
||||||
FGameTexture *texture;
|
|
||||||
|
|
||||||
|
int section;
|
||||||
float z; // the z position of the flat (only valid for non-sloped planes)
|
float z; // the z position of the flat (only valid for non-sloped planes)
|
||||||
|
|
||||||
PalEntry fade;
|
PalEntry fade;
|
||||||
|
@ -271,10 +283,12 @@ public:
|
||||||
FRenderStyle RenderStyle;
|
FRenderStyle RenderStyle;
|
||||||
int iboindex;
|
int iboindex;
|
||||||
bool stack;
|
bool stack;
|
||||||
|
uint8_t plane;
|
||||||
|
short slopecount;
|
||||||
FVector2 geoofs;
|
FVector2 geoofs;
|
||||||
//int vboheight;
|
//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.
|
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);
|
void MakeVertices(HWDrawInfo* di);
|
||||||
|
|
||||||
|
@ -298,11 +312,10 @@ public:
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
class HWSprite
|
class HWSprite : public HWFlatOrSprite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
tspritetype* Sprite;
|
|
||||||
PalEntry fade;
|
PalEntry fade;
|
||||||
int shade, palette;
|
int shade, palette;
|
||||||
float visibility;
|
float visibility;
|
||||||
|
@ -312,7 +325,6 @@ public:
|
||||||
voxmodel_t* voxel;
|
voxmodel_t* voxel;
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
float depth;
|
|
||||||
int vertexindex;
|
int vertexindex;
|
||||||
|
|
||||||
float x,y,z; // needed for sorting!
|
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;
|
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++)
|
for (unsigned i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 };
|
const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||||
int j = indices[i];
|
*vp++ = di->SlopeSpriteVertices[svi + 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++;
|
|
||||||
}
|
}
|
||||||
|
slopeindex = svi;
|
||||||
|
slopecount = 4;
|
||||||
vertindex = ret.second;
|
vertindex = ret.second;
|
||||||
vertcount = 6;
|
vertcount = 6;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue