- do the handling of 90° rotated wall textures in the renderer instead of duplicating the texture.

Aside from less resource use this also works with hires replacement - which the old code was incapable of.
This commit is contained in:
Christoph Oelckers 2022-12-05 18:32:43 +01:00
parent 6a690849e6
commit faeb19a485
6 changed files with 24 additions and 113 deletions

View file

@ -344,36 +344,6 @@ EClose IsCloseToWall(const DVector2& point, walltype* wal, double maxdist)
return IsCloseToLine(point, wal->pos, wal->point2Wall()->pos, maxdist);
}
//==========================================================================
//
// Check if some walls are set to use rotated textures.
// Ideally this should just have been done with texture rotation,
// but the effects on the render code would be too severe due to the alignment mess.
//
//==========================================================================
void checkRotatedWalls()
{
for (auto& w : wall)
{
if (w.cstat & CSTAT_WALL_ROTATE_90)
{
int picnum = w.picnum;
tileUpdatePicnum(&picnum);
auto& tile = RotTile(picnum);
if (tile.newtile == -1 && tile.owner == -1)
{
tile.newtile = TileFiles.tileCreateRotated(picnum);
assert(tile.newtile != -1);
RotTile(tile.newtile).owner = picnum;
}
}
}
}
//==========================================================================
//
// check if two sectors share a wall connection

View file

@ -298,7 +298,6 @@ enum class EClose
EClose IsCloseToLine(const DVector2& vect, const DVector2& start, const DVector2& end, double walldist);
EClose IsCloseToWall(const DVector2& vect, walltype* wal, double walldist);
void checkRotatedWalls();
bool sectorsConnected(int sect1, int sect2);
int32_t inside(double x, double y, const sectortype* sect);
int insidePoly(double x, double y, const DVector2* points, int count);

View file

