- Backend update from Raze.

Mainly optimizations for the sound system and texture manager.
This commit is contained in:
Christoph Oelckers 2022-12-18 16:19:18 +01:00
parent 79a38f1f3a
commit 941c0850ba
30 changed files with 323 additions and 261 deletions

View file

@ -193,7 +193,7 @@ public:
TArray<RenderCommand> mData;
int Width, Height;
bool isIn2D;
bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades)
bool locked = false; // prevents clearing of the data so it can be reused multiple times (useful for screen fades)
float screenFade = 1.f;
DVector2 offset;
DMatrix3x3 transform;

View file

@ -1465,21 +1465,11 @@ void SoundEngine::Reset()
FSoundID SoundEngine::FindSound(const char* logicalname)
{
int i;
if (logicalname != NULL)
{
i = S_sfx[MakeKey(logicalname) % S_sfx.Size()].index;
while ((i != 0) && stricmp(S_sfx[i].name, logicalname))
i = S_sfx[i].next;
return FSoundID::fromInt(i);
}
else
{
return NO_SOUND;
}
if (!logicalname) return NO_SOUND;
FName name(logicalname, true);
if (name == NAME_None) return NO_SOUND;
auto p = SoundMap.CheckKey(name);
return p ? *p : NO_SOUND;
}
FSoundID SoundEngine::FindSoundByResID(int resid)
@ -1497,12 +1487,35 @@ FSoundID SoundEngine::FindSoundByResID(int resid)
//==========================================================================
FSoundID SoundEngine::FindSoundNoHash(const char* logicalname)
{
if (!logicalname) return NO_SOUND;
FName name(logicalname, true);
if (name == NAME_None) return NO_SOUND;
for (unsigned i = 1; i < S_sfx.Size(); i++)
{
if (S_sfx[i].name == name)
{
return FSoundID::fromInt(i);
}
}
return NO_SOUND;
}
//==========================================================================
//
// S_FindSoundByResIDNoHash
//
// same with resource IDs.
//==========================================================================
FSoundID SoundEngine::FindSoundByResIDNoHash(int resid)
{
unsigned int i;
for (i = 1; i < S_sfx.Size(); i++)
{
if (stricmp(S_sfx[i].name, logicalname) == 0)
if (S_sfx[i].ResourceId == resid)
{
return FSoundID::fromInt(i);
}
@ -1544,14 +1557,11 @@ FSoundID SoundEngine::AddSoundLump(const char* logicalname, int lump, int Curren
newsfx.name = logicalname;
newsfx.lumpnum = lump;
newsfx.next = 0;
newsfx.PitchMask = CurrentPitchMask;
newsfx.NearLimit = nearlimit;
newsfx.ResourceId = resid;
newsfx.bTentative = false;
auto id = FSoundID::fromInt(S_sfx.Size() - 1);
if (resid >= 0) ResIdMap[resid] = id;
return id;
}
@ -1565,12 +1575,12 @@ FSoundID SoundEngine::AddSoundLump(const char* logicalname, int lump, int Curren
// an associated lump is created.
//==========================================================================
FSoundID SoundEngine::FindSoundTentative(const char* name)
FSoundID SoundEngine::FindSoundTentative(const char* name, int nearlimit)
{
auto id = FindSoundNoHash(name);
if (id == NO_SOUND)
{
id = AddSoundLump(name, -1, 0);
id = AddSoundLump(name, -1, 0, -1, nearlimit);
S_sfx[id.index()].bTentative = true;
}
return id;
@ -1675,25 +1685,21 @@ FSoundID SoundEngine::PickReplacement(FSoundID refid)
void SoundEngine::HashSounds()
{
unsigned int i;
unsigned int j;
unsigned int size;
S_sfx.ShrinkToFit();
size = S_sfx.Size();
SoundMap.Clear();
ResIdMap.Clear();
// Mark all buckets as empty
for (i = 0; i < size; i++)
S_sfx[i].index = 0;
// Now set up the chains
for (i = 1; i < size; i++)
for (unsigned i = 1; i < S_sfx.Size(); i++)
{
j = MakeKey(S_sfx[i].name) % size;
S_sfx[i].next = S_sfx[j].index;
S_sfx[j].index = i;
SoundMap.Insert(S_sfx[i].name, FSoundID::fromInt(i));
if (S_sfx[i].ResourceId != -1)
{
ResIdMap.Insert(S_sfx[i].ResourceId, FSoundID::fromInt(i));
}
}
S_rnd.ShrinkToFit();
}
void SoundEngine::AddRandomSound(FSoundID Owner, TArray<FSoundID> list)
@ -1824,26 +1830,20 @@ void S_SetSoundPaused(int state)
if ((state || i_soundinbackground) && !pauseext)
{
if (paused == 0)
S_ResumeSound(true);
if (GSnd != nullptr)
{
S_ResumeSound(true);
if (GSnd != nullptr)
{
GSnd->SetInactive(SoundRenderer::INACTIVE_Active);
}
GSnd->SetInactive(SoundRenderer::INACTIVE_Active);
}
}
else
{
if (paused == 0)
S_PauseSound(false, true);
if (GSnd != nullptr)
{
S_PauseSound(false, true);
if (GSnd != nullptr)
{
GSnd->SetInactive(gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL ?
SoundRenderer::INACTIVE_Complete :
SoundRenderer::INACTIVE_Mute);
}
GSnd->SetInactive(gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL ?
SoundRenderer::INACTIVE_Complete :
SoundRenderer::INACTIVE_Mute);
}
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "i_sound.h"
#include "name.h"
enum
{
@ -78,10 +79,9 @@ constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1);
// A non-null data means the sound has been loaded.
SoundHandle data{};
FString name; // [RH] Sound name defined in SNDINFO
FName name; // [RH] Sound name defined in SNDINFO
int lumpnum = sfx_empty; // lump number of sfx
unsigned int next = -1, index = 0; // [RH] For hashing
float Volume = 1.f;
int ResourceId = -1; // Resource ID as implemented by Blood. Not used by Doom but added for completeness.
@ -192,6 +192,7 @@ protected:
TArray<sfxinfo_t> S_sfx;
FRolloffInfo S_Rolloff{};
TArray<uint8_t> S_SoundCurve;
TMap<FName, FSoundID> SoundMap;
TMap<int, FSoundID> ResIdMap;
TArray<FRandomSoundList> S_rnd;
bool blockNewSounds = false;
@ -390,9 +391,10 @@ public:
FSoundID FindSound(const char* logicalname);
FSoundID FindSoundByResID(int rid);
FSoundID FindSoundNoHash(const char* logicalname);
FSoundID FindSoundByResIDNoHash(int rid);
FSoundID FindSoundByLump(int lump);
virtual FSoundID AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2);
FSoundID FindSoundTentative(const char* name);
FSoundID FindSoundTentative(const char* name, int nearlimit = 2);
void CacheRandomSound(sfxinfo_t* sfx);
unsigned int GetMSLength(FSoundID sound);
FSoundID PickReplacement(FSoundID refid);

View file

@ -44,8 +44,6 @@
#include "gamestate.h"
#include "i_interface.h"
bool G_Responder(event_t* ev);
int eventhead;
int eventtail;
event_t events[MAXEVENTS];
@ -86,12 +84,16 @@ void D_ProcessEvents (void)
if (ev->type == EV_DeviceChange)
UpdateJoystickMenu(I_UpdateDeviceList());
if (gamestate != GS_INTRO) // GS_INTRO blocks the UI.
// allow the game to intercept Escape before dispatching it.
if (ev->type != EV_KeyDown || ev->data1 != KEY_ESCAPE || !sysCallbacks.WantEscape || !sysCallbacks.WantEscape())
{
if (C_Responder(ev))
continue; // console ate the event
if (M_Responder(ev))
continue; // menu ate the event
if (gamestate != GS_INTRO) // GS_INTRO blocks the UI.
{
if (C_Responder(ev))
continue; // console ate the event
if (M_Responder(ev))
continue; // menu ate the event
}
}
if (sysCallbacks.G_Responder(ev) && ev->type == EV_KeyDown) keywasdown.Set(ev->data1);

View file

@ -46,6 +46,7 @@ struct SystemCallbacks
void (*LanguageChanged)(const char*);
bool (*OkForLocalization)(FTextureID, const char*);
FConfigFile* (*GetConfig)();
bool (*WantEscape)();
};
extern SystemCallbacks sysCallbacks;

View file

@ -184,6 +184,7 @@ xx(IsNull)
xx(Exists)
xx(SetInvalid)
xx(SetNull)
xx(Key)
// color channels
xx(a)

View file

@ -99,106 +99,23 @@ void VersionInfo::operator=(const char *string)
//
//==========================================================================
FScanner::FScanner()
FScanner::FScanner(TMap<FName, Symbol>* extsymbols) : symbols(extsymbols? *extsymbols : mysymbols)
{
ScriptOpen = false;
}
//==========================================================================
//
// FScanner Destructor
//
//==========================================================================
FScanner::~FScanner()
{
// Humm... Nothing to do in here.
}
//==========================================================================
//
// FScanner Copy Constructor
//
//==========================================================================
FScanner::FScanner(const FScanner &other)
{
ScriptOpen = false;
*this = other;
}
//==========================================================================
//
// FScanner OpenLumpNum Constructor
//
//==========================================================================
FScanner::FScanner(int lumpnum)
FScanner::FScanner(int lumpnum, TMap<FName, Symbol>* extsymbols) : symbols(extsymbols ? *extsymbols : mysymbols)
{
ScriptOpen = false;
OpenLumpNum(lumpnum);
}
//==========================================================================
//
// FScanner :: operator =
//
//==========================================================================
FScanner &FScanner::operator=(const FScanner &other)
{
if (this == &other)
{
return *this;
}
if (!other.ScriptOpen)
{
Close();
return *this;
}
// Copy protected members
ScriptOpen = true;
ScriptName = other.ScriptName;
ScriptBuffer = other.ScriptBuffer;
ScriptPtr = other.ScriptPtr;
ScriptEndPtr = other.ScriptEndPtr;
AlreadyGot = other.AlreadyGot;
AlreadyGotLine = other.AlreadyGotLine;
LastGotToken = other.LastGotToken;
LastGotPtr = other.LastGotPtr;
LastGotLine = other.LastGotLine;
CMode = other.CMode;
Escape = other.Escape;
StateMode = other.StateMode;
StateOptions = other.StateOptions;
// Copy public members
if (other.String == other.StringBuffer)
{
memcpy(StringBuffer, other.StringBuffer, sizeof(StringBuffer));
BigStringBuffer = "";
String = StringBuffer;
}
else
{
// Past practice means the string buffer must be writeable, which
// removes some of the benefit from using an FString to store
// the big string buffer.
BigStringBuffer = other.BigStringBuffer;
String = BigStringBuffer.LockBuffer();
}
StringLen = other.StringLen;
TokenType = other.TokenType;
Number = other.Number;
Float = other.Float;
Line = other.Line;
End = other.End;
Crossed = other.Crossed;
return *this;
}
//==========================================================================
//
// FScanner :: Open
@ -1229,7 +1146,7 @@ void FScanner::AddSymbol(const char *name, int64_t value)
{
Symbol sym;
sym.tokenType = TK_IntConst;
sym.Number = int(value);
sym.Number = value;
sym.Float = double(value);
symbols.Insert(name, sym);
}

View file

@ -54,16 +54,18 @@ public:
double Float;
};
using SymbolMap = TMap<FName, Symbol>;
TMap<FName, Symbol> symbols;
SymbolMap mysymbols;
SymbolMap& symbols;
TMap<FName, Symbol>& GetSymbols() { return symbols; }
// Methods ------------------------------------------------------
FScanner();
FScanner(const FScanner &other);
FScanner(int lumpnum);
~FScanner();
FScanner &operator=(const FScanner &other);
FScanner(TMap<FName, Symbol>* extsymbols = nullptr);
FScanner(const FScanner& other) = delete;
FScanner& operator=(const FScanner& other) = delete;
FScanner(int lumpnum, TMap<FName, Symbol>* extsymbols = nullptr);
~FScanner() = default;
void Open(const char *lumpname);
bool OpenFile(const char *filename);
@ -115,6 +117,13 @@ public:
void MustGetNumber(bool evaluate = false);
bool CheckNumber(bool evaluate = false);
bool GetNumber(int16_t& var, bool evaluate = false)
{
if (!GetNumber(evaluate)) return false;
var = Number;
return true;
}
bool GetNumber(int& var, bool evaluate = false)
{
if (!GetNumber(evaluate)) return false;
@ -155,9 +164,9 @@ public:
void MustGetFloat(bool evaluate = false);
bool CheckFloat(bool evaluate = false);
double *LookupConstant(FName name)
Symbol *LookupSymbol(FName name)
{
return constants.CheckKey(name);
return symbols.CheckKey(name);
}
// Token based variant

View file

@ -121,7 +121,7 @@ FTextureID LoadSkin(const char * path, const char * fn)
int texlump = FindGFXFile(buffer);
const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump);
return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup);
}
//===========================================================================

