diff --git a/source/build/include/polymost.h b/source/build/include/polymost.h index c0906b518..f43d1aa01 100644 --- a/source/build/include/polymost.h +++ b/source/build/include/polymost.h @@ -47,8 +47,6 @@ enum { extern float curpolygonoffset; -extern uint8_t alphahackarray[MAXTILES]; - extern int32_t r_scenebrightness; extern int32_t polymostcenterhoriz; diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 5891670ff..172467ed7 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -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: diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index cf5d22cd2..5bea04a37 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -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; diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index 2b2242f21..3ae9e02e5 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -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); diff --git a/source/common/textures/gametexture.h b/source/common/textures/gametexture.h index 2b8638ea5..4c717a8b9 100644 --- a/source/common/textures/gametexture.h +++ b/source/common/textures/gametexture.h @@ -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; + } }; diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index 02cefd3e6..c39c2d830 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -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; diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index 9cece50fc..432f0f748 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -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 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; -} \ No newline at end of file +} + +bool PickTexture(int picnum, FGameTexture* tex, int paletteid, TexturePick& pick); diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 65a74f124..eeab2349c 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -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; } diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 95df70fa3..95d513309 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -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]; diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 9220cfddd..6fd71ee1b 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -6820,6 +6820,7 @@ static void G_Startup(void) // Printf("Loading palette/lookups...\n"); G_LoadLookups(); + TileFiles.PostLoadSetup(); if (DEER) sub_54DE0();