@ -307,8 +307,6 @@ void animatecamsprite(double s);
void render_drawrooms(DCoreActor* playersprite, const DVector3& position, sectortype* sect, const DRotator& angles, double interpfrac, float fov)
{
checkRotatedWalls();
updatesector(position.XY(), &sect);
if (sect == nullptr) return;

View file

@ -197,13 +197,16 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
state.EnableTexture(false);
}
int h = (int)texture->GetDisplayHeight();
int h2 = 1 << sizeToBits(h);
if (h2 < h) h2 *= 2;
if (h != h2)
if (!(seg->cstat & CSTAT_WALL_ROTATE_90))
{
float xOffset = 1.f / texture->GetDisplayWidth();
state.SetNpotEmulation(float(h2) / h, xOffset);
int h = (int)texture->GetDisplayHeight();
int h2 = 1 << sizeToBits(h);
if (h2 < h) h2 *= 2;
if (h != h2)
{
float xOffset = 1.f / texture->GetDisplayWidth();
state.SetNpotEmulation(float(h2) / h, xOffset);
}
}
RenderWall(di, state, rflags);
}
@ -412,6 +415,15 @@ void HWWall::PutWall(HWDrawInfo *di, bool translucent)
ViewDistance = (di->Viewpoint.Pos.XY() - DVector2((glseg.x1 + glseg.x2) * 0.5f, (glseg.y1 + glseg.y2) * 0.5f)).LengthSquared();
}
if (seg && (seg->cstat & CSTAT_WALL_ROTATE_90))
{
float f;
// rotate 90° clockwise. The coordinates have already been set up in rotated space, so all we need to do here is swap u and v and then negate the new v.
f = tcs[UPLFT].u; tcs[UPLFT].u = tcs[UPLFT].v; tcs[UPLFT].v = 1.f - f;
f = tcs[LOLFT].u; tcs[LOLFT].u = tcs[LOLFT].v; tcs[LOLFT].v = 1.f - f;
f = tcs[UPRGT].u; tcs[UPRGT].u = tcs[UPRGT].v; tcs[UPRGT].v = 1.f - f;
f = tcs[LORGT].u; tcs[LORGT].u = tcs[LORGT].v; tcs[LORGT].v = 1.f - f;
}
if (texture->isHardwareCanvas())
{
tcs[UPLFT].v = 1.f - tcs[UPLFT].v;
@ -743,6 +755,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r
float tw = texture->GetDisplayWidth();
float th = texture->GetDisplayHeight();
if (wal->cstat & CSTAT_WALL_ROTATE_90) std::swap(tw, th);
int pow2size = 1 << sizeToBits(th);
if (pow2size < th) pow2size *= 2;
float ypanning = refwall->ypan_ ? pow2size * refwall->ypan_ / (256.0f * th) : 0;
@ -999,7 +1012,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec
int tilenum = ((wal->cstat & CSTAT_WALL_1WAY) && wal->nextwall != -1) ? wal->overpicnum : wal->picnum;
gotpic.Set(tilenum);
tileUpdatePicnum(&tilenum, (wal->cstat & CSTAT_WALL_ROTATE_90));
tileUpdatePicnum(&tilenum);
texture = tileGetTexture(tilenum);
if (texture && texture->isValid())
{
@ -1037,7 +1050,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec
{
int tilenum = wal->picnum;
gotpic.Set(tilenum);
tileUpdatePicnum(&tilenum, (wal->cstat & CSTAT_WALL_ROTATE_90));
tileUpdatePicnum(&tilenum);
texture = tileGetTexture(tilenum);
if (texture && texture->isValid())
{
@ -1050,7 +1063,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec
{
int tilenum = wal->overpicnum;
gotpic.Set(tilenum);
tileUpdatePicnum(&tilenum, (wal->cstat & CSTAT_WALL_ROTATE_90));
tileUpdatePicnum(&tilenum);
texture = tileGetTexture(tilenum);
if (texture && texture->isValid())
{
@ -1076,7 +1089,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec
auto w = (wal->cstat & CSTAT_WALL_BOTTOM_SWAP) ? backwall : wal;
int tilenum = w->picnum;
gotpic.Set(tilenum);
tileUpdatePicnum(&tilenum, (w->cstat & CSTAT_WALL_ROTATE_90));
tileUpdatePicnum(&tilenum);
texture = tileGetTexture(tilenum);
if (texture && texture->isValid())
{

View file

@ -143,7 +143,6 @@ void BuildTiles::Init()
{
tile.texture = Placeholder;
tile.picanm = {};
tile.RotTile = { -1,-1 };
tile.replacement = ReplacementType::Art;
tile.alphaThreshold = 0.5;
tile.hiofs = {};
@ -604,7 +603,7 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
pixel = remap[pixel];
}
}
tex = MakeGameTexture(new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight())), "", ETextureType::Any);
tex = MakeGameTexture(new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight())), FStringf("#%05d", tile), ETextureType::Any);
picanm = &TileFiles.tiledata[tile].picanm;
TileFiles.AddTile(tile, tex);
}
@ -655,61 +654,6 @@ void tileSetDummy(int tile, int width, int height)
//
//==========================================================================
int BuildTiles::findUnusedTile(void)
{
static int lastUnusedTile = MAXUSERTILES - 1;
for (; lastUnusedTile >= 0; --lastUnusedTile)
{
auto tex = tileGetTexture(lastUnusedTile);
if (!tex || !tex->isValid()) return lastUnusedTile;
}
return -1;
}
//==========================================================================
//
// fixme: This *really* needs to be done by rotating the texture coordinates,
// not by creating an entirely new texture.
// Unfortunately it's in all the wrong place in the rendering code so it
// has to wait for later.
//
//==========================================================================
int BuildTiles::tileCreateRotated(int tileNum)
{
if ((unsigned)tileNum >= MAXTILES) return tileNum;
auto tex = tileGetTexture(tileNum);
if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return tileNum;
TArray<uint8_t> buffer = tex->GetTexture()->Get8BitPixels(false);
TArray<uint8_t> dbuffer(tex->GetTexelWidth() * tex->GetTexelHeight(), true);
auto src = buffer.Data();
auto dst = dbuffer.Data();
auto width = tex->GetTexelWidth();
auto height = tex->GetTexelHeight();
for (int x = 0; x < width; ++x)
{
int xofs = width - x - 1;
int yofs = height * x;
for (int y = 0; y < height; ++y)
*(dst + y * width + xofs) = *(src + y + yofs);
}
auto dtex = MakeGameTexture(new FImageTexture(new FLooseTile(dbuffer, tex->GetTexelHeight(), tex->GetTexelWidth())), "", ETextureType::Override);
int index = findUnusedTile();
TileFiles.AddTile(index, dtex);
return index;
}
//==========================================================================
//
//
//
//==========================================================================
void BuildTiles::CloseAll()
{
ArtFiles.DeleteAndClear();

View file

@ -278,7 +278,6 @@ struct TileDesc
FGameTexture* texture; // the currently active tile
RawCacheNode rawCache; // this is needed for hitscan testing to avoid reloading the texture each time.
picanm_t picanm; // animation descriptor
rottile_t RotTile;// = { -1,-1 };
ReplacementType replacement;
float alphaThreshold;
int tileflags;
@ -370,8 +369,6 @@ struct BuildTiles
uint8_t* tileMakeWritable(int num);
uint8_t* tileCreate(int tilenum, int width, int height);
uint8_t* tileGet(int tilenum);
int findUnusedTile(void);
int tileCreateRotated(int owner);
void InvalidateTile(int num);
void MakeCanvas(int tilenum, int width, int height);
};
@ -455,13 +452,6 @@ inline int tileTopOffset(int num)
return (int)TileFiles.tiledata[num].texture->GetDisplayTopOffset();
}
inline rottile_t& RotTile(int tile)
{
assert(tile < MAXTILES);
return TileFiles.tiledata[tile].RotTile;
}
int tileAnimateOfs(int tilenum, int randomize = -1);
inline void tileUpdatePicnum(int* const tileptr, bool mayrotate = false, int randomize = -1)
@ -470,9 +460,6 @@ inline void tileUpdatePicnum(int* const tileptr, bool mayrotate = false, int ran
if (picanm[tile].type())
tile += tileAnimateOfs(tile, randomize);
if (mayrotate && RotTile(tile).newtile != -1)
tile = RotTile(tile).newtile;
}