View file

@ -625,6 +625,7 @@ private:
public:
void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader)
{
tex->setSeen();
if (!sysCallbacks.PreBindTexture || !sysCallbacks.PreBindTexture(this, tex, upscalemask, scaleflags, clampmode, translation, overrideshader))
{
if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale;

View file

@ -560,14 +560,12 @@ public:
class FxVectorValue : public FxExpression
{
constexpr static int maxVectorDimensions = 4;
FxExpression *xyzw[maxVectorDimensions];
bool isConst; // gets set to true if all element are const (used by function defaults parser)
public:
FxExpression *xyzw[maxVectorDimensions];
friend class ZCCCompiler;
friend class ZCCDoomCompiler;
FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, FxExpression* w, const FScriptPosition &sc);
~FxVectorValue();

View file

@ -638,7 +638,8 @@ struct DirectNativeDesc
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); }
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13); }
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13), TP(14)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14); }
#undef TP
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13), TP(14), TP(15)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14), VP(15); }
#undef TP
#undef VP
template<typename T> void ValidateType() { static_assert(native_is_valid<T>::value, "Argument type is not valid as a direct native parameter or return type"); }

View file

@ -124,7 +124,7 @@ void ST_UnloadCrosshair()
//
//---------------------------------------------------------------------------
void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale)
void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale, DAngle angle)
{
uint32_t color;
double size;
@ -207,6 +207,7 @@ void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale)
xpos, ypos,
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_Rotate, angle.Degrees(),
DTA_AlphaChannel, true,
DTA_FillColor, color & 0xFFFFFF,
TAG_DONE);

