- transitioned to using GZDoom's texture creation code.

Also added support for creating indexed textures directly into CreateTexBuffer, where this functionality can be shared.
As an added plus, brightmaps are working again, this time with less hackery.
This commit is contained in:
Christoph Oelckers 2020-05-29 15:55:08 +02:00
parent 66809ca9f4
commit 594ec6626c
9 changed files with 106 additions and 170 deletions

View File

@ -302,7 +302,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i
{
int usebright = false;
bool needmipmap = (clampmode <= CLAMP_XY);
bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter;
// Bind it to the system.
if (!Bind(texunit, needmipmap))
@ -331,6 +331,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i
return false;
}
}
if (forcenofilter) clampmode += CLAMP_NOFILTER - CLAMP_NONE;
GLRenderer->mSamplerManager->Bind(texunit, clampmode, 255);
return true;
}

View File

@ -187,7 +187,7 @@ void FGameTexture::AddAutoMaterials()
void FGameTexture::CreateDefaultBrightmap()
{
auto tex = GetTexture();
if (flags & GTexf_BrightmapChecked)
if (!(flags & GTexf_BrightmapChecked))
{
flags |= GTexf_BrightmapChecked;
// Check for brightmaps

View File

@ -305,6 +305,13 @@ public:
}
}
FTexture* GetBrightmap()
{
if (Brightmap.get() || (flags & GTexf_BrightmapChecked)) return Brightmap.get();
CreateDefaultBrightmap();
return Brightmap.get();
}
};
inline FGameTexture* MakeGameTexture(FTexture* tex, const char *name, ETextureType useType)

View File

@ -14,6 +14,7 @@ enum ECreateTexBufferFlags
CTF_CreateMask = 3, // Flags that are relevant for hardware texture creation.
CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures.
CTF_Indexed = 16 // Tell the backend to create an indexed texture.
};
class FHardwareTextureContainer

View File

@ -48,6 +48,7 @@
#include "formats/multipatchtexture.h"
#include "texturemanager.h"
#include "c_cvars.h"
#include "imagehelpers.h"
// Wrappers to keep the definitions of these classes out of here.
IHardwareTexture* CreateHardwareTexture(int numchannels);
@ -323,66 +324,82 @@ bool FTexture::ProcessData(unsigned char* buffer, int w, int h, bool ispatch)
FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
{
FTextureBuffer result;
unsigned char* buffer = nullptr;
int W, H;
int isTransparent = -1;
bool checkonly = !!(flags & CTF_CheckOnly);
int exx = !!(flags & CTF_Expand);
W = GetWidth() + 2 * exx;
H = GetHeight() + 2 * exx;
if (!checkonly)
if (flags & CTF_Indexed)
{
buffer = new unsigned char[W * (H + 1) * 4];
memset(buffer, 0, W * (H + 1) * 4);
// Indexed textures will never be translated and never be scaled.
int w = GetWidth(), h = GetHeight();
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
if (remap) translation = remap->Index;
FBitmap bmp(buffer, W * 4, W, H);
auto store = Get8BitPixels(false);
const uint8_t* p = store.Data();
int trans;
auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans);
bmp.Blit(exx, exx, Pixels);
result.mBuffer = new uint8_t[w * h];
result.mWidth = w;
result.mHeight = h;
result.mContentId = 0;
ImageHelpers::FlipNonSquareBlock(result.mBuffer, p, h, w, h);
}
else
{
unsigned char* buffer = nullptr;
int W, H;
int isTransparent = -1;
bool checkonly = !!(flags & CTF_CheckOnly);
if (remap == nullptr)
int exx = !!(flags & CTF_Expand);
W = GetWidth() + 2 * exx;
H = GetHeight() + 2 * exx;
if (!checkonly)
{
CheckTrans(buffer, W * H, trans);
isTransparent = bTranslucent;
buffer = new unsigned char[W * (H + 1) * 4];
memset(buffer, 0, W * (H + 1) * 4);
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
if (remap) translation = remap->Index;
FBitmap bmp(buffer, W * 4, W, H);
int trans;
auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans);
bmp.Blit(exx, exx, Pixels);
if (remap == nullptr)
{
CheckTrans(buffer, W * H, trans);
isTransparent = bTranslucent;
}
else
{
isTransparent = 0;
// A translated image is not conclusive for setting the texture's transparency info.
}
}
else
if (GetImage())
{
isTransparent = 0;
// A translated image is not conclusive for setting the texture's transparency info.
FContentIdBuilder builder;
builder.id = 0;
builder.imageID = GetImage()->GetId();
builder.translation = MAX(0, translation);
builder.expand = exx;
result.mContentId = builder.id;
}
else result.mContentId = 0; // for non-image backed textures this has no meaning so leave it at 0.
result.mBuffer = buffer;
result.mWidth = W;
result.mHeight = H;
// Only do postprocessing for image-backed textures. (i.e. not for the burn texture which can also pass through here.)
if (GetImage() && flags & CTF_ProcessData)
{
if (flags & CTF_Upscale) CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly);
if (!checkonly) ProcessData(result.mBuffer, result.mWidth, result.mHeight, false);
}
}
if (GetImage())
{
FContentIdBuilder builder;
builder.id = 0;
builder.imageID = GetImage()->GetId();
builder.translation = MAX(0, translation);
builder.expand = exx;
result.mContentId = builder.id;
}
else result.mContentId = 0; // for non-image backed textures this has no meaning so leave it at 0.
result.mBuffer = buffer;
result.mWidth = W;
result.mHeight = H;
// Only do postprocessing for image-backed textures. (i.e. not for the burn texture which can also pass through here.)
if (GetImage() && flags & CTF_ProcessData)
{
if (flags & CTF_Upscale) CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly);
if (!checkonly) ProcessData(result.mBuffer, result.mWidth, result.mHeight, false);
}
return result;
}
//===========================================================================

View File

@ -138,7 +138,6 @@ void BuildTiles::Init()
tile.picanm = {};
tile.RotTile = { -1,-1 };
tile.replacement = ReplacementType::Art;
tile.NoBrightmapFlag.Zero();
}
}
@ -743,7 +742,7 @@ int BuildTiles::findUnusedTile(void)
for (; lastUnusedTile >= 0; --lastUnusedTile)
{
auto tex = tileGetTexture(lastUnusedTile);
if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return lastUnusedTile;
if (!tex || !tex->isValid()) return lastUnusedTile;
}
return -1;
}

View File

@ -265,7 +265,6 @@ struct TileDesc
rottile_t RotTile;// = { -1,-1 };
TArray<HightileReplacement> Hightiles;
ReplacementType replacement;
FixedBitArray<256> NoBrightmapFlag;
};
struct BuildTiles

View File

@ -43,98 +43,26 @@
#include "palettecontainer.h"
#include "../../glbackend/glbackend.h"
#include "texturemanager.h"
#include "v_video.h"
// Test CVARs.
CVAR(Int, fixpalette, -1, 0)
CVAR(Int, fixpalswap, -1, 0)
template<class T>
void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch)
{
for (int i = 0; i < x; ++i)
{
for (int j = 0; j < y; ++j)
{
dst[i * y + j] = src[i + j * srcpitch];
}
}
}
//===========================================================================
//
// Create an indexed version of the requested texture
//
//===========================================================================
OpenGLRenderer::FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex)
{
vec2_t siz = { tex->GetTexelWidth(), tex->GetTexelHeight() };
auto store = tex->GetTexture()->Get8BitPixels(false);
const uint8_t* p = store.Data();
auto glpic = GLInterface.NewTexture(1);
TArray<uint8_t> flipped(siz.x * siz.y, true);
FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y);
glpic->CreateTexture(flipped.Data(), siz.x, siz.y, 15, false, tex->GetName());
return glpic;
}
//===========================================================================
//
// Create a true color version of the requested tile
//
//===========================================================================
OpenGLRenderer::FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
{
if (tex == TexMan.GameByIndex(0))
return nullptr;
auto texbuffer = tex->GetTexture()->CreateTexBuffer(palid, checkfulltransparency? 0: CTF_ProcessData);
// Check if the texture is fully transparent. When creating a brightmap such textures can be discarded.
if (checkfulltransparency)
{
int siz = texbuffer.mWidth * texbuffer.mHeight * 4;
bool found = false;
for (int i = 3; i < siz; i+=4)
{
if (texbuffer.mBuffer[i] > 0)
{
found = true;
break;
}
}
if (!found) return nullptr;
}
auto glpic = GLInterface.NewTexture(4);
glpic->CreateTexture(texbuffer.mBuffer, texbuffer.mWidth, texbuffer.mHeight, 15, true, tex->GetName());
return glpic;
}
//===========================================================================
//
// Retrieve the texture to be used.
//
//===========================================================================
OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid)
OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FTexture *tex, int textype, int palid)
{
if (textype == TT_INDEXED) palid = -1;
auto phwtex = tex->GetTexture()->SystemTextures.GetHardwareTexture(palid, false);
auto phwtex = tex->SystemTextures.GetHardwareTexture(palid, false);
if (phwtex) return (OpenGLRenderer::FHardwareTexture*)phwtex;
OpenGLRenderer::FHardwareTexture *hwtex = nullptr;
if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex);
else if (!tex->GetTexture()->isHardwareCanvas())
hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP);
else
hwtex = nullptr;
if (hwtex) tex->GetTexture()->SystemTextures.AddHardwareTexture(palid, false, hwtex);
auto hwtex = static_cast<OpenGLRenderer::FHardwareTexture*>(screen->CreateHardwareTexture(textype == TT_INDEXED? 1:4));
if (hwtex) tex->SystemTextures.AddHardwareTexture(palid, false, hwtex);
return hwtex;
}
@ -203,7 +131,7 @@ TexturePick PickTexture(int tilenum, int basepal, int palette)
bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow)
{
if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false;
if (!tex->isValid() || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false;
int curbasepal = GetTranslationType(paletteid) - Translation_Remap;
int palette = GetTranslationIndex(paletteid);
int usepalette = fixpalette >= 0 ? fixpalette : curbasepal;
@ -216,6 +144,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
TextureType = hw_int_useindexedcolortextures? TT_INDEXED : TT_TRUECOLOR;
int lookuppal = 0;
int bindflags = 0;
VSMatrix texmat;
GLInterface.SetBasepalTint(0xffffff);
@ -241,6 +170,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
}
if (!rep || rep->palnum != palette || (h.f & HICTINT_APPLYOVERALTPAL)) applytint = true;
TextureType = TT_HICREPLACE;
bindflags = CTF_Upscale;
}
else
{
@ -254,7 +184,9 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
if (!(h.f & HICTINT_APPLYOVERPALSWAP)) usepalswap = 0;
}
lookuppal = TRANSLATION(usepalette + Translation_Remap, usepalswap);
bindflags = CTF_Upscale;
}
else bindflags = CTF_Indexed;
}
// This is intentionally the same value for both parameters. The shader does not use the same uniform for modulation and overlay colors.
@ -264,7 +196,8 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
// Load the main texture
auto mtex = LoadTexture(tex, TextureType, lookuppal);
auto mtex = LoadTexture(tex->GetTexture(), TextureType, lookuppal);
if (mtex)
{
auto sampler = (method & DAMETH_CLAMPED) ? (sampleroverride != -1 ? sampleroverride : SamplerClampXY) : SamplerRepeat;
@ -280,6 +213,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
UseGlowMapping(false);
UseBrightmaps(false);
mtex->BindOrCreate(tex->GetTexture(), 0, sampler, lookuppal, bindflags);
BindTexture(0, mtex, sampler);
// Needs a) testing and b) verification for correctness. This doesn't look like it makes sense.
if (rep && (rep->scale.x != 1.0f || rep->scale.y != 1.0f))
@ -305,8 +239,9 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
}
if (det)
{
auto htex = LoadTexture(det, TT_HICREPLACE, 0);
auto htex = LoadTexture(det->GetTexture(), TT_HICREPLACE, 0);
UseDetailMapping(true);
htex->BindOrCreate(det->GetTexture(), 3, CLAMP_NONE, 0, 0);
BindTexture(3, htex, SamplerRepeat);
texbound[0] = true;
@ -335,44 +270,38 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
}
if (glow)
{
auto htex = LoadTexture(glow, TT_HICREPLACE, 0);
auto htex = LoadTexture(glow->GetTexture(), TT_HICREPLACE, 0);
UseGlowMapping(true);
htex->BindOrCreate(glow->GetTexture(), 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) && !TileFiles.tiledata[picnum].NoBrightmapFlag[usepalswap])
if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT))
{
if (TextureType == TT_HICREPLACE)
{
auto brep = TileFiles.FindReplacement(picnum, BRIGHTPAL);
if (brep)
{
LoadTexture(brep->faces[0], TT_HICREPLACE, 0);
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);
texbound[2] = true;
}
else
{
TileFiles.tiledata[picnum].picanm.sf |= PICANM_NOFULLBRIGHT_BIT;
}
}
else if (TextureType == TT_TRUECOLOR)
{
lookuppal = -1;// Needs some work on the texture management first. palmanager.LookupPalette(usepalette, usepalswap, true);
if (lookuppal >= 0)
auto btex = tex->GetBrightmap();
if (btex)
{
auto htex = LoadTexture(tex, TT_BRIGHTMAP, lookuppal);
if (htex == nullptr)
{
// Flag the texture as not being brightmapped for the given palette
TileFiles.tiledata[picnum].NoBrightmapFlag.Set(usepalswap);
}
else
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;
}
@ -399,23 +328,10 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid
//===========================================================================
//
// Sets a named texture for 2D rendering. In this case the palette is
// a direct index into the palette map.
// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker
//
//===========================================================================
bool GLInstance::SetNamedTexture(FGameTexture* tex, int palette, int sampler)
{
auto mtex = LoadTexture(tex, palette>= 0? TT_TRUECOLOR : TT_HICREPLACE, palette);
if (!mtex) return false;
BindTexture(0, mtex, sampler);
GLInterface.SetAlphaThreshold(tex->GetTranslucency()? 0.f : 0.5f);
return true;
}
// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker
int PalCheck(int tex)
{
return tex;

View File

@ -487,13 +487,9 @@ public:
renderState.AlphaThreshold = al;
}
OpenGLRenderer::FHardwareTexture* CreateIndexedTexture(FGameTexture* tex);
OpenGLRenderer::FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
OpenGLRenderer::FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid);
OpenGLRenderer::FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow);
bool SetNamedTexture(FGameTexture* tex, int palette, int sampleroverride);
bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride)
{
return SetTextureInternal(globalpicnum, tex, palette, method, sampleroverride, nullptr, 1, nullptr);