- render free standing wall sprites without depth bias.

Otherwise they can end up badly ordered with walls.
This commit is contained in:
Christoph Oelckers 2021-05-20 12:36:35 +02:00
parent e99567cd70
commit d4eb54d686
4 changed files with 86 additions and 1 deletions

View file

@ -268,6 +268,9 @@ struct spritetype
int16_t extra; int16_t extra;
int16_t detail; int16_t detail;
int time; int time;
int16_t wall;
int8_t wdist;
#if 0 #if 0
// make sure we do not accidentally copy this // make sure we do not accidentally copy this

View file

@ -519,7 +519,6 @@ void HWDrawInfo::RenderScene(FRenderState &state)
drawlists[GLDL_MASKEDWALLSV].SortWallsHorz(this); drawlists[GLDL_MASKEDWALLSV].SortWallsHorz(this);
drawlists[GLDL_MASKEDWALLSH].SortWallsVert(this); drawlists[GLDL_MASKEDWALLSH].SortWallsVert(this);
state.SetDepthBias(-1, -128);
// these lists are only wall and floor sprites - often attached to walls and floors - so they need to be offset from the plane they may be attached to. // these lists are only wall and floor sprites - often attached to walls and floors - so they need to be offset from the plane they may be attached to.
drawlists[GLDL_MASKEDWALLSS].DrawWalls(this, state, false); drawlists[GLDL_MASKEDWALLSS].DrawWalls(this, state, false);
@ -539,6 +538,9 @@ void HWDrawInfo::RenderScene(FRenderState &state)
drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false); drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false);
state.SetColorMask(true); state.SetColorMask(true);
/*
state.SetDepthBias(-1, -128);
state.SetDepthMask(false); state.SetDepthMask(false);
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
state.SetDepthMask(true); state.SetDepthMask(true);
@ -546,6 +548,7 @@ void HWDrawInfo::RenderScene(FRenderState &state)
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
state.SetColorMask(true); state.SetColorMask(true);
state.ClearDepthBias(); state.ClearDepthBias();
*/
drawlists[GLDL_MODELS].Draw(this, state, false); drawlists[GLDL_MODELS].Draw(this, state, false);

View file

@ -133,6 +133,7 @@ public:
{ {
RWF_BLANK = 0, RWF_BLANK = 0,
RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here
RWF_TRANS = 2,
RWF_NORENDER = 8, RWF_NORENDER = 8,
}; };
@ -158,6 +159,7 @@ public:
float ViewDistance; float ViewDistance;
float visibility; float visibility;
int walldist;
short shade, palette; short shade, palette;
PalEntry fade; PalEntry fade;

View file

@ -39,6 +39,72 @@
#include "flatvertices.h" #include "flatvertices.h"
#include "glbackend/glbackend.h" #include "glbackend/glbackend.h"
//==========================================================================
//
//
//
//==========================================================================
static int GetClosestPointOnWall(vec2_t const* const pos, walltype* wal, vec2_t* const n)
{
auto w = wal->pos;
auto d = wall[wal->point2].pos - w;
int64_t i = d.x * ((int64_t)pos->x - w.x) + d.y * ((int64_t)pos->y - w.y);
if (d.x == 0 && d.y == 0)
{
// In Blood's E1M1 this gets triggered for wall 522.
return 1;
}
if (i < 0)
return 1;
int64_t j = (int64_t)d.x * d.x + (int64_t)d.y * d.y;
if (i > j)
return 1;
i = ((i << 15) / j) << 15;
n->x = w.x + ((d.x * i) >> 30);
n->y = w.y + ((d.y * i) >> 30);
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
static int IsOnWall(spritetype* tspr, int height)
{
int dist = 3, closest = -1;
auto sect = &sector[tspr->sectnum];
vec2_t n;
int topz = (tspr->z - ((height * tspr->yrepeat) << 2));
for (int i = sect->wallptr; i < sect->wallptr + sect->wallnum; i++)
{
auto wal = &wall[i];
if ((wal->nextsector == -1 || ((sector[wal->nextsector].ceilingz > topz) ||
sector[wal->nextsector].floorz < tspr->z)) && !GetClosestPointOnWall(&tspr->pos.vec2, wal, &n))
{
int const dst = abs(tspr->x - n.x) + abs(tspr->y - n.y);
if (dst <= dist)
{
dist = dst;
closest = i;
}
}
}
return closest == -1? -1 : dist;
}
//========================================================================== //==========================================================================
// //
// Create vertices for one wall // Create vertices for one wall
@ -169,9 +235,14 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
state.SetNpotEmulation(float(h2) / h, xOffset); state.SetNpotEmulation(float(h2) / h, xOffset);
} }
} }
else if (walldist >= 0 && !(rflags && RWF_TRANS))
{
state.SetDepthBias(-1, -128);
}
RenderWall(di, state, rflags); RenderWall(di, state, rflags);
if (!(rflags && RWF_TRANS)) state.ClearDepthBias();
state.SetNpotEmulation(0.f, 0.f); state.SetNpotEmulation(0.f, 0.f);
state.SetObjectColor(0xffffffff); state.SetObjectColor(0xffffffff);
/* none of these functions is in use. /* none of these functions is in use.
@ -1021,6 +1092,11 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect
auto tex = tileGetTexture(spr->picnum); auto tex = tileGetTexture(spr->picnum);
if (!tex || !tex->isValid()) return; if (!tex || !tex->isValid()) return;
if (spr->owner == 771)
{
int a = 0;
}
seg = nullptr; seg = nullptr;
Sprite = spr; Sprite = spr;
vec2_t pos[2]; vec2_t pos[2];
@ -1067,6 +1143,7 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect
height = (int)tex->GetDisplayHeight(); height = (int)tex->GetDisplayHeight();
topofs = ((int)tex->GetDisplayTopOffset() + spr->yoffset); topofs = ((int)tex->GetDisplayTopOffset() + spr->yoffset);
} }
walldist = IsOnWall(spr, height);
if (spr->cstat & CSTAT_SPRITE_YFLIP) if (spr->cstat & CSTAT_SPRITE_YFLIP)
topofs = -topofs; topofs = -topofs;