View file

@ -10,7 +10,7 @@ class FFont;
extern FGameTexture* CrosshairImage;
void ST_LoadCrosshair(int num, bool alwaysload);
void ST_UnloadCrosshair();
void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale);
void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale, DAngle angle = nullAngle);
enum DI_Flags

View file

@ -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;

View file

@ -1,5 +1,6 @@
#pragma once
#include <stdint.h>
#include <memory>
#include "vectors.h"
#include "floatrect.h"
#include "refcounted.h"
@ -60,6 +61,19 @@ enum EGameTexFlags
GTexf_AutoMaterialsAdded = 256, // AddAutoMaterials has been called on this texture.
GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font.
GTexf_NoTrim = 1024, // Don't perform trimming on this texture.
GTexf_Seen = 2048, // Set to true when the texture is being used for rendering. Must be cleared manually if the check is needed.
};
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
@ -71,14 +85,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;
@ -179,6 +186,13 @@ public:
void SetRotations(int rot) { Rotations = int16_t(rot); }
void SetSkyOffset(int offs) { SkyOffset = offs; }
int GetSkyOffset() const { return SkyOffset; }
void setSeen() { flags |= GTexf_Seen; }
bool isSeen(bool reset)
{
int v = flags & GTexf_Seen;
if (reset) flags &= ~GTexf_Seen;
return v;
}
ISoftwareTexture* GetSoftwareTexture()
{
@ -204,14 +218,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();
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
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]) CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
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]) Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
}
}
}
float GetGlossiness() const { return Glossiness; }
@ -306,13 +331,20 @@ 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)
{
if (tex != nullptr) layers.Push(tex.get());
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());
}
}
}
@ -335,28 +367,59 @@ 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();
}
FTexture* GetNormalmap()
{
if (!Layers) return nullptr;
return Layers->Normal.get();
}
FTexture* GetSpecularmap()
{
if (!Layers) return nullptr;
return Layers->Specular.get();
}
FTexture* GetMetallic()
{
if (!Layers) return nullptr;
return Layers->Metallic.get();
}
FTexture* GetRoughness()
{
if (!Layers) return nullptr;
return Layers->Roughness.get();
}
FTexture* GetAmbientOcclusion()
{
if (!Layers) return nullptr;
return Layers->AmbientOcclusion.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;
}
};

