- added GZDoom's texture manager.

It doesn't do anything yet, but it can now be used to manage textures.
This commit is contained in:
Christoph Oelckers 2020-05-24 16:11:10 +02:00
parent e6b94d35ff
commit e985db3d08
9 changed files with 1732 additions and 17 deletions

View file

@ -753,6 +753,7 @@ set (PCH_SOURCES
common/textures/bitmap.cpp common/textures/bitmap.cpp
common/textures/m_png.cpp common/textures/m_png.cpp
common/textures/image.cpp common/textures/image.cpp
common/textures/texturemanager.cpp
common/textures/formats/automaptexture.cpp common/textures/formats/automaptexture.cpp
common/textures/formats/brightmaptexture.cpp common/textures/formats/brightmaptexture.cpp
common/textures/formats/buildtexture.cpp common/textures/formats/buildtexture.cpp

View file

@ -0,0 +1,75 @@
#pragma once
#include "palentry.h"
struct TextureManipulation
{
enum
{
BlendNone = 0,
BlendAlpha = 1,
BlendScreen = 2,
BlendOverlay = 3,
BlendHardLight = 4,
BlendMask = 7,
InvertBit = 8,
ActiveBit = 16, // Must be set for the shader to do something
};
PalEntry AddColor; // Alpha contains the blend flags
PalEntry ModulateColor; // Alpha may contain a multiplier to get higher values than 1.0 without promoting this to 4 full floats.
PalEntry BlendColor;
float DesaturationFactor;
bool CheckIfEnabled() // check if this manipulation is doing something. NoOps do not need to be preserved, unless they override older setttings.
{
if (AddColor != 0 || // this includes a check for the blend mode without which BlendColor is not active
ModulateColor != 0x01ffffff || // 1 in alpha must be the default for a no-op.
DesaturationFactor != 0)
{
AddColor.a |= ActiveBit; // mark as active for the shader's benefit.
return true;
}
return false;
}
void SetTextureModulateColor(int slot, PalEntry rgb)
{
rgb.a = ModulateColor.a;
ModulateColor = rgb;
}
void SetTextureModulateScaleFactor(int slot, int fac)
{
ModulateColor.a = (uint8_t)fac;
}
void SetTextureAdditiveColor(int slot, PalEntry rgb)
{
rgb.a = AddColor.a;
AddColor = rgb;
}
void SetTextureBlendColor(int slot, PalEntry rgb)
{
BlendColor = rgb;
}
void SetTextureDesaturationFactor(int slot, double fac)
{
DesaturationFactor = (float)fac;
}
void SetTextureBlendMode(int slot, int mode)
{
AddColor.a = (AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask);
}
void SetTextureInvert(bool on)
{
AddColor.a |= TextureManipulation::InvertBit;
AddColor.a &= ~TextureManipulation::InvertBit;
}
};

View file

@ -1,8 +1,30 @@
#pragma once #pragma once
enum class ETextureType : uint8_t
{
Any,
Wall,
Flat,
Sprite,
WallPatch,
Build, // no longer used but needs to remain for ZScript
SkinSprite,
Decal,
MiscPatch,
FontChar,
Override, // For patches between TX_START/TX_END
Autopage, // Automap background - used to enable the use of FAutomapTexture
SkinGraphic,
Null,
FirstDefined,
Canvas,
SWCanvas,
};
class FTextureID class FTextureID
{ {
friend class FTextureManager; friend class FTextureManager;
friend void R_InitSpriteDefs();
public: public:
FTextureID() = default; FTextureID() = default;
@ -15,6 +37,7 @@ public:
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; } bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
FTextureID operator +(int offset) throw(); FTextureID operator +(int offset) throw();
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index! int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
void SetIndex(int index) { texnum = index; } // Use this only if you absolutely need the index!
// The switch list needs these to sort the switches by texture index // The switch list needs these to sort the switches by texture index
int operator -(FTextureID other) const { return texnum - other.texnum; } int operator -(FTextureID other) const { return texnum - other.texnum; }
@ -33,4 +56,4 @@ class FSetTextureID : public FTextureID
public: public:
FSetTextureID(int v) : FTextureID(v) {} FSetTextureID(int v) : FTextureID(v) {}
}; };

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,189 @@
#pragma once
#include <stdint.h>
#include "tarray.h"
#include "textureid.h"
#include "basics.h"
#include "sc_man.h"
#include "texmanip.h"
#include "name.h"
class FxAddSub;
class FTexture;
struct BuildInfo;
int PalCheck(int tex);
// Texture manager
class FTextureManager
{
void (*progressFunc)();
friend class FxAddSub; // needs access to do a bounds check on the texture ID.
public:
FTextureManager ();
~FTextureManager ();
private:
int ResolveLocalizedTexture(int texnum);
FTexture *InternalGetTexture(int texnum, bool animate, bool localize, bool palettesubst)
{
if ((unsigned)texnum >= Textures.Size()) return nullptr;
if (animate) texnum = Translation[texnum];
if (localize && Textures[texnum].HasLocalization) texnum = ResolveLocalizedTexture(texnum);
#if 0
if (palettesubst) texnum = PalCheck(texnum);
#endif
return Textures[texnum].Texture;
}
public:
// This only gets used in UI code so we do not need PALVERS handling.
FTexture *GetTextureByName(const char *name, bool animate = false)
{
FTextureID texnum = GetTextureID (name, ETextureType::MiscPatch);
return InternalGetTexture(texnum.GetIndex(), animate, true, false);
}
FTexture *GetTexture(FTextureID texnum, bool animate = false)
{
return InternalGetTexture(texnum.GetIndex(), animate, true, false);
}
// This is the only access function that should be used inside the software renderer.
FTexture *GetPalettedTexture(FTextureID texnum, bool animate)
{
return InternalGetTexture(texnum.GetIndex(), animate, true, true);
}
FTexture *ByIndex(int i, bool animate = false)
{
return InternalGetTexture(i, animate, true, false);
}
FTexture *FindTexture(const char *texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny);
bool OkForLocalization(FTextureID texnum, const char *substitute, int locnum);
void FlushAll();
enum
{
TEXMAN_TryAny = 1,
TEXMAN_Overridable = 2,
TEXMAN_ReturnFirst = 4,
TEXMAN_AllowSkins = 8,
TEXMAN_ShortNameOnly = 16,
TEXMAN_DontCreate = 32,
TEXMAN_Localize = 64
};
enum
{
HIT_Wall = 1,
HIT_Flat = 2,
HIT_Sky = 4,
HIT_Sprite = 8,
HIT_Columnmode = HIT_Wall|HIT_Sky|HIT_Sprite
};
FTextureID CheckForTexture (const char *name, ETextureType usetype, BITFIELD flags=TEXMAN_TryAny);
FTextureID GetTextureID (const char *name, ETextureType usetype, BITFIELD flags=0);
int ListTextures (const char *name, TArray<FTextureID> &list, bool listall = false);
void AddGroup(int wadnum, int ns, ETextureType usetype);
void AddPatches (int lumpnum);
void AddHiresTextures (int wadnum);
void LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build);
void ParseColorization(FScanner& sc);
void ParseTextureDef(int remapLump, FMultipatchTextureBuilder &build);
void SortTexturesByType(int start, int end);
bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2);
void AddLocalizedVariants();
FTextureID CreateTexture (int lumpnum, ETextureType usetype=ETextureType::Any); // Also calls AddTexture
FTextureID AddTexture (FTexture *texture);
FTextureID GetDefaultTexture() const { return DefaultTexture; }
void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build);
void AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build);
void Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo &));
void DeleteAll();
void ReplaceTexture (FTextureID picnum, FTexture *newtexture, bool free);
int NumTextures () const { return (int)Textures.Size(); }
int GuesstimateNumTextures ();
TextureManipulation* GetTextureManipulation(FName name)
{
return tmanips.CheckKey(name);
}
void InsertTextureManipulation(FName cname, TextureManipulation tm)
{
tmanips.Insert(cname, tm);
}
void RemoveTextureManipulation(FName cname)
{
tmanips.Remove(cname);
}
private:
// texture counting
int CountTexturesX ();
int CountLumpTextures (int lumpnum);
void AdjustSpriteOffsets();
// Build tiles
//int CountBuildTiles ();
public:
TArray<uint8_t>& GetNewBuildTileData()
{
BuildTileData.Reserve(1);
return BuildTileData.Last();
}
FTexture* Texture(FTextureID id) { return Textures[id.GetIndex()].Texture; }
void SetTranslation(FTextureID fromtexnum, FTextureID totexnum);
private:
void InitPalettedVersions();
// Switches
struct TextureHash
{
FTexture *Texture;
int HashNext;
bool HasLocalization;
};
enum { HASH_END = -1, HASH_SIZE = 1027 };
TArray<TextureHash> Textures;
TMap<uint64_t, int> LocalizedTextures;
int HashFirst[HASH_SIZE];
FTextureID DefaultTexture;
TArray<int> FirstTextureForFile;
TArray<TArray<uint8_t> > BuildTileData;
TArray<int> Translation;
TMap<FName, TextureManipulation> tmanips;
public:
short sintable[2048]; // for texture warping
enum
{
SINMASK = 2047
};
FTextureID glPart2;
FTextureID glPart;
FTextureID mirrorTexture;
};
extern FTextureManager TexMan;

View file

@ -812,9 +812,10 @@ void tileSetAnim(int tile, const picanm_t& anm)
FTexture* BuildTiles::GetTexture(const char* path) FTexture* BuildTiles::GetTexture(const char* path)
{ {
// let this go away.
auto res = textures.CheckKey(path); auto res = textures.CheckKey(path);
if (res) return *res; if (res) return *res;
auto tex = FTexture::CreateTexture(path); auto tex = FTexture::CreateTexture(path, -1, ETextureType::Override);
if (tex) textures.Insert(path, tex); if (tex) textures.Insert(path, tex);
return tex; return tex;
} }

View file

@ -54,10 +54,13 @@ FTexture *CreateBrightmapTexture(FImageSource*);
// Examines the lump contents to decide what type of texture to create, // Examines the lump contents to decide what type of texture to create,
// and creates the texture. // and creates the texture.
FTexture * FTexture::CreateTexture(const char *name) FTexture * FTexture::CreateTexture(const char *name, int lump, ETextureType useType)
{ {
int lump = fileSystem.FindFile(name); if (lump < 0)
if (lump < 0) return nullptr; {
lump = fileSystem.FindFile(name);
if (lump < 0) return nullptr;
}
auto image = FImageSource::GetImage(lump, false); auto image = FImageSource::GetImage(lump, false);
if (image != nullptr) if (image != nullptr)
{ {

View file

@ -200,17 +200,12 @@ struct FTextureBuffer
class FTexture class FTexture
{ {
friend struct BuildTiles; friend struct BuildTiles;
friend class FTextureManager;
friend bool tileLoad(int tileNum); friend bool tileLoad(int tileNum);
friend const uint8_t* tilePtr(int num); friend const uint8_t* tilePtr(int num);
public: public:
enum UseType : uint8_t static FTexture* CreateTexture(const char* name, int lumpnum, ETextureType useType);
{
Canvas, // camera texture
User // A texture with user-provided image content
};
static FTexture *CreateTexture(const char *name);
virtual ~FTexture (); virtual ~FTexture ();
virtual FImageSource *GetImage() const { return nullptr; } virtual FImageSource *GetImage() const { return nullptr; }
@ -246,8 +241,10 @@ public:
void CheckTrans(unsigned char * buffer, int size, int trans); void CheckTrans(unsigned char * buffer, int size, int trans);
bool ProcessData(unsigned char * buffer, int w, int h, bool ispatch); bool ProcessData(unsigned char * buffer, int w, int h, bool ispatch);
virtual void Reload() {} virtual void Reload() {}
UseType GetUseType() const { return useType; } ETextureType GetUseType() const { return UseType; }
void DeleteHardwareTextures(); void DeleteHardwareTextures();
int GetSourceLump() { return SourceLump; }
void SetUseType(ETextureType use) { UseType = use; }
void SetHardwareTexture(int palid, FHardwareTexture* htex) void SetHardwareTexture(int palid, FHardwareTexture* htex)
{ {
@ -286,12 +283,15 @@ protected:
uint8_t bMasked = true; // Texture (might) have holes uint8_t bMasked = true; // Texture (might) have holes
int8_t bTranslucent = -1; // Does this texture have an active alpha channel? int8_t bTranslucent = -1; // Does this texture have an active alpha channel?
bool skyColorDone = false; bool skyColorDone = false;
UseType useType = User; ETextureType UseType = ETextureType::Any;
PalEntry FloorSkyColor; PalEntry FloorSkyColor;
PalEntry CeilingSkyColor; PalEntry CeilingSkyColor;
TArray<uint8_t> CachedPixels; TArray<uint8_t> CachedPixels;
// Don't waste too much effort on efficient storage here. Polymost performs so many calculations on a single draw call that the minor map lookup hardly matters. // Don't waste too much effort on efficient storage here. Polymost performs so many calculations on a single draw call that the minor map lookup hardly matters.
TMap<int, FHardwareTexture*> HardwareTextures; // Note: These must be deleted by the backend. When the texture manager is taken down it may already be too late to delete them. TMap<int, FHardwareTexture*> HardwareTextures; // Note: These must be deleted by the backend. When the texture manager is taken down it may already be too late to delete them.
bool bFullNameTexture = false;
FTextureID id = FSetTextureID(-1);
int SourceLump = -1;
FTexture (const char *name = NULL); FTexture (const char *name = NULL);
friend struct BuildTiles; friend struct BuildTiles;
@ -309,7 +309,7 @@ public:
bMasked = false; bMasked = false;
bTranslucent = false; bTranslucent = false;
//bNoExpand = true; //bNoExpand = true;
useType = FTexture::Canvas; UseType = ETextureType::Wall;
} }
void NeedUpdate() { bNeedsUpdate = true; } void NeedUpdate() { bNeedsUpdate = true; }

View file

@ -138,7 +138,7 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
FHardwareTexture *hwtex = nullptr; FHardwareTexture *hwtex = nullptr;
if (textype == TT_INDEXED) if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex); hwtex = CreateIndexedTexture(tex);
else if (tex->GetUseType() != FTexture::Canvas) else if (tex->GetUseType() != ETextureType::Canvas)
hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP); hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP);
else else
hwtex = nullptr; hwtex = nullptr;
@ -232,7 +232,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
// Canvas textures must be treated like hightile replacements in the following code. // Canvas textures must be treated like hightile replacements in the following code.
if (picnum < 0) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number. if (picnum < 0) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
auto rep = (picnum >= 0 && hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? TileFiles.FindReplacement(picnum, palette) : nullptr; auto rep = (picnum >= 0 && hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? TileFiles.FindReplacement(picnum, palette) : nullptr;
if (rep || tex->GetUseType() == FTexture::Canvas) if (rep || tex->GetUseType() == ETextureType::Canvas)
{ {
if (usepalette != 0) if (usepalette != 0)
{ {