- texture code cleanup, mainly cppying layer data into the textures at startup to be able to use a real material system.

This commit is contained in:
Christoph Oelckers 2020-05-29 23:33:26 +02:00
parent 2c94b2bb6d
commit cca4fc609f
10 changed files with 218 additions and 180 deletions

View file

@ -47,8 +47,6 @@ enum {
extern float curpolygonoffset;
extern uint8_t alphahackarray[MAXTILES];
extern int32_t r_scenebrightness;
extern int32_t polymostcenterhoriz;

View file

@ -390,19 +390,14 @@ static int32_t defsparser(scriptfile *script)
if (scriptfile_getsymbol(script,&tile)) break;
if (scriptfile_getdouble(script,&alpha)) break;
#ifdef USE_OPENGL
if ((uint32_t)tile < MAXTILES)
alphahackarray[tile] = Blrintf(alpha * (float)UINT8_MAX);
#endif
TileFiles.tiledata[tile].alphaThreshold = (float)alpha;
}
break;
case T_ALPHAHACKRANGE:
{
int32_t tilenume1,tilenume2;
double alpha;
#ifdef USE_OPENGL
int32_t i;
#endif
if (scriptfile_getsymbol(script,&tilenume1)) break;
if (scriptfile_getsymbol(script,&tilenume2)) break;
@ -411,10 +406,8 @@ static int32_t defsparser(scriptfile *script)
if (check_tile_range("alphahackrange", &tilenume1, &tilenume2, script, cmdtokptr))
break;
#ifdef USE_OPENGL
for (i=tilenume1; i<=tilenume2; i++)
alphahackarray[i] = Blrintf(alpha * (float)UINT8_MAX);
#endif
for (int i=tilenume1; i<=tilenume2; i++)
TileFiles.tiledata[i].alphaThreshold = (float)alpha;
}
break;
case T_SPRITECOL:

View file

@ -73,7 +73,6 @@ int32_t r_rortexture = 0;
int32_t r_rortexturerange = 0;
int32_t r_rorphase = 0;
int32_t mdtims, omdtims;
uint8_t alphahackarray[MAXTILES];
int32_t polymostcenterhoriz = 100;
float fcosglobalang, fsinglobalang;

View file

@ -1607,12 +1607,9 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
if (m->usesalpha) //Sprites with alpha in texture
{
// PLAG : default cutoff removed
float al = 0.0;
if (alphahackarray[globalpicnum] != 0)
al=alphahackarray[globalpicnum] * (1.f/255.f);
GLInterface.EnableBlend(true);
GLInterface.EnableAlphaTest(true);
GLInterface.SetAlphaThreshold(al);
GLInterface.SetAlphaThreshold(TileFiles.tiledata[globalpicnum].alphaThreshold);
}
else
{
@ -1713,7 +1710,9 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
FGameTexture *det = nullptr, *glow = nullptr;
float detscale = 1.f;
#if 0
// The data lookup here is one incredible mess. Thanks to whoever cooked this up... :(
// Todo: assign the laxers to the base textures at setup time
if (!(tspr->clipdist & TSPR_FLAGS_MDHACK))
{
det = tex = hw_detailmapping ? mdloadskin((md2model_t *) m, tile2model[Ptile2tile(tspr->picnum, lpal)].skinnum, DETAILPAL, surfi, nullptr) : nullptr;
@ -1725,6 +1724,7 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
}
glow = hw_glowmapping ? mdloadskin((md2model_t *) m, tile2model[Ptile2tile(tspr->picnum, lpal)].skinnum, GLOWPAL, surfi, nullptr) : 0;
}
#endif
int palid = TRANSLATION(Translation_Remap + curbasepal, globalpal);
GLInterface.SetModelTexture(tex, palid, det, detscale, glow);

View file