View file

@ -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.

View file

@ -82,9 +82,6 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion)
{
PalettedPixels ret;
FString name;
fileSystem.GetFileShortName(name, SourceLump);
auto imageID = ImageID;
// Do we have this image in the cache?
@ -196,10 +193,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int
{
FBitmap ret;
FString name;
int trans = -1;
fileSystem.GetFileShortName(name, SourceLump);
auto imageID = ImageID;
if (remap != nullptr)

View file

@ -60,7 +60,7 @@ public:
virtual bool SupportRemap0() { return false; } // Unfortunate hackery that's needed for Hexen's skies. Only the image can know about the needed parameters
virtual bool IsRawCompatible() { return true; } // Same thing for mid texture compatibility handling. Can only be determined by looking at the composition data which is private to the image.
void CopySize(FImageSource &other)
void CopySize(FImageSource &other) noexcept
{
Width = other.Width;
Height = other.Height;
@ -71,6 +71,7 @@ public:
// Images are statically allocated and freed in bulk. None of the subclasses may hold any destructible data.
void *operator new(size_t block) { return ImageArena.Alloc(block); }
void* operator new(size_t block, void* mem) { return mem; }
void operator delete(void *block) {}
bool bMasked = true; // Image (might) have holes (Assume true unless proven otherwise!)
@ -86,7 +87,6 @@ public:
// tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy.
TArray<uint8_t> GetPalettedPixels(int conversion);
// Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format.
FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr);
@ -103,8 +103,8 @@ public:
noremap0 = 2
};
FImageSource(int sourcelump = -1) : SourceLump(sourcelump) { ImageID = ++NextID; }
virtual ~FImageSource() {}
FImageSource(int sourcelump = -1) noexcept : SourceLump(sourcelump) { ImageID = ++NextID; }
virtual ~FImageSource() = default;
int GetWidth() const
{

View file

@ -186,6 +186,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
// The name matches, so check the texture type
if (usetype == ETextureType::Any)
{
if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures.
// All NULL textures should actually return 0
if (texUseType == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0;
if (texUseType == ETextureType::SkinGraphic && !(flags & TEXMAN_AllowSkins)) return 0;
@ -229,6 +230,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
// Never return the index of NULL textures.
if (firstfound != -1)
{
if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures.
if (firsttype == ETextureType::Null) return FTextureID(0);
if (firsttype == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0);
return FTextureID(firstfound);
@ -426,7 +428,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 +1152,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
{
@ -1601,11 +1603,28 @@ void FTextureManager::SetTranslation(FTextureID fromtexnum, FTextureID totexnum)
//
//-----------------------------------------------------------------------------
void FTextureManager::AddAlias(const char* name, FGameTexture* tex)
void FTextureManager::AddAlias(const char* name, int texindex)
{
FTextureID id = tex->GetID();
if (tex != Textures[id.GetIndex()].Texture || !tex->isValid()) return; // Whatever got passed in here was not valid, so ignore the alias.
aliases.Insert(name, id.GetIndex());
if (texindex < 0 || texindex >= NumTextures()) return; // Whatever got passed in here was not valid, so ignore the alias.
aliases.Insert(name, texindex);
}
void FTextureManager::Listaliases()
{
decltype(aliases)::Iterator it(aliases);
decltype(aliases)::Pair* pair;
TArray<FString> list;
while (it.NextPair(pair))
{
auto tex = GetGameTexture(pair->Value);
list.Push(FStringf("%s -> %s%s", pair->Key.GetChars(), tex ? tex->GetName().GetChars() : "(null)", ((tex && tex->GetUseType() == ETextureType::Null) ? ", null" : "")));
}
std::sort(list.begin(), list.end(), [](const FString& l, const FString& r) { return l.CompareNoCase(r) < 0; });
for (auto& s : list)
{
Printf("%s\n", s.GetChars());
}
}
//==========================================================================
@ -1627,3 +1646,7 @@ CCMD(flushtextures)
TexMan.FlushAll();
}
CCMD(listtexturealiases)
{
TexMan.Listaliases();
}

View file

@ -25,50 +25,50 @@ public:
private:
int ResolveLocalizedTexture(int texnum);
int ResolveTextureIndex(int texnum, bool animate, bool localize)
int ResolveTextureIndex(int texnum, bool animate) const
{
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;
}
FGameTexture *InternalGetTexture(int texnum, bool animate, bool localize)
FGameTexture *InternalGetTexture(int texnum, bool animate) const
{
texnum = ResolveTextureIndex(texnum, animate, localize);
texnum = ResolveTextureIndex(texnum, animate);
if (texnum == -1) return nullptr;
return Textures[texnum].Texture;
}
public:
FTextureID ResolveTextureIndex(FTextureID texid, bool animate, bool localize)
FTextureID ResolveTextureIndex(FTextureID texid, bool animate) const
{
return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate, localize));
return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate));
}
public:
// This only gets used in UI code so we do not need PALVERS handling.
FGameTexture* GetGameTextureByName(const char *name, bool animate = false, int flags = 0)
{
FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch, flags);
return InternalGetTexture(texnum.GetIndex(), animate, true);
return InternalGetTexture(texnum.GetIndex(), animate);
}
FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false)
FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false) const
{
return InternalGetTexture(texnum.GetIndex(), animate, true);
return InternalGetTexture(texnum.GetIndex(), animate);
}
FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true)
FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true) const
{
auto texid = ResolveTextureIndex(texnum.GetIndex(), animate, true);
auto texid = ResolveTextureIndex(texnum.GetIndex(), animate);
if (texid == -1) return nullptr;
if (allowsubstitute && Textures[texid].Paletted > 0) texid = Textures[texid].Paletted;
return Textures[texid].Texture;
}
FGameTexture* GameByIndex(int i, bool animate = false)
FGameTexture* GameByIndex(int i, bool animate = false) const
{
return InternalGetTexture(i, animate, true);
return InternalGetTexture(i, animate);
}
FGameTexture* FindGameTexture(const char* texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny);
@ -76,6 +76,7 @@ public:
bool OkForLocalization(FTextureID texnum, const char *substitute, int locnum);
void FlushAll();
void Listaliases();
FTextureID GetFrontSkyLayer(FTextureID);
FTextureID GetRawTexture(FTextureID tex, bool dontlookup = false);
void SetRawTexture(FTextureID texid)
@ -99,6 +100,7 @@ public:
TEXMAN_Localize = 64,
TEXMAN_ForceLookup = 128,
TEXMAN_NoAlias = 256,
TEXMAN_ReturnAll = 512,
};
enum
@ -154,7 +156,11 @@ public:
tmanips.Remove(cname);
}
void AddAlias(const char* name, FGameTexture* tex);
void AddAlias(const char* name, int texindex);
void AddAlias(const char* name, FTextureID texindex)
{
AddAlias(name, texindex.GetIndex());
}
private:
@ -173,6 +179,10 @@ public:
BuildTileData.Reserve(1);
return BuildTileData.Last();
}
TArray<TArray<uint8_t>>& GetBuildTileDataStore()
{
return BuildTileData;
}
FGameTexture* GameTexture(FTextureID id) { return Textures[id.GetIndex()].Texture; }
void SetTranslation(FTextureID fromtexnum, FTextureID totexnum);
@ -183,17 +193,26 @@ 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,
};
public:
constexpr static int TEXFLAG_FIRSTUSER = 65536; // this leaves 16 flags to the texture manager and 48 flags to the user
private:
enum { HASH_END = -1, HASH_SIZE = 1027 };
TArray<TextureHash> Textures;
TArray<TextureDescriptor> Textures;
TMap<uint64_t, int> LocalizedTextures;
int HashFirst[HASH_SIZE];
FTextureID DefaultTexture;

