mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-15 08:51:24 +00:00
- did a bit of optimization on FGameTexture.
Since all material layers except the brightmaps are relatively rare encounters these were taken out of the main texture object and offloaded to a substructure that is only allocated on demand.
This commit is contained in:
parent
52e5e2f59a
commit
10c552fb66
5 changed files with 110 additions and 46 deletions
|
@ -140,16 +140,27 @@ void FGameTexture::AddAutoMaterials()
|
|||
const char* path;
|
||||
RefCountedPtr<FTexture> FGameTexture::* pointer;
|
||||
};
|
||||
struct AutoTextureSearchPath2
|
||||
{
|
||||
const char* path;
|
||||
RefCountedPtr<FTexture> FMaterialLayers::* pointer;
|
||||
};
|
||||
|
||||
static AutoTextureSearchPath autosearchpaths[] =
|
||||
{
|
||||
{ "brightmaps/", &FGameTexture::Brightmap }, // For backwards compatibility, only for short names
|
||||
{ "materials/brightmaps/", &FGameTexture::Brightmap },
|
||||
{ "materials/normalmaps/", &FGameTexture::Normal },
|
||||
{ "materials/specular/", &FGameTexture::Specular },
|
||||
{ "materials/metallic/", &FGameTexture::Metallic },
|
||||
{ "materials/roughness/", &FGameTexture::Roughness },
|
||||
{ "materials/ao/", &FGameTexture::AmbientOcclusion }
|
||||
};
|
||||
|
||||
static AutoTextureSearchPath2 autosearchpaths2[] =
|
||||
{
|
||||
{ "materials/detailmaps/", &FMaterialLayers::Detailmap },
|
||||
{ "materials/glowmaps/", &FMaterialLayers::Glowmap },
|
||||
{ "materials/normalmaps/", &FMaterialLayers::Normal },
|
||||
{ "materials/specular/", &FMaterialLayers::Specular },
|
||||
{ "materials/metallic/", &FMaterialLayers::Metallic },
|
||||
{ "materials/roughness/", &FMaterialLayers::Roughness },
|
||||
{ "materials/ao/", &FMaterialLayers::AmbientOcclusion }
|
||||
};
|
||||
|
||||
if (flags & GTexf_AutoMaterialsAdded) return; // do this only once
|
||||
|
@ -181,6 +192,24 @@ void FGameTexture::AddAutoMaterials()
|
|||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < countof(autosearchpaths2); i++)
|
||||
{
|
||||
auto& layer = autosearchpaths2[i];
|
||||
if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
|
||||
{
|
||||
FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars());
|
||||
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true);
|
||||
if (lump != -1)
|
||||
{
|
||||
auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
||||
if (bmtex != nullptr)
|
||||
{
|
||||
if (this->Layers == nullptr) this->Layers = std::make_unique<FMaterialLayers>();
|
||||
this->Layers.get()->* (layer.pointer) = bmtex->GetTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
flags |= GTexf_AutoMaterialsAdded;
|
||||
}
|
||||
|
||||
|
@ -283,7 +312,7 @@ bool FGameTexture::ShouldExpandSprite()
|
|||
expandSprite = false;
|
||||
return false;
|
||||
}
|
||||
if (Glowmap != NULL && (Base->GetWidth() != Glowmap->GetWidth() || Base->GetHeight() != Glowmap->GetHeight()))
|
||||
if (Layers && Layers->Glowmap != NULL && (Base->GetWidth() != Layers->Glowmap->GetWidth() || Base->GetHeight() != Layers->Glowmap->GetHeight()))
|
||||
{
|
||||
// same restriction for the glow map
|
||||
expandSprite = false;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include "vectors.h"
|
||||
#include "floatrect.h"
|
||||
#include "refcounted.h"
|
||||
|
@ -62,6 +63,18 @@ enum EGameTexFlags
|
|||
GTexf_NoTrim = 1024, // Don't perform trimming on this texture.
|
||||
};
|
||||
|
||||
struct FMaterialLayers
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
// Refactoring helper to allow piece by piece adjustment of the API
|
||||
class FGameTexture
|
||||
{
|
||||
|
@ -71,14 +84,7 @@ class FGameTexture
|
|||
// Material layers. These are shared so reference counting is used.
|
||||
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
|
||||
std::unique_ptr<FMaterialLayers> Layers;
|
||||
|
||||
FString Name;
|
||||
FTextureID id;
|
||||
|
@ -204,14 +210,25 @@ public:
|
|||
if (lay.Glossiness > -1000) Glossiness = lay.Glossiness;
|
||||
if (lay.SpecularLevel > -1000) SpecularLevel = lay.SpecularLevel;
|
||||
if (lay.Brightmap) Brightmap = lay.Brightmap->GetTexture();
|
||||
if (lay.Normal) Normal = lay.Normal->GetTexture();
|
||||
if (lay.Specular) Specular = lay.Specular->GetTexture();
|
||||
if (lay.Metallic) Metallic = lay.Metallic->GetTexture();
|
||||
if (lay.Roughness) Roughness = lay.Roughness->GetTexture();
|
||||
if (lay.AmbientOcclusion) AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
|
||||
|
||||
bool needlayers = (lay.Normal || lay.Specular || lay.Metallic || lay.Roughness || lay.AmbientOcclusion);
|
||||
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES && !needlayers; i++)
|
||||
{
|
||||
if (lay.CustomShaderTextures[i]) needlayers = true;
|
||||
}
|
||||
if (needlayers)
|
||||
{
|
||||
Layers = std::make_unique<FMaterialLayers>();
|
||||
|
||||
if (lay.Normal) Layers->Normal = lay.Normal->GetTexture();
|
||||
if (lay.Specular) Layers->Specular = lay.Specular->GetTexture();
|
||||
if (lay.Metallic) Layers->Metallic = lay.Metallic->GetTexture();
|
||||
if (lay.Roughness) Layers->Roughness = lay.Roughness->GetTexture();
|
||||
if (lay.AmbientOcclusion) Layers->AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
|
||||
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
|
||||
{
|
||||
if (lay.CustomShaderTextures[i]) CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
||||
if (lay.CustomShaderTextures[i]) Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
float GetGlossiness() const { return Glossiness; }
|
||||
|
@ -306,15 +323,22 @@ public:
|
|||
void GetLayers(TArray<FTexture*>& layers)
|
||||
{
|
||||
layers.Clear();
|
||||
for (auto tex : { Base.get(), Brightmap.get(), Detailmap.get(), Glowmap.get(), Normal.get(), Specular.get(), Metallic.get(), Roughness.get(), AmbientOcclusion.get() })
|
||||
for (auto tex : { Base.get(), Brightmap.get() })
|
||||
{
|
||||
if (tex != nullptr) layers.Push(tex);
|
||||
}
|
||||
for (auto& tex : CustomShaderTextures)
|
||||
if (Layers)
|
||||
{
|
||||
for (auto tex : { Layers->Detailmap.get(), Layers->Glowmap.get(), Layers->Normal.get(), Layers->Specular.get(), Layers->Metallic.get(), Layers->Roughness.get(), Layers->AmbientOcclusion.get() })
|
||||
{
|
||||
if (tex != nullptr) layers.Push(tex);
|
||||
}
|
||||
for (auto& tex : Layers->CustomShaderTextures)
|
||||
{
|
||||
if (tex != nullptr) layers.Push(tex.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FVector2 GetDetailScale() const
|
||||
{
|
||||
|
@ -335,28 +359,34 @@ public:
|
|||
}
|
||||
FTexture* GetGlowmap()
|
||||
{
|
||||
return Glowmap.get();
|
||||
if (!Layers) return nullptr;
|
||||
return Layers->Glowmap.get();
|
||||
}
|
||||
FTexture* GetDetailmap()
|
||||
{
|
||||
return Detailmap.get();
|
||||
if (!Layers) return nullptr;
|
||||
return Layers->Detailmap.get();
|
||||
}
|
||||
|
||||
void SetGlowmap(FTexture *T)
|
||||
{
|
||||
Glowmap = T;
|
||||
if (!Layers) Layers = std::make_unique<FMaterialLayers>();
|
||||
Layers->Glowmap = T;
|
||||
}
|
||||
void SetDetailmap(FTexture* T)
|
||||
{
|
||||
Detailmap = T;
|
||||
if (!Layers) Layers = std::make_unique<FMaterialLayers>();
|
||||
Layers->Detailmap = T;
|
||||
}
|
||||
void SetNormalmap(FTexture* T)
|
||||
{
|
||||
Normal = T;
|
||||
if (!Layers) Layers = std::make_unique<FMaterialLayers>();
|
||||
Layers->Normal = T;
|
||||
}
|
||||
void SetSpecularmap(FTexture* T)
|
||||
{
|
||||
Specular = T;
|
||||
if (!Layers) Layers = std::make_unique<FMaterialLayers>();
|
||||
Layers->Specular = T;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -79,17 +79,17 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2
|
||||
}
|
||||
// Note that the material takes no ownership of the texture!
|
||||
else if (tx->Normal.get() && tx->Specular.get())
|
||||
else if (tx->Layers && tx->Layers->Normal.get() && tx->Layers->Specular.get())
|
||||
{
|
||||
for (auto &texture : { tx->Normal.get(), tx->Specular.get() })
|
||||
for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Specular.get() })
|
||||
{
|
||||
mTextureLayers.Push({ texture, 0, -1 });
|
||||
}
|
||||
mShaderIndex = SHADER_Specular;
|
||||
}
|
||||
else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get())
|
||||
else if (tx->Layers && tx->Layers->Normal.get() && tx->Layers->Metallic.get() && tx->Layers->Roughness.get() && tx->Layers->AmbientOcclusion.get())
|
||||
{
|
||||
for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() })
|
||||
for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Metallic.get(), tx->Layers->Roughness.get(), tx->Layers->AmbientOcclusion.get() })
|
||||
{
|
||||
mTextureLayers.Push({ texture, 0, -1 });
|
||||
}
|
||||
|
@ -108,18 +108,18 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
{
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 });
|
||||
}
|
||||
if (tx->Detailmap.get())
|
||||
if (tx->Layers && tx->Layers->Detailmap.get())
|
||||
{
|
||||
mTextureLayers.Push({ tx->Detailmap.get(), 0, CLAMP_NONE });
|
||||
mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE });
|
||||
mLayerFlags |= TEXF_Detailmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 });
|
||||
}
|
||||
if (tx->Glowmap.get())
|
||||
if (tx->Layers && tx->Layers->Glowmap.get())
|
||||
{
|
||||
mTextureLayers.Push({ tx->Glowmap.get(), scaleflags, -1 });
|
||||
mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1 });
|
||||
mLayerFlags |= TEXF_Glowmap;
|
||||
}
|
||||
else
|
||||
|
@ -133,9 +133,9 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
if (index >= FIRST_USER_SHADER)
|
||||
{
|
||||
const UserShaderDesc& usershader = usershaders[index - FIRST_USER_SHADER];
|
||||
if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material
|
||||
if (tx->Layers && usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material
|
||||
{
|
||||
for (auto& texture : tx->CustomShaderTextures)
|
||||
for (auto& texture : tx->Layers->CustomShaderTextures)
|
||||
{
|
||||
if (texture == nullptr) continue;
|
||||
mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable.
|
||||
|
|
|
@ -426,7 +426,7 @@ FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohas
|
|||
hash = -1;
|
||||
}
|
||||
|
||||
TextureHash hasher = { texture, -1, -1, -1, hash };
|
||||
TextureDescriptor hasher = { texture, -1, -1, -1, hash };
|
||||
int trans = Textures.Push (hasher);
|
||||
Translation.Push (trans);
|
||||
if (bucket >= 0) HashFirst[bucket] = trans;
|
||||
|
@ -1150,7 +1150,7 @@ void FTextureManager::AddLocalizedVariants()
|
|||
uint32_t langid = MAKE_ID(lang[0], lang[1], lang[2], 0);
|
||||
uint64_t comboid = (uint64_t(langid) << 32) | origTex.GetIndex();
|
||||
LocalizedTextures.Insert(comboid, tex.GetIndex());
|
||||
Textures[origTex.GetIndex()].HasLocalization = true;
|
||||
Textures[origTex.GetIndex()].Flags |= TEXFLAG_HASLOCALIZATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@ private:
|
|||
{
|
||||
if ((unsigned)texnum >= Textures.Size()) return -1;
|
||||
if (animate) texnum = Translation[texnum];
|
||||
if (localize && Textures[texnum].HasLocalization) texnum = ResolveLocalizedTexture(texnum);
|
||||
if (localize && Textures[texnum].Flags & TEXFLAG_HASLOCALIZATION) texnum = ResolveLocalizedTexture(texnum);
|
||||
return texnum;
|
||||
}
|
||||
|
||||
|
@ -183,17 +183,22 @@ private:
|
|||
|
||||
// Switches
|
||||
|
||||
struct TextureHash
|
||||
struct TextureDescriptor
|
||||
{
|
||||
FGameTexture* Texture;
|
||||
int Paletted; // redirection to paletted variant
|
||||
int FrontSkyLayer; // and front sky layer,
|
||||
int RawTexture;
|
||||
int HashNext;
|
||||
bool HasLocalization;
|
||||
uint64_t Flags;
|
||||
};
|
||||
enum : uint64_t
|
||||
{
|
||||
TEXFLAG_HASLOCALIZATION = 1,
|
||||
TEXFLAG_FIRSTUSER = 65536, // this leaves 16 flags to the texture manager and 48 flags to the user
|
||||
};
|
||||
enum { HASH_END = -1, HASH_SIZE = 1027 };
|
||||
TArray<TextureHash> Textures;
|
||||
TArray<TextureDescriptor> Textures;
|
||||
TMap<uint64_t, int> LocalizedTextures;
|
||||
int HashFirst[HASH_SIZE];
|
||||
FTextureID DefaultTexture;
|
||||
|
|
Loading…
Reference in a new issue