@ -92,6 +92,7 @@ class FGameTexture
FMaterial* Material[4] = { };
// Material properties
FVector2 detailScale = { 1.f, 1.f };
float Glossiness = 10.f;
float SpecularLevel = 0.1f;
float shaderspeed = 1.f;
@ -305,12 +306,48 @@ public:
}
}
FVector2 GetDetailScale() const
{
return detailScale;
}
void SetDetailScale(float x, float y)
{
detailScale.X = x;
detailScale.Y = y;
}
FTexture* GetBrightmap()
{
if (Brightmap.get() || (flags & GTexf_BrightmapChecked)) return Brightmap.get();
CreateDefaultBrightmap();
return Brightmap.get();
}
FTexture* GetGlowmap()
{
return Glowmap.get();
}
FTexture* GetDetailmap()
{
return Detailmap.get();
}
void SetGlowmap(FTexture *T)
{
Glowmap = T;
}
void SetDetailmap(FTexture* T)
{
Detailmap = T;
}
void SetNormalmap(FTexture* T)
{
Normal = T;
}
void SetSpecularmap(FTexture* T)
{
Specular = T;
}
};

View file

@ -138,6 +138,7 @@ void BuildTiles::Init()
tile.picanm = {};
tile.RotTile = { -1,-1 };
tile.replacement = ReplacementType::Art;
tile.alphaThreshold = 0.5;
}
}
@ -491,6 +492,59 @@ uint8_t* BuildTiles::tileMakeWritable(int num)
return wtex ? wtex->GetRawData() : nullptr;
}
//==========================================================================
//
// Processes data from .def files into the textures
//
//==========================================================================
void BuildTiles::PostLoadSetup()
{
for (auto& tile : tiledata)
{
FGameTexture* detailTex = nullptr, * glowTex = nullptr, * normalTex = nullptr, *specTex = nullptr;
float scalex = 1.f, scaley = 1.f;
for (auto& rep : tile.Hightiles)
{
if (rep.palnum == GLOWPAL)
{
glowTex = rep.faces[0];
}
if (rep.palnum == NORMALPAL)
{
normalTex = rep.faces[0];
}
if (rep.palnum == SPECULARPAL)
{
specTex = rep.faces[0];
}
if (rep.palnum == DETAILPAL)
{
detailTex = rep.faces[0];
scalex = rep.scale.x;
scaley = rep.scale.y;
}
}
if (!detailTex && !glowTex && !normalTex && !specTex) continue; // if there's no layers there's nothing to do.
for (auto& rep : tile.Hightiles)
{
if (rep.faces[1]) continue; // do not muck around with skyboxes (yet)
if (rep.palnum < NORMALPAL)
{
auto tex = rep.faces[0];
// Make a copy so that multiple appearances of the same texture can be handled. They will all refer to the same internal texture anyway.
tex = MakeGameTexture(tex->GetTexture(), "", ETextureType::Any);
tex->SetGlowmap(glowTex->GetTexture());
tex->SetDetailmap(detailTex->GetTexture());
tex->SetNormalmap(normalTex->GetTexture());
tex->SetSpecularmap(specTex->GetTexture());
tex->SetDetailScale(scalex, scaley);
rep.faces[0] = tex;
}
}
}
}
//==========================================================================
//
// Returns checksum for a given tile
@ -543,7 +597,6 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu
FTextureID texid = TexMan.CheckForTexture(fn, ETextureType::Any);
if (!texid.isValid()) return -1;
auto tex = TexMan.GetGameTexture(texid);
//tex->alphaThreshold = 255 - alphacut;
int32_t xsiz = tex->GetTexelWidth(), ysiz = tex->GetTexelHeight();
@ -931,6 +984,83 @@ void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int til
TileFiles.InvalidateTile(tilenum2);
}
//===========================================================================
//
// Picks a texture for rendering for a given tilenum/palette combination
//
//===========================================================================
// Test CVARs.
CVAR(Int, fixpalette, -1, 0)
CVAR(Int, fixpalswap, -1, 0)
bool PickTexture(int picnum, FGameTexture* tex, int paletteid, TexturePick& pick)
{
if (!tex) tex = tileGetTexture(picnum);
if (picnum == -1) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
if (!tex->isValid() || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false;
pick.texture = tex;
int curbasepal = GetTranslationType(paletteid) - Translation_Remap;
int palette = GetTranslationIndex(paletteid);
int usepalette = fixpalette >= 0 ? fixpalette : curbasepal;
int usepalswap = fixpalswap >= 0 ? fixpalswap : palette;
int TextureType = hw_int_useindexedcolortextures && picnum >= 0 ? TT_INDEXED : TT_TRUECOLOR;
pick.translation = TRANSLATION(usepalette + Translation_Remap, usepalswap);
pick.basepalTint = 0xffffff;
auto& h = lookups.tables[palette];
bool applytint = false;
// Canvas textures must be treated like hightile replacements in the following code.
if (picnum < 0) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
auto rep = (picnum >= 0 && hw_hightile && !(h.tintFlags & TINTF_ALWAYSUSEART)) ? TileFiles.FindReplacement(picnum, palette) : nullptr;
if (rep || tex->GetTexture()->isHardwareCanvas())
{
if (usepalette != 0)
{
// This is a global setting for the entire scene, so let's do it here, right at the start. (Fixme: Store this in a static table instead of reusing the same entry for all palettes.)
auto& hh = lookups.tables[MAXPALOOKUPS - 1];
// This sets a tinting color for global palettes, e.g. water or slime - only used for hires replacements (also an option for low-resource hardware where duplicating the textures may be problematic.)
pick.basepalTint = hh.tintColor;
}
if (rep)
{
tex = rep->faces[0];
}
if (!rep || rep->palnum != palette || (h.tintFlags & TINTF_APPLYOVERALTPAL)) applytint = true;
pick.translation = 0;
}
else
{
// Only look up the palette if we really want to use it (i.e. when creating a true color texture of an ART tile.)
if (TextureType == TT_TRUECOLOR)
{
if (h.tintFlags & (TINTF_ALWAYSUSEART | TINTF_USEONART))
{
applytint = true;
if (!(h.tintFlags & TINTF_APPLYOVERPALSWAP)) usepalswap = 0;
}
pick.translation = TRANSLATION(usepalette + Translation_Remap, usepalswap);
}
else pick.translation |= 0x80000000;
}
if (applytint && h.tintFlags)
{
pick.tintFlags = h.tintFlags;
pick.tintColor = h.tintColor;
}
else
{
pick.tintFlags = -1;
pick.tintColor = 0xffffff;
}
return true;
}
TileSiz tilesiz;

View file

@ -30,6 +30,13 @@ enum
};
enum ETexType
{
TT_INDEXED,
TT_TRUECOLOR,
};
enum class ReplacementType : int
{
Art,
@ -265,6 +272,16 @@ struct TileDesc
rottile_t RotTile;// = { -1,-1 };
TArray<HightileReplacement> Hightiles;
ReplacementType replacement;
float alphaThreshold;
};
struct TexturePick
{
FGameTexture* texture; // which texture to use
int translation; // which translation table to use
int tintFlags; // which shader tinting options to use
PalEntry tintColor; // Tint color
PalEntry basepalTint; // can the base palette be done with a global tint effect?
};
struct BuildTiles
@ -334,6 +351,7 @@ struct BuildTiles
tiledata[picnum].Hightiles.Clear();
}
void PostLoadSetup();
};
@ -467,4 +485,6 @@ inline FGameTexture* tileGetTexture(int tile)
{
assert(tile < MAXTILES);
return TileFiles.tiledata[tile].texture;
}
}
bool PickTexture(int picnum, FGameTexture* tex, int paletteid, TexturePick& pick);

View file

@ -44,10 +44,6 @@
#include "texturemanager.h"
#include "v_video.h"
// Test CVARs.
CVAR(Int, fixpalette, -1, 0)
CVAR(Int, fixpalswap, -1, 0)
//===========================================================================
//
// Retrieve the texture to be used.
@ -65,89 +61,6 @@ OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FTexture *tex, int tex
return hwtex;
}
//===========================================================================
//
// Sets a texture for rendering. This should be the ONLY place to bind in-game textures
//
//===========================================================================
struct TexturePick
{
FGameTexture* texture; // which texture to use
int translation; // which translation table to use
int tintFlags; // which shader tinting options to use
PalEntry tintColor; // Tint color
PalEntry basepalTint; // can the base palette be done with a global tint effect?
};
bool PickTexture(int picnum, FGameTexture *tex, int paletteid, TexturePick &pick)
{
if (!tex) tex = tileGetTexture(picnum);
if (picnum == -1) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
if (!tex->isValid() || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false;
pick.texture = tex;
int curbasepal = GetTranslationType(paletteid) - Translation_Remap;
int palette = GetTranslationIndex(paletteid);
int usepalette = fixpalette >= 0 ? fixpalette : curbasepal;
int usepalswap = fixpalswap >= 0 ? fixpalswap : palette;
int TextureType = hw_int_useindexedcolortextures ? TT_INDEXED : TT_TRUECOLOR;
pick.translation = TRANSLATION(usepalette + Translation_Remap, usepalswap);
pick.basepalTint = 0xffffff;
auto& h = lookups.tables[palette];
bool applytint = false;
// Canvas textures must be treated like hightile replacements in the following code.
if (picnum < 0) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
auto rep = (picnum >= 0 && hw_hightile && !(h.tintFlags & TINTF_ALWAYSUSEART)) ? TileFiles.FindReplacement(picnum, palette) : nullptr;
if (rep || tex->GetTexture()->isHardwareCanvas())
{
if (usepalette != 0)
{
// This is a global setting for the entire scene, so let's do it here, right at the start. (Fixme: Store this in a static table instead of reusing the same entry for all palettes.)
auto& hh = lookups.tables[MAXPALOOKUPS - 1];
// This sets a tinting color for global palettes, e.g. water or slime - only used for hires replacements (also an option for low-resource hardware where duplicating the textures may be problematic.)
pick.basepalTint = hh.tintColor;
}
if (rep)
{
tex = rep->faces[0];
}
if (!rep || rep->palnum != palette || (h.tintFlags & TINTF_APPLYOVERALTPAL)) applytint = true;
pick.translation = 0;
//TextureType = TT_HICREPLACE;
}
else
{
// Only look up the palette if we really want to use it (i.e. when creating a true color texture of an ART tile.)
if (TextureType == TT_TRUECOLOR)
{
if (h.tintFlags & (TINTF_ALWAYSUSEART | TINTF_USEONART))
{
applytint = true;
if (!(h.tintFlags & TINTF_APPLYOVERPALSWAP)) usepalswap = 0;
}
pick.translation = TRANSLATION(usepalette + Translation_Remap, usepalswap);
}
else pick.translation |= 0x80000000;
}
if (applytint && h.tintFlags)
{
pick.tintFlags = h.tintFlags;
pick.tintColor = h.tintColor;
}
else
{
pick.tintFlags = -1;
pick.tintColor = 0xffffff;
}
return true;
}
bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow)
{
TexturePick pick;
@ -200,104 +113,59 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
#endif
// Also load additional layers needed for this texture.
if (hw_detailmapping && hw_hightile && picnum > -1)
if (hw_detailmapping)
{
float detscalex = detscale, detscaley = detscale;
if (!(method & DAMETH_MODEL))
{
auto drep = TileFiles.FindReplacement(picnum, DETAILPAL);
if (drep)
{
det = drep->faces[0];
detscalex = drep->scale.x;
detscaley = drep->scale.y;
}
}
auto det = tex->GetDetailmap();
auto detscale = tex->GetDetailScale();
if (det)
{
auto htex = LoadTexture(det->GetTexture(), TT_HICREPLACE, 0);
auto htex = LoadTexture(det, TT_TRUECOLOR, 0);
UseDetailMapping(true);
htex->BindOrCreate(det->GetTexture(), 3, CLAMP_NONE, 0, 0);
htex->BindOrCreate(det, 3, CLAMP_NONE, 0, 0);
BindTexture(3, htex, SamplerRepeat);
texbound[0] = true;
/* todo: instead of a matrix, just pass a two-component uniform. Using a full matrix here is problematic.
if (MatrixChange & 1) MatrixChange |= 2;
else texmat.loadIdentity();
if ((detscalex != 1.0f) || (detscaley != 1.0f))
{
texmat.scale(detscalex, detscaley, 1.0f);
MatrixChange |= 2;
}
if (MatrixChange & 2) GLInterface.SetMatrix(Matrix_Detail, &texmat);
/* todo:
GLInterface.SetDetailScale(detscale);
*/
}
}
if (hw_glowmapping && hw_hightile && picnum > -1)
if (hw_glowmapping)
{
if (!(method & DAMETH_MODEL))
{
auto drep = TileFiles.FindReplacement(picnum, GLOWPAL);
if (drep)
{
glow = drep->faces[0];
}
}
auto glow = tex->GetGlowmap();
if (glow)
{
auto htex = LoadTexture(glow->GetTexture(), TT_HICREPLACE, 0);
auto htex = LoadTexture(glow, TT_TRUECOLOR, 0);
UseGlowMapping(true);
htex->BindOrCreate(glow->GetTexture(), 4, sampler, 0, CTF_Upscale);
htex->BindOrCreate(glow, 4, sampler, 0, CTF_Upscale);
BindTexture(4, htex, SamplerRepeat);
texbound[1] = true;
}
}
#if 1
if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT))
if (!(globalflags & GLOBAL_NO_GL_FULLBRIGHT))
{
if (TextureType == TT_HICREPLACE)
auto btex = tex->GetBrightmap();
if (btex)
{
auto brep = TileFiles.FindReplacement(picnum, BRIGHTPAL);
if (brep)
auto htex = LoadTexture(btex, TT_TRUECOLOR, lookuppal);
if (htex != nullptr)
{
auto mtex = LoadTexture(brep->faces[0]->GetTexture(), TT_HICREPLACE, 0);
UseBrightmaps(true);
mtex->BindOrCreate(brep->faces[0]->GetTexture(), 5, sampler, 0, CTF_Upscale);
BindTexture(5, mtex, sampler);
htex->BindOrCreate(btex, 5, sampler, 0, CTF_Upscale);
BindTexture(5, htex, sampler);
texbound[2] = true;
}
}
else if (TextureType == TT_TRUECOLOR)
{
auto btex = tex->GetBrightmap();
if (btex)
{
auto htex = LoadTexture(btex, TT_BRIGHTMAP, lookuppal);
if (htex != nullptr)
{
UseBrightmaps(true);
htex->BindOrCreate(btex, 5, sampler, 0, CTF_Upscale);
BindTexture(5, htex, sampler);
texbound[2] = true;
}
}
}
}
if (!texbound[0]) UnbindTexture(3);
if (!texbound[1]) UnbindTexture(4);
if (!texbound[2]) UnbindTexture(5);
#endif
}
else return false;
float al = 0.5f;
if (TextureType == TT_HICREPLACE)
{
al = ((unsigned)picnum < MAXTILES&& alphahackarray[picnum] != 0) ? alphahackarray[picnum] * (1.f / 255.f) :
(tex->alphaThreshold >= 0 ? tex->alphaThreshold * (1.f / 255.f) : 0.f);
}
GLInterface.SetAlphaThreshold(al);
GLInterface.SetAlphaThreshold(tex->alphaThreshold);
return true;
}

View file

@ -95,14 +95,6 @@ enum EWinding
Winding_CW
};
enum ETexType
{
TT_INDEXED,
TT_TRUECOLOR,
TT_HICREPLACE,
TT_BRIGHTMAP
};
struct ImDrawData;
struct palette_t;
extern float shadediv[256];

View file

@ -6820,6 +6820,7 @@ static void G_Startup(void)
// Printf("Loading palette/lookups...\n");
G_LoadLookups();
TileFiles.PostLoadSetup();
if (DEER)
sub_54DE0();