View file

@ -213,7 +213,7 @@ public:
{
}
////////
TArray ()
constexpr TArray ()
{
Most = 0;
Count = 0;

View file

@ -1428,11 +1428,6 @@ public:
return int(Degrees_ * (512 / 90.0));
}
constexpr double Buildfang() const
{
return Degrees_ * (512 / 90.0);
}
constexpr int Q16() const
{
return int(Degrees_ * (16384 / 90.0));
@ -1455,7 +1450,8 @@ public:
double Tan() const
{
return vec_t(g_tan(Radians()));
auto bam = BAMs();
return g_sinbam(bam) / g_cosbam(bam);
}
// This is for calculating vertical velocity. For high pitches the tangent will become too large to be useful.

View file

@ -2299,9 +2299,11 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i
fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(inclump)), sc.String);
}
}
FScanner saved_sc = sc;
ParseMapInfo(inclump, gamedefaults, defaultinfo);
sc = saved_sc;
// use a new parser object to parse the include. Otherwise we'd have to save the entire FScanner in a local variable which is a lot more messy.
FMapInfoParser includer(&sc);
includer.format_type = format_type;
includer.HexenHack = HexenHack;
includer.ParseMapInfo(inclump, gamedefaults, defaultinfo);
}
else if (sc.Compare("gamedefaults"))
{

View file

@ -78,6 +78,10 @@ struct CutsceneDef;
struct FMapInfoParser
{
FMapInfoParser(FScanner* parent)
: sc(parent ? &parent->GetSymbols() : nullptr)
{
}
enum EFormatType
{
FMT_Unknown,

View file

@ -472,7 +472,6 @@ xx(Strength)
xx(Mode)
xx(PowerupType)
xx(PlayerPawn)
xx(Key)
xx(RipSound)
xx(Archvile)

View file

@ -1445,12 +1445,12 @@ class GLDefsParser
if (usershader.shader.IsNotEmpty())
{
int firstUserTexture;
if ((mlay.Normal || tex->Normal.get()) && (mlay.Specular || tex->Specular.get()))
if ((mlay.Normal || tex->GetNormalmap()) && (mlay.Specular || tex->GetSpecularmap()))
{
usershader.shaderType = SHADER_Specular;
firstUserTexture = 7;
}
else if ((mlay.Normal || tex->Normal.get()) && (mlay.Metallic || tex->Metallic.get()) && (mlay.Roughness || tex->Roughness.get()) && (mlay.AmbientOcclusion || tex->AmbientOcclusion.get()))
else if ((mlay.Normal || tex->GetNormalmap()) && (mlay.Metallic || tex->GetMetallic()) && (mlay.Roughness || tex->GetRoughness()) && (mlay.AmbientOcclusion || tex->GetAmbientOcclusion()))
{
usershader.shaderType = SHADER_PBR;
firstUserTexture = 9;

View file

@ -2428,7 +2428,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetDisplacement)
DVector2 ofs(0, 0);
if (pg1 != pg2)
{
int i = pg1 + self->Displacements.size * pg2;
unsigned i = pg1 + self->Displacements.size * pg2;
if (i < self->Displacements.data.Size())
ofs = self->Displacements.data[i].pos;
}

View file

@ -476,8 +476,8 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *
return;
}
(*(FVector2*)addr) = FVector2(
static_cast<FxConstant *>(v->xyzw[0])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[1])->GetValue().GetFloat()
float(static_cast<FxConstant *>(v->xyzw[0])->GetValue().GetFloat()),
float(static_cast<FxConstant *>(v->xyzw[1])->GetValue().GetFloat())
);
goto vector_ok;
}
@ -503,9 +503,9 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *
return;
}
(*(FVector3*)addr) = FVector3(
static_cast<FxConstant *>(v->xyzw[0])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[1])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[2])->GetValue().GetFloat()
float(static_cast<FxConstant*>(v->xyzw[0])->GetValue().GetFloat()),
float(static_cast<FxConstant*>(v->xyzw[1])->GetValue().GetFloat()),
float(static_cast<FxConstant*>(v->xyzw[2])->GetValue().GetFloat())
);
goto vector_ok;
}
@ -532,10 +532,10 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *
return;
}
(*(FVector4*)addr) = FVector4(
static_cast<FxConstant *>(v->xyzw[0])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[1])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[2])->GetValue().GetFloat(),
static_cast<FxConstant *>(v->xyzw[3])->GetValue().GetFloat()
float(static_cast<FxConstant*>(v->xyzw[0])->GetValue().GetFloat()),
float(static_cast<FxConstant*>(v->xyzw[1])->GetValue().GetFloat()),
float(static_cast<FxConstant*>(v->xyzw[2])->GetValue().GetFloat()),
float(static_cast<FxConstant *>(v->xyzw[3])->GetValue().GetFloat())
);
goto vector_ok;
}

View file

@ -492,7 +492,7 @@ FSoundID S_AddPlayerSound (const char *pclass, int gender, FSoundID refid, int l
fakename += '"';
fakename += '0' + gender;
fakename += '"';
fakename += sfx->name;
fakename += sfx->name.GetChars();
id = soundEngine->AddSoundLump (fakename, lumpnum, CurrentPitchMask);
int classnum = S_AddPlayerClass (pclass);
@ -1593,7 +1593,7 @@ CCMD (playersounds)
if (sfx->UserData[0] & SND_PlayerReserve)
{
++j;
reserveNames[sfx->link.index()] = sfx->name;
reserveNames[sfx->link.index()] = sfx->name.GetChars();
}
}