From faeb19a485692c1d04b08420c92e5691c644cb3e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Dec 2022 18:32:43 +0100 Subject: [PATCH] =?UTF-8?q?-=20do=20the=20handling=20of=2090=C2=B0=20rotat?= =?UTF-8?q?ed=20wall=20textures=20in=20the=20renderer=20instead=20of=20dup?= =?UTF-8?q?licating=20the=20texture.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aside from less resource use this also works with hires replacement - which the old code was incapable of. --- source/core/gamefuncs.cpp | 30 ------------ source/core/gamefuncs.h | 1 - source/core/rendering/hw_entrypoint.cpp | 2 - source/core/rendering/scene/hw_walls.cpp | 33 ++++++++++---- source/core/textures/buildtiles.cpp | 58 +----------------------- source/core/textures/buildtiles.h | 13 ------ 6 files changed, 24 insertions(+), 113 deletions(-) diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 3ef5336c1..5941ddc0b 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -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 diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index e87902857..d124ea6f6 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -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); diff --git a/source/core/rendering/hw_entrypoint.cpp b/source/core/rendering/hw_entrypoint.cpp index a79b54bf4..c35632856 100644 --- a/source/core/rendering/hw_entrypoint.cpp +++ b/source/core/rendering/hw_entrypoint.cpp @@ -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(), §); if (sect == nullptr) return; diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index efdfa22fb..3a230f85a 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -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()) { diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index a1be4bbb5..eb8178807 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -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 buffer = tex->GetTexture()->Get8BitPixels(false); - TArray 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(); diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index e73b0ddb8..2e1b3b70d 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -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; }