mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- store the material layers in reference counted pointers in the FGameTexture object.
Reference counting is used because a texture image may be shared by more than one game texture.
This commit is contained in:
parent
70ec20c137
commit
42304d9680
5 changed files with 244 additions and 139 deletions
|
@ -60,17 +60,18 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
||||||
{
|
{
|
||||||
mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2
|
mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2
|
||||||
}
|
}
|
||||||
else if (imgtex->Normal && imgtex->Specular)
|
// Note that the material takes no ownership of the texture!
|
||||||
|
else if (tx->Normal.get() && tx->Specular.get())
|
||||||
{
|
{
|
||||||
for (auto &texture : { imgtex->Normal, imgtex->Specular })
|
for (auto &texture : { tx->Normal.get(), tx->Specular.get() })
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(texture);
|
mTextureLayers.Push(texture);
|
||||||
}
|
}
|
||||||
mShaderIndex = SHADER_Specular;
|
mShaderIndex = SHADER_Specular;
|
||||||
}
|
}
|
||||||
else if (imgtex->Normal && imgtex->Metallic && imgtex->Roughness && imgtex->AmbientOcclusion)
|
else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get())
|
||||||
{
|
{
|
||||||
for (auto &texture : { imgtex->Normal, imgtex->Metallic, imgtex->Roughness, imgtex->AmbientOcclusion })
|
for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() })
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(texture);
|
mTextureLayers.Push(texture);
|
||||||
}
|
}
|
||||||
|
@ -80,27 +81,27 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
||||||
// Note that these layers must present a valid texture even if not used, because empty TMUs in the shader are an undefined condition.
|
// Note that these layers must present a valid texture even if not used, because empty TMUs in the shader are an undefined condition.
|
||||||
tx->CreateDefaultBrightmap();
|
tx->CreateDefaultBrightmap();
|
||||||
auto placeholder = TexMan.GameByIndex(1);
|
auto placeholder = TexMan.GameByIndex(1);
|
||||||
if (imgtex->Brightmap)
|
if (tx->Brightmap.get())
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(imgtex->Brightmap);
|
mTextureLayers.Push(tx->Brightmap.get());
|
||||||
mLayerFlags |= TEXF_Brightmap;
|
mLayerFlags |= TEXF_Brightmap;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(placeholder->GetTexture());
|
mTextureLayers.Push(placeholder->GetTexture());
|
||||||
}
|
}
|
||||||
if (imgtex->Detailmap)
|
if (tx->Detailmap.get())
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(imgtex->Detailmap);
|
mTextureLayers.Push(tx->Detailmap.get());
|
||||||
mLayerFlags |= TEXF_Detailmap;
|
mLayerFlags |= TEXF_Detailmap;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(placeholder->GetTexture());
|
mTextureLayers.Push(placeholder->GetTexture());
|
||||||
}
|
}
|
||||||
if (imgtex->Glowmap)
|
if (tx->Glowmap.get())
|
||||||
{
|
{
|
||||||
mTextureLayers.Push(imgtex->Glowmap);
|
mTextureLayers.Push(tx->Glowmap.get());
|
||||||
mLayerFlags |= TEXF_Glowmap;
|
mLayerFlags |= TEXF_Glowmap;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -113,10 +114,10 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
||||||
const UserShaderDesc &usershader = usershaders[imgtex->shaderindex - FIRST_USER_SHADER];
|
const UserShaderDesc &usershader = usershaders[imgtex->shaderindex - FIRST_USER_SHADER];
|
||||||
if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material
|
if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material
|
||||||
{
|
{
|
||||||
for (auto &texture : imgtex->CustomShaderTextures)
|
for (auto &texture : tx->CustomShaderTextures)
|
||||||
{
|
{
|
||||||
if (texture == nullptr) continue;
|
if (texture == nullptr) continue;
|
||||||
mTextureLayers.Push(texture);
|
mTextureLayers.Push(texture.get());
|
||||||
}
|
}
|
||||||
mShaderIndex = tx->GetShaderIndex();
|
mShaderIndex = tx->GetShaderIndex();
|
||||||
}
|
}
|
||||||
|
@ -167,7 +168,7 @@ FMaterial * FMaterial::ValidateTexture(FGameTexture * gtex, int scaleflags, bool
|
||||||
if (gtex && gtex->isValid())
|
if (gtex && gtex->isValid())
|
||||||
{
|
{
|
||||||
auto tex = gtex->GetTexture();
|
auto tex = gtex->GetTexture();
|
||||||
if (!tex->ShouldExpandSprite()) scaleflags &= ~CTF_Expand;
|
if (!gtex->ShouldExpandSprite()) scaleflags &= ~CTF_Expand;
|
||||||
|
|
||||||
FMaterial *hwtex = tex->Material[scaleflags];
|
FMaterial *hwtex = tex->Material[scaleflags];
|
||||||
if (hwtex == NULL && create)
|
if (hwtex == NULL && create)
|
||||||
|
|
|
@ -288,30 +288,30 @@ int FTexture::CheckRealHeight()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FTexture::AddAutoMaterials()
|
void FGameTexture::AddAutoMaterials()
|
||||||
{
|
{
|
||||||
struct AutoTextureSearchPath
|
struct AutoTextureSearchPath
|
||||||
{
|
{
|
||||||
const char *path;
|
const char *path;
|
||||||
FTexture *FTexture::*pointer;
|
RefCountedPtr<FTexture> FGameTexture::*pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static AutoTextureSearchPath autosearchpaths[] =
|
static AutoTextureSearchPath autosearchpaths[] =
|
||||||
{
|
{
|
||||||
{ "brightmaps/", &FTexture::Brightmap }, // For backwards compatibility, only for short names
|
{ "brightmaps/", &FGameTexture::Brightmap }, // For backwards compatibility, only for short names
|
||||||
{ "materials/brightmaps/", &FTexture::Brightmap },
|
{ "materials/brightmaps/", &FGameTexture::Brightmap },
|
||||||
{ "materials/normalmaps/", &FTexture::Normal },
|
{ "materials/normalmaps/", &FGameTexture::Normal },
|
||||||
{ "materials/specular/", &FTexture::Specular },
|
{ "materials/specular/", &FGameTexture::Specular },
|
||||||
{ "materials/metallic/", &FTexture::Metallic },
|
{ "materials/metallic/", &FGameTexture::Metallic },
|
||||||
{ "materials/roughness/", &FTexture::Roughness },
|
{ "materials/roughness/", &FGameTexture::Roughness },
|
||||||
{ "materials/ao/", &FTexture::AmbientOcclusion }
|
{ "materials/ao/", &FGameTexture::AmbientOcclusion }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int startindex = bFullNameTexture ? 1 : 0;
|
int startindex = Base->bFullNameTexture ? 1 : 0;
|
||||||
FString searchname = Name;
|
FString searchname = GetName();
|
||||||
|
|
||||||
if (bFullNameTexture)
|
if (Base->bFullNameTexture)
|
||||||
{
|
{
|
||||||
auto dot = searchname.LastIndexOf('.');
|
auto dot = searchname.LastIndexOf('.');
|
||||||
auto slash = searchname.LastIndexOf('/');
|
auto slash = searchname.LastIndexOf('/');
|
||||||
|
@ -323,7 +323,7 @@ void FTexture::AddAutoMaterials()
|
||||||
auto &layer = autosearchpaths[i];
|
auto &layer = autosearchpaths[i];
|
||||||
if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
|
if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
|
||||||
{
|
{
|
||||||
FStringf lookup("%s%s%s", layer.path, bFullNameTexture ? "" : "auto/", searchname.GetChars());
|
FStringf lookup("%s%s%s", layer.path, Base->bFullNameTexture ? "" : "auto/", searchname.GetChars());
|
||||||
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true);
|
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true);
|
||||||
if (lump != -1)
|
if (lump != -1)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +351,7 @@ void FGameTexture::CreateDefaultBrightmap()
|
||||||
// Check for brightmaps
|
// Check for brightmaps
|
||||||
if (tex->GetImage() && tex->GetImage()->UseGamePalette() && GPalette.HasGlobalBrightmap &&
|
if (tex->GetImage() && tex->GetImage()->UseGamePalette() && GPalette.HasGlobalBrightmap &&
|
||||||
GetUseType() != ETextureType::Decal && GetUseType() != ETextureType::MiscPatch && GetUseType() != ETextureType::FontChar &&
|
GetUseType() != ETextureType::Decal && GetUseType() != ETextureType::MiscPatch && GetUseType() != ETextureType::FontChar &&
|
||||||
tex->Brightmap == NULL)
|
Brightmap == nullptr)
|
||||||
{
|
{
|
||||||
// May have one - let's check when we use this texture
|
// May have one - let's check when we use this texture
|
||||||
auto texbuf = tex->Get8BitPixels(false);
|
auto texbuf = tex->Get8BitPixels(false);
|
||||||
|
@ -364,7 +364,7 @@ void FGameTexture::CreateDefaultBrightmap()
|
||||||
{
|
{
|
||||||
// Create a brightmap
|
// Create a brightmap
|
||||||
DPrintf(DMSG_NOTIFY, "brightmap created for texture '%s'\n", GetName().GetChars());
|
DPrintf(DMSG_NOTIFY, "brightmap created for texture '%s'\n", GetName().GetChars());
|
||||||
tex->Brightmap = CreateBrightmapTexture(static_cast<FImageTexture*>(tex)->GetImage());
|
Brightmap = CreateBrightmapTexture(tex->GetImage());
|
||||||
tex->bBrightmapChecked = true;
|
tex->bBrightmapChecked = true;
|
||||||
//TexMan.AddGameTexture(MakeGameTexture(tex->Brightmap));
|
//TexMan.AddGameTexture(MakeGameTexture(tex->Brightmap));
|
||||||
return;
|
return;
|
||||||
|
@ -743,21 +743,21 @@ TArray<uint8_t> FTexture::Get8BitPixels(bool alphatex)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
bool FTexture::ShouldExpandSprite()
|
bool FGameTexture::ShouldExpandSprite()
|
||||||
{
|
{
|
||||||
if (bExpandSprite != -1) return bExpandSprite;
|
if (Base->bExpandSprite != -1) return Base->bExpandSprite;
|
||||||
if (isWarped() || isHardwareCanvas() || shaderindex != SHADER_Default)
|
if (isWarped() || isHardwareCanvas() || GetShaderIndex() != SHADER_Default)
|
||||||
{
|
{
|
||||||
bExpandSprite = false;
|
Base->bExpandSprite = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Brightmap != NULL && (GetTexelWidth() != Brightmap->GetTexelWidth() || GetTexelHeight() != Brightmap->GetTexelHeight()))
|
if (Brightmap != NULL && (GetTexelWidth() != Brightmap->GetTexelWidth() || GetTexelHeight() != Brightmap->GetTexelHeight()))
|
||||||
{
|
{
|
||||||
// do not expand if the brightmap's size differs.
|
// do not expand if the brightmap's size differs.
|
||||||
bExpandSprite = false;
|
Base->bExpandSprite = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bExpandSprite = true;
|
Base->bExpandSprite = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,14 +857,14 @@ outl:
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void FTexture::SetupSpriteData()
|
void FGameTexture::SetupSpriteData()
|
||||||
{
|
{
|
||||||
// Since this is only needed for real sprites it gets allocated on demand.
|
// Since this is only needed for real sprites it gets allocated on demand.
|
||||||
// It also allocates from the image memory arena because it has the same lifetime and to reduce maintenance.
|
// It also allocates from the image memory arena because it has the same lifetime and to reduce maintenance.
|
||||||
if (spi == nullptr) spi = (SpritePositioningInfo*)ImageArena.Alloc(2 * sizeof(SpritePositioningInfo));
|
if (Base->spi == nullptr) Base->spi = (SpritePositioningInfo*)ImageArena.Alloc(2 * sizeof(SpritePositioningInfo));
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
auto& spi = this->spi[i];
|
auto& spi = Base->spi[i];
|
||||||
spi.mSpriteU[0] = spi.mSpriteV[0] = 0.f;
|
spi.mSpriteU[0] = spi.mSpriteV[0] = 0.f;
|
||||||
spi.mSpriteU[1] = spi.mSpriteV[1] = 1.f;
|
spi.mSpriteU[1] = spi.mSpriteV[1] = 1.f;
|
||||||
spi.spriteWidth = GetTexelWidth();
|
spi.spriteWidth = GetTexelWidth();
|
||||||
|
@ -872,7 +872,7 @@ void FTexture::SetupSpriteData()
|
||||||
|
|
||||||
if (i == 1 && ShouldExpandSprite())
|
if (i == 1 && ShouldExpandSprite())
|
||||||
{
|
{
|
||||||
spi.mTrimResult = TrimBorders(spi.trim); // get the trim size before adding the empty frame
|
spi.mTrimResult = Base->TrimBorders(spi.trim); // get the trim size before adding the empty frame
|
||||||
spi.spriteWidth += 2;
|
spi.spriteWidth += 2;
|
||||||
spi.spriteHeight += 2;
|
spi.spriteHeight += 2;
|
||||||
}
|
}
|
||||||
|
@ -886,19 +886,19 @@ void FTexture::SetupSpriteData()
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void FTexture::SetSpriteRect()
|
void FGameTexture::SetSpriteRect()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!spi) return;
|
if (!Base->spi) return;
|
||||||
auto leftOffset = GetLeftOffsetHW();
|
auto leftOffset = GetLeftOffsetHW();
|
||||||
auto topOffset = GetTopOffsetHW();
|
auto topOffset = GetTopOffsetHW();
|
||||||
|
|
||||||
float fxScale = (float)Scale.X;
|
float fxScale = (float)Base->Scale.X;
|
||||||
float fyScale = (float)Scale.Y;
|
float fyScale = (float)Base->Scale.Y;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
auto& spi = this->spi[i];
|
auto& spi = Base->spi[i];
|
||||||
|
|
||||||
// mSpriteRect is for positioning the sprite in the scene.
|
// mSpriteRect is for positioning the sprite in the scene.
|
||||||
spi.mSpriteRect.left = -leftOffset / fxScale;
|
spi.mSpriteRect.left = -leftOffset / fxScale;
|
||||||
|
@ -1087,12 +1087,13 @@ FGameTexture::~FGameTexture()
|
||||||
{
|
{
|
||||||
FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump());
|
FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump());
|
||||||
if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr);
|
if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr);
|
||||||
delete wrapped;
|
auto str = GetName();
|
||||||
|
Printf("Deleting texture %s\n", str.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGameTexture::isUserContent() const
|
bool FGameTexture::isUserContent() const
|
||||||
{
|
{
|
||||||
int filenum = fileSystem.GetFileContainer(wrapped->GetSourceLump());
|
int filenum = fileSystem.GetFileContainer(Base->GetSourceLump());
|
||||||
return (filenum > fileSystem.GetMaxIwadNum());
|
return (filenum > fileSystem.GetMaxIwadNum());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1093,9 +1093,6 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI
|
||||||
DeleteAll();
|
DeleteAll();
|
||||||
//if (BuildTileFiles.Size() == 0) CountBuildTiles ();
|
//if (BuildTileFiles.Size() == 0) CountBuildTiles ();
|
||||||
|
|
||||||
// Texture 0 is a dummy texture used to indicate "no texture"
|
|
||||||
auto nulltex = MakeGameTexture(new FImageTexture(nullptr, ""), ETextureType::Null);
|
|
||||||
AddGameTexture (nulltex);
|
|
||||||
// This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture.
|
// This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture.
|
||||||
auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture(), ""), ETextureType::Override);
|
auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture(), ""), ETextureType::Override);
|
||||||
emptytex->SetSize(1, 1);
|
emptytex->SetSize(1, 1);
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "textureid.h"
|
#include "textureid.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "hw_texcontainer.h"
|
#include "hw_texcontainer.h"
|
||||||
|
#include "refcounted.h"
|
||||||
|
|
||||||
// 15 because 0th texture is our texture
|
// 15 because 0th texture is our texture
|
||||||
#define MAX_CUSTOM_HW_SHADER_TEXTURES 15
|
#define MAX_CUSTOM_HW_SHADER_TEXTURES 15
|
||||||
|
@ -235,7 +236,7 @@ struct SpritePositioningInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base texture class
|
// Base texture class
|
||||||
class FTexture
|
class FTexture : public RefCountedBase
|
||||||
{
|
{
|
||||||
friend class FGameTexture; // only for the porting work
|
friend class FGameTexture; // only for the porting work
|
||||||
friend class FTexture;
|
friend class FTexture;
|
||||||
|
@ -253,9 +254,9 @@ public:
|
||||||
static FTexture *CreateTexture(const char *name, int lumpnum, ETextureType UseType);
|
static FTexture *CreateTexture(const char *name, int lumpnum, ETextureType UseType);
|
||||||
virtual ~FTexture ();
|
virtual ~FTexture ();
|
||||||
virtual FImageSource *GetImage() const { return nullptr; }
|
virtual FImageSource *GetImage() const { return nullptr; }
|
||||||
void AddAutoMaterials();
|
|
||||||
void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly);
|
void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly);
|
||||||
void CleanHardwareTextures(bool reallyclean);
|
void CleanHardwareTextures(bool reallyclean);
|
||||||
|
void SetSpriteRect();
|
||||||
|
|
||||||
// These are mainly meant for 2D code which only needs logical information about the texture to position it properly.
|
// These are mainly meant for 2D code which only needs logical information about the texture to position it properly.
|
||||||
int GetDisplayWidth() { int foo = int((Width * 2) / Scale.X); return (foo >> 1) + (foo & 1); }
|
int GetDisplayWidth() { int foo = int((Width * 2) / Scale.X); return (foo >> 1) + (foo & 1); }
|
||||||
|
@ -325,9 +326,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrimBorders(uint16_t* rect);
|
bool TrimBorders(uint16_t* rect);
|
||||||
void SetSpriteRect();
|
|
||||||
bool ShouldExpandSprite();
|
|
||||||
void SetupSpriteData();
|
|
||||||
int GetAreas(FloatRect** pAreas) const;
|
int GetAreas(FloatRect** pAreas) const;
|
||||||
|
|
||||||
// Returns the whole texture, stored in column-major order
|
// Returns the whole texture, stored in column-major order
|
||||||
|
@ -360,19 +358,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
ISoftwareTexture *SoftwareTexture = nullptr;
|
ISoftwareTexture *SoftwareTexture = nullptr;
|
||||||
|
|
||||||
public:
|
|
||||||
// Material layers
|
|
||||||
FTexture *Brightmap = nullptr;
|
|
||||||
FTexture* Detailmap = nullptr;
|
|
||||||
FTexture* Glowmap = nullptr;
|
|
||||||
FTexture *Normal = nullptr; // Normal map texture
|
|
||||||
FTexture *Specular = nullptr; // Specular light texture for the diffuse+normal+specular light model
|
|
||||||
FTexture *Metallic = nullptr; // Metalness texture for the physically based rendering (PBR) light model
|
|
||||||
FTexture *Roughness = nullptr; // Roughness texture for PBR
|
|
||||||
FTexture *AmbientOcclusion = nullptr; // Ambient occlusion texture for PBR
|
|
||||||
|
|
||||||
FTexture *CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES] = { nullptr }; // Custom texture maps for custom hardware shaders
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FString Name;
|
FString Name;
|
||||||
|
@ -623,127 +608,145 @@ public:
|
||||||
// Refactoring helper to allow piece by piece adjustment of the API
|
// Refactoring helper to allow piece by piece adjustment of the API
|
||||||
class FGameTexture
|
class FGameTexture
|
||||||
{
|
{
|
||||||
FTexture *wrapped;
|
friend class FMaterial;
|
||||||
|
|
||||||
|
// Material layers
|
||||||
|
RefCountedPtr<FTexture> Base;
|
||||||
|
RefCountedPtr<FTexture> Brightmap;
|
||||||
|
RefCountedPtr<FTexture> Detailmap;
|
||||||
|
RefCountedPtr<FTexture> Glowmap;
|
||||||
|
RefCountedPtr<FTexture> Normal; // Normal map texture
|
||||||
|
RefCountedPtr<FTexture> Specular; // Specular light texture for the diffuse+normal+specular light model
|
||||||
|
RefCountedPtr<FTexture> Metallic; // Metalness texture for the physically based rendering (PBR) light model
|
||||||
|
RefCountedPtr<FTexture> Roughness; // Roughness texture for PBR
|
||||||
|
RefCountedPtr<FTexture> AmbientOcclusion; // Ambient occlusion texture for PBR
|
||||||
|
RefCountedPtr<FTexture> CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES]; // Custom texture maps for custom hardware shaders
|
||||||
|
|
||||||
int8_t shouldUpscaleFlag = 0; // Without explicit setup, scaling is disabled for a texture.
|
int8_t shouldUpscaleFlag = 0; // Without explicit setup, scaling is disabled for a texture.
|
||||||
ETextureType UseType = ETextureType::Wall; // This texture's primary purpose
|
ETextureType UseType = ETextureType::Wall; // This texture's primary purpose
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGameTexture(FTexture* wrap) : wrapped(wrap) {}
|
FGameTexture(FTexture* wrap) : Base(wrap) {}
|
||||||
~FGameTexture();
|
~FGameTexture();
|
||||||
void CreateDefaultBrightmap();
|
void CreateDefaultBrightmap();
|
||||||
|
void AddAutoMaterials();
|
||||||
|
bool ShouldExpandSprite();
|
||||||
|
void SetupSpriteData();
|
||||||
|
void SetSpriteRect();
|
||||||
|
|
||||||
ETextureType GetUseType() const { return UseType; }
|
ETextureType GetUseType() const { return UseType; }
|
||||||
void SetUpscaleFlag(int what) { shouldUpscaleFlag = what; }
|
void SetUpscaleFlag(int what) { shouldUpscaleFlag = what; }
|
||||||
int GetUpscaleFlag() { return shouldUpscaleFlag; }
|
int GetUpscaleFlag() { return shouldUpscaleFlag; }
|
||||||
|
|
||||||
FTexture* GetTexture() { return wrapped; }
|
FTexture* GetTexture() { return Base.get(); }
|
||||||
int GetSourceLump() const { return wrapped->GetSourceLump(); }
|
int GetSourceLump() const { return Base->GetSourceLump(); }
|
||||||
void SetBrightmap(FGameTexture* tex) { wrapped->Brightmap = tex->GetTexture(); }
|
void SetBrightmap(FGameTexture* tex) { Brightmap = tex->GetTexture(); }
|
||||||
|
|
||||||
double GetDisplayWidth() /*const*/ { return wrapped->GetDisplayWidthDouble(); }
|
double GetDisplayWidth() /*const*/ { return Base->GetDisplayWidthDouble(); }
|
||||||
double GetDisplayHeight() /*const*/ { return wrapped->GetDisplayHeightDouble(); }
|
double GetDisplayHeight() /*const*/ { return Base->GetDisplayHeightDouble(); }
|
||||||
int GetTexelWidth() /*const*/ { return wrapped->GetTexelWidth(); }
|
int GetTexelWidth() /*const*/ { return Base->GetTexelWidth(); }
|
||||||
int GetTexelHeight() /*const*/ { return wrapped->GetTexelHeight(); }
|
int GetTexelHeight() /*const*/ { return Base->GetTexelHeight(); }
|
||||||
int GetTexelLeftOffset(int adjusted = 0) /*const*/ { return wrapped->GetTexelLeftOffset(adjusted); }
|
int GetTexelLeftOffset(int adjusted = 0) /*const*/ { return Base->GetTexelLeftOffset(adjusted); }
|
||||||
int GetTexelTopOffset(int adjusted = 0) /*const*/ { return wrapped->GetTexelTopOffset(adjusted); }
|
int GetTexelTopOffset(int adjusted = 0) /*const*/ { return Base->GetTexelTopOffset(adjusted); }
|
||||||
double GetDisplayLeftOffset(int adjusted = 0) /*const*/ { return wrapped->GetDisplayLeftOffsetDouble(adjusted); }
|
double GetDisplayLeftOffset(int adjusted = 0) /*const*/ { return Base->GetDisplayLeftOffsetDouble(adjusted); }
|
||||||
double GetDisplayTopOffset(int adjusted = 0) /*const*/ { return wrapped->GetDisplayTopOffsetDouble(adjusted); }
|
double GetDisplayTopOffset(int adjusted = 0) /*const*/ { return Base->GetDisplayTopOffsetDouble(adjusted); }
|
||||||
|
// For the hardware renderer. The software renderer's have been offloaded to FSoftwareTexture
|
||||||
|
int GetLeftOffsetHW() { return GetTexelLeftOffset(r_spriteadjustHW); }
|
||||||
|
int GetTopOffsetHW() { return GetTexelTopOffset(r_spriteadjustHW); }
|
||||||
|
|
||||||
bool isValid() const { return UseType != ETextureType::Null; }
|
bool isValid() const { return UseType != ETextureType::Null; }
|
||||||
int isWarped() { return wrapped->isWarped(); }
|
int isWarped() { return Base->isWarped(); }
|
||||||
void SetWarpStyle(int style) { wrapped->bWarped = style; }
|
void SetWarpStyle(int style) { Base->bWarped = style; }
|
||||||
bool isMasked() { return wrapped->isMasked(); }
|
bool isMasked() { return Base->isMasked(); }
|
||||||
bool isHardwareCanvas() const { return wrapped->isHardwareCanvas(); } // There's two here so that this can deal with software canvases in the hardware renderer later.
|
bool isHardwareCanvas() const { return Base->isHardwareCanvas(); } // There's two here so that this can deal with software canvases in the hardware renderer later.
|
||||||
bool isSoftwareCanvas() const { return wrapped->isCanvas(); }
|
bool isSoftwareCanvas() const { return Base->isCanvas(); }
|
||||||
bool isMiscPatch() const { return GetUseType() == ETextureType::MiscPatch; } // only used by the intermission screen to decide whether to tile the background image or not.
|
bool isMiscPatch() const { return GetUseType() == ETextureType::MiscPatch; } // only used by the intermission screen to decide whether to tile the background image or not.
|
||||||
bool isMultiPatch() const { return wrapped->bMultiPatch; }
|
bool isMultiPatch() const { return Base->bMultiPatch; }
|
||||||
bool isFullbrightDisabled() const { return wrapped->isFullbrightDisabled(); }
|
bool isFullbrightDisabled() const { return Base->isFullbrightDisabled(); }
|
||||||
bool isFullbright() const { return wrapped->isFullbright(); }
|
bool isFullbright() const { return Base->isFullbright(); }
|
||||||
bool isFullNameTexture() const { return wrapped->bFullNameTexture; }
|
bool isFullNameTexture() const { return Base->bFullNameTexture; }
|
||||||
bool expandSprites() const { return wrapped->bExpandSprite; }
|
bool expandSprites() const { return Base->bExpandSprite; }
|
||||||
bool useWorldPanning() const { return wrapped->UseWorldPanning(); }
|
bool useWorldPanning() const { return Base->UseWorldPanning(); }
|
||||||
void SetWorldPanning(bool on) { wrapped->SetWorldPanning(on); }
|
void SetWorldPanning(bool on) { Base->SetWorldPanning(on); }
|
||||||
bool allowNoDecals() const { return wrapped->allowNoDecals(); }
|
bool allowNoDecals() const { return Base->allowNoDecals(); }
|
||||||
void SetNoDecals(bool on) { wrapped->bNoDecals = on; }
|
void SetNoDecals(bool on) { Base->bNoDecals = on; }
|
||||||
void SetTranslucent(bool on) { wrapped->bTranslucent = on; }
|
void SetTranslucent(bool on) { Base->bTranslucent = on; }
|
||||||
void SetUseType(ETextureType type) { UseType = type; }
|
void SetUseType(ETextureType type) { UseType = type; }
|
||||||
int GetShaderIndex() const { return wrapped->shaderindex; }
|
int GetShaderIndex() const { return Base->shaderindex; }
|
||||||
float GetShaderSpeed() const { return wrapped->GetShaderSpeed(); }
|
float GetShaderSpeed() const { return Base->GetShaderSpeed(); }
|
||||||
uint16_t GetRotations() const { return wrapped->GetRotations(); }
|
uint16_t GetRotations() const { return Base->GetRotations(); }
|
||||||
void SetRotations(int index) { wrapped->SetRotations(index); }
|
void SetRotations(int index) { Base->SetRotations(index); }
|
||||||
void SetSkyOffset(int ofs) { wrapped->SetSkyOffset(ofs); }
|
void SetSkyOffset(int ofs) { Base->SetSkyOffset(ofs); }
|
||||||
int GetSkyOffset() const { return wrapped->GetSkyOffset(); }
|
int GetSkyOffset() const { return Base->GetSkyOffset(); }
|
||||||
FTextureID GetID() const { return wrapped->GetID(); }
|
FTextureID GetID() const { return Base->GetID(); }
|
||||||
ISoftwareTexture* GetSoftwareTexture() { return wrapped->GetSoftwareTexture(); }
|
ISoftwareTexture* GetSoftwareTexture() { return Base->GetSoftwareTexture(); }
|
||||||
void SetSoftwareTexture(ISoftwareTexture* swtex) { wrapped->SetSoftwareTextue(swtex); }
|
void SetSoftwareTexture(ISoftwareTexture* swtex) { Base->SetSoftwareTextue(swtex); }
|
||||||
void SetScale(DVector2 vec) { wrapped->SetScale(vec); }
|
void SetScale(DVector2 vec) { Base->SetScale(vec); }
|
||||||
const FString& GetName() const { return wrapped->GetName(); }
|
const FString& GetName() const { return Base->GetName(); }
|
||||||
void SetShaderSpeed(float speed) { wrapped->shaderspeed = speed; }
|
void SetShaderSpeed(float speed) { Base->shaderspeed = speed; }
|
||||||
void SetShaderIndex(int index) { wrapped->shaderindex = index; }
|
void SetShaderIndex(int index) { Base->shaderindex = index; }
|
||||||
void SetShaderLayers(MaterialLayers& lay)
|
void SetShaderLayers(MaterialLayers& lay)
|
||||||
{
|
{
|
||||||
// Only update layers that have something defind.
|
// Only update layers that have something defind.
|
||||||
if (lay.Glossiness > -1000) wrapped->Glossiness = lay.Glossiness;
|
if (lay.Glossiness > -1000) Base->Glossiness = lay.Glossiness;
|
||||||
if (lay.SpecularLevel > -1000) wrapped->SpecularLevel = lay.SpecularLevel;
|
if (lay.SpecularLevel > -1000) Base->SpecularLevel = lay.SpecularLevel;
|
||||||
if (lay.Brightmap) wrapped->Brightmap = lay.Brightmap->GetTexture();
|
if (lay.Brightmap) Brightmap = lay.Brightmap->GetTexture();
|
||||||
if (lay.Normal) wrapped->Normal = lay.Normal->GetTexture();
|
if (lay.Normal) Normal = lay.Normal->GetTexture();
|
||||||
if (lay.Specular) wrapped->Specular = lay.Specular->GetTexture();
|
if (lay.Specular) Specular = lay.Specular->GetTexture();
|
||||||
if (lay.Metallic) wrapped->Metallic = lay.Metallic->GetTexture();
|
if (lay.Metallic) Metallic = lay.Metallic->GetTexture();
|
||||||
if (lay.Roughness) wrapped->Roughness = lay.Roughness->GetTexture();
|
if (lay.Roughness) Roughness = lay.Roughness->GetTexture();
|
||||||
if (lay.AmbientOcclusion) wrapped->AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
|
if (lay.AmbientOcclusion) AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
|
||||||
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
|
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
|
||||||
{
|
{
|
||||||
if (lay.CustomShaderTextures[i]) wrapped->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
if (lay.CustomShaderTextures[i]) CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float GetGlossiness() const { return wrapped->Glossiness; }
|
float GetGlossiness() const { return Base->Glossiness; }
|
||||||
float GetSpecularLevel() const { return wrapped->SpecularLevel; }
|
float GetSpecularLevel() const { return Base->SpecularLevel; }
|
||||||
|
|
||||||
void CopySize(FGameTexture* BaseTexture)
|
void CopySize(FGameTexture* BaseTexture)
|
||||||
{
|
{
|
||||||
wrapped->CopySize(BaseTexture->wrapped);
|
Base->CopySize(BaseTexture->Base.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Glowing is a pure material property that should not filter down to the actual texture objects.
|
// Glowing is a pure material property that should not filter down to the actual texture objects.
|
||||||
void GetGlowColor(float* data) { wrapped->GetGlowColor(data); }
|
void GetGlowColor(float* data) { Base->GetGlowColor(data); }
|
||||||
bool isGlowing() const { return wrapped->isGlowing(); }
|
bool isGlowing() const { return Base->isGlowing(); }
|
||||||
bool isAutoGlowing() const { return wrapped->isAutoGlowing(); }
|
bool isAutoGlowing() const { return Base->isAutoGlowing(); }
|
||||||
int GetGlowHeight() const { return wrapped->GetGlowHeight(); }
|
int GetGlowHeight() const { return Base->GetGlowHeight(); }
|
||||||
void SetAutoGlowing() { auto tex = GetTexture(); tex->bAutoGlowing = tex->bGlowing = tex->bFullbright = true; }
|
void SetAutoGlowing() { auto tex = GetTexture(); tex->bAutoGlowing = tex->bGlowing = tex->bFullbright = true; }
|
||||||
void SetGlowHeight(int v) { wrapped->GlowHeight = v; }
|
void SetGlowHeight(int v) { Base->GlowHeight = v; }
|
||||||
void SetFullbright() { wrapped->bFullbright = true; }
|
void SetFullbright() { Base->bFullbright = true; }
|
||||||
void SetDisableFullbright(bool on) { wrapped->bDisableFullbright = on; }
|
void SetDisableFullbright(bool on) { Base->bDisableFullbright = on; }
|
||||||
void SetGlowing(PalEntry color) { auto tex = GetTexture(); tex->bAutoGlowing = false; tex->bGlowing = true; tex->GlowColor = color; }
|
void SetGlowing(PalEntry color) { auto tex = GetTexture(); tex->bAutoGlowing = false; tex->bGlowing = true; tex->GlowColor = color; }
|
||||||
|
|
||||||
bool isUserContent() const;
|
bool isUserContent() const;
|
||||||
void AddAutoMaterials() { wrapped->AddAutoMaterials(); }
|
int CheckRealHeight() { return Base->CheckRealHeight(); }
|
||||||
int CheckRealHeight() { return wrapped->CheckRealHeight(); }
|
bool isSkybox() const { return Base->isSkybox(); }
|
||||||
bool isSkybox() const { return wrapped->isSkybox(); }
|
void SetSize(int x, int y) { Base->SetSize(x, y); }
|
||||||
void SetSize(int x, int y) { wrapped->SetSize(x, y); }
|
void SetDisplaySize(float w, float h) { Base->SetSize((int)w, (int)h); }
|
||||||
void SetDisplaySize(float w, float h) { wrapped->SetSize((int)w, (int)h); }
|
|
||||||
|
|
||||||
void SetSpriteRect() { wrapped->SetSpriteRect(); }
|
const SpritePositioningInfo& GetSpritePositioning(int which) { if (Base->spi == nullptr) SetupSpriteData(); return Base->spi[which]; }
|
||||||
const SpritePositioningInfo& GetSpritePositioning(int which) { if (wrapped->spi == nullptr) wrapped->SetupSpriteData(); return wrapped->spi[which]; }
|
int GetAreas(FloatRect** pAreas) const { return Base->GetAreas(pAreas); }
|
||||||
int GetAreas(FloatRect** pAreas) const { return wrapped->GetAreas(pAreas); }
|
PalEntry GetSkyCapColor(bool bottom) { return Base->GetSkyCapColor(bottom); }
|
||||||
PalEntry GetSkyCapColor(bool bottom) { return wrapped->GetSkyCapColor(bottom); }
|
|
||||||
|
|
||||||
bool GetTranslucency()
|
bool GetTranslucency()
|
||||||
{
|
{
|
||||||
return wrapped->GetTranslucency();
|
return Base->GetTranslucency();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since these properties will later piggyback on existing members of FGameTexture, the accessors need to be here.
|
// Since these properties will later piggyback on existing members of FGameTexture, the accessors need to be here.
|
||||||
FGameTexture *GetSkyFace(int num)
|
FGameTexture *GetSkyFace(int num)
|
||||||
{
|
{
|
||||||
return (isSkybox() ? static_cast<FSkyBox*>(wrapped)->faces[num] : nullptr);
|
return (isSkybox() ? static_cast<FSkyBox*>(Base.get())->faces[num] : nullptr);
|
||||||
}
|
}
|
||||||
bool GetSkyFlip() { return isSkybox() ? static_cast<FSkyBox*>(wrapped)->fliptop : false; }
|
bool GetSkyFlip() { return isSkybox() ? static_cast<FSkyBox*>(Base.get())->fliptop : false; }
|
||||||
|
|
||||||
int GetClampMode(int clampmode)
|
int GetClampMode(int clampmode)
|
||||||
{
|
{
|
||||||
if (GetUseType() == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER;
|
if (GetUseType() == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER;
|
||||||
else if (isHardwareCanvas()) clampmode = CLAMP_CAMTEX;
|
else if (isHardwareCanvas()) clampmode = CLAMP_CAMTEX;
|
||||||
else if ((isWarped() || wrapped->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
|
else if ((isWarped() || Base->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
|
||||||
return clampmode;
|
return clampmode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
103
src/common/utility/refcounted.h
Normal file
103
src/common/utility/refcounted.h
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Simple lightweight reference counting pointer alternative for std::shared_ptr which stores the reference counter in the handled object itself.
|
||||||
|
|
||||||
|
// Base class for handled objects
|
||||||
|
class RefCountedBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void IncRef() { refCount++; }
|
||||||
|
void DecRef() { if (--refCount <= 0) delete this; }
|
||||||
|
private:
|
||||||
|
int refCount = 0;
|
||||||
|
protected:
|
||||||
|
virtual ~RefCountedBase() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The actual pointer object
|
||||||
|
template<class T>
|
||||||
|
class RefCountedPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~RefCountedPtr()
|
||||||
|
{
|
||||||
|
if (ptr) ptr->DecRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCountedPtr() : ptr(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit RefCountedPtr(T* p) : ptr(p)
|
||||||
|
{
|
||||||
|
if (ptr) ptr->IncRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCountedPtr & operator=(const RefCountedPtr& r)
|
||||||
|
{
|
||||||
|
if (ptr != r.ptr)
|
||||||
|
{
|
||||||
|
if (ptr) ptr->DecRef();
|
||||||
|
ptr = r.ptr;
|
||||||
|
if (ptr) ptr->IncRef();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCountedPtr& operator=(T* r)
|
||||||
|
{
|
||||||
|
if (ptr != r)
|
||||||
|
{
|
||||||
|
if (ptr) ptr->DecRef();
|
||||||
|
ptr = r;
|
||||||
|
if (ptr) ptr->IncRef();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCountedPtr & operator=(const RefCountedPtr&& r)
|
||||||
|
{
|
||||||
|
if (ptr) ptr->DecRef();
|
||||||
|
ptr = r.ptr;
|
||||||
|
r.ptr = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(T* p) const
|
||||||
|
{
|
||||||
|
return ptr == p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(T* p) const
|
||||||
|
{
|
||||||
|
return ptr != p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const RefCountedPtr &p) const
|
||||||
|
{
|
||||||
|
return ptr == p.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const RefCountedPtr& p) const
|
||||||
|
{
|
||||||
|
return ptr != p.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator* () const
|
||||||
|
{
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator-> () const
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get() const
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * ptr;
|
||||||
|
};
|
Loading…
Reference in a new issue