- texture creation WIP.

This commit is contained in:
Christoph Oelckers 2019-10-18 00:20:27 +02:00
parent 3da49ad20a
commit c6514949e3
7 changed files with 208 additions and 194 deletions

View file

@ -649,7 +649,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
if (drawpoly_srepeat && drawpoly_trepeat) sampleroverride = SamplerRepeat; if (drawpoly_srepeat && drawpoly_trepeat) sampleroverride = SamplerRepeat;
else if (drawpoly_srepeat) sampleroverride = SamplerClampY; else if (drawpoly_srepeat) sampleroverride = SamplerClampY;
else if (drawpoly_trepeat) sampleroverride = SamplerClampX; else if (drawpoly_trepeat) sampleroverride = SamplerClampX;
else sampleroverride = -1; else sampleroverride = SamplerClampXY;
bool success = GLInterface.SetTexture(TileFiles.tiles[globalpicnum], globalpal, method, sampleroverride); bool success = GLInterface.SetTexture(TileFiles.tiles[globalpicnum], globalpal, method, sampleroverride);

View file

@ -129,45 +129,7 @@ void copybufbyte(const void *s, void *d, int32_t c)
// *and* x86_64, and the C version otherwise. // *and* x86_64, and the C version otherwise.
// XXX: we don't honor NOASM in the x86_64 case. // XXX: we don't honor NOASM in the x86_64 case.
#if defined(__GNUC__) && defined(__x86_64__) #if !defined pragmas_have_copybufreverse
// NOTE: Almost CODEDUP from x86 GCC assembly version, except that
// - %%esi -> %%rsi
// - %%edi -> %%rdi
// - (dec,inc,sub,add)l suffix removed where necessary
void copybufreverse(const void *S, void *D, int32_t c)
{
__asm__ __volatile__(
"shrl $1, %%ecx\n\t"
"jnc 0f\n\t" // jnc skipit1
"movb (%%rsi), %%al\n\t"
"dec %%rsi\n\t"
"movb %%al, (%%rdi)\n\t"
"inc %%rdi\n\t"
"0:\n\t" // skipit1:
"shrl $1, %%ecx\n\t"
"jnc 1f\n\t" // jnc skipit2
"movw -1(%%rsi), %%ax\n\t"
"sub $2, %%rsi\n\t"
"rorw $8, %%ax\n\t"
"movw %%ax, (%%rdi)\n\t"
"add $2, %%rdi\n\t"
"1:\n\t" // skipit2
"testl %%ecx, %%ecx\n\t"
"jz 3f\n\t" // jz endloop
"2:\n\t" // begloop
"movl -3(%%rsi), %%eax\n\t"
"sub $4, %%rsi\n\t"
"bswapl %%eax\n\t"
"movl %%eax, (%%rdi)\n\t"
"add $4, %%rdi\n\t"
"decl %%ecx\n\t"
"jnz 2b\n\t" // jnz begloop
"3:"
: "+S"(S), "+D"(D), "+c"(c) :
: "eax", "memory", "cc"
);
}
#elif !defined pragmas_have_copybufreverse
void copybufreverse(const void *s, void *d, int32_t c) void copybufreverse(const void *s, void *d, int32_t c)
{ {
auto src = (const char *)s; auto src = (const char *)s;

View file

@ -1,4 +1,3 @@
#ifdef USE_OPENGL
#include "baselayer.h" #include "baselayer.h"
#include "build.h" #include "build.h"
@ -15,6 +14,9 @@
#include "bitmap.h" #include "bitmap.h"
#include "../../glbackend/glbackend.h" #include "../../glbackend/glbackend.h"
extern int r_detailmapping, r_glowmapping, usehightile, r_useindexedcolortextures;
extern int fixpalette, fixpalswap;
#if 0 #if 0
void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth) void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth)
@ -99,18 +101,6 @@ static void polymost_setupsampler(FHardwareTexture* tex, const int32_t dameth, i
} }
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];
}
}
}
void gloadtile_art(int32_t dapic, int32_t dameth, pthtyp* pth, int32_t doalloc) void gloadtile_art(int32_t dapic, int32_t dameth, pthtyp* pth, int32_t doalloc)
{ {
vec2_16_t const& tsizart = tilesiz[dapic]; vec2_16_t const& tsizart = tilesiz[dapic];
@ -229,77 +219,8 @@ int32_t gloadtile_hi(int32_t dapic, int32_t dapalnum, int32_t facen, hicreplctyp
globaltexcache texcache; globaltexcache texcache;
static pthtyp *texcache_tryart(int32_t const dapicnum, int32_t const dapalnum, int32_t const dashade, int32_t dameth)
{
const int32_t j = dapicnum&(GLTEXCACHEADSIZ-1);
pthtyp *pth;
int32_t tintpalnum = -1;
int32_t searchpalnum = dapalnum;
polytintflags_t const tintflags = hictinting[dapalnum].f;
if (tintflags & (HICTINT_USEONART))
{
tintpalnum = dapalnum;
if (!(tintflags & HICTINT_APPLYOVERPALSWAP))
searchpalnum = 0;
}
// load from art
for (pth=texcache.list[j]; pth; pth=pth->next)
if (pth->picnum == dapicnum && ((pth->flags & (PTH_INDEXED|PTH_HIGHTILE)) == PTH_INDEXED))
{
if (pth->flags & PTH_INVALIDATED)
{
pth->flags &= ~PTH_INVALIDATED;
gloadtile_art(dapicnum, dameth, pth, 0);
pth->palnum = dapalnum;
}
return pth;
}
pth = (pthtyp *)Xcalloc(1,sizeof(pthtyp));
gloadtile_art(dapicnum, dameth, pth, 1);
pth->palnum = dapalnum;
pth->next = texcache.list[j];
texcache.list[j] = pth;
return pth;
}
#if 0
pthtyp *texcache_fetchmulti(pthtyp *pth, hicreplctyp *si, int32_t dapicnum, int32_t dameth)
{
const int32_t j = dapicnum&(GLTEXCACHEADSIZ-1);
int32_t i;
for (i = 0; i <= (GLTEXCACHEADSIZ - 1); i++)
{
const pthtyp *pth2;
for (pth2=texcache.list[i]; pth2; pth2=pth2->next)
{
if (pth2->hicr && pth2->hicr->filename && si->filename && filnamcmp(pth2->hicr->filename, si->filename) == 0)
{
Bmemcpy(pth, pth2, sizeof(pthtyp));
pth->picnum = dapicnum;
pth->flags = PTH_HIGHTILE | (drawingskybox>0)*PTH_SKYBOX;
if (pth2->flags & PTH_HASALPHA)
pth->flags |= PTH_HASALPHA;
pth->hicr = si;
pth->next = texcache.list[j];
texcache.list[j] = pth;
return pth;
}
}
}
return NULL;
}
#endif
// <dashade>: ignored if not in Polymost+r_usetileshades // <dashade>: ignored if not in Polymost+r_usetileshades
pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int32_t dameth) pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int32_t dameth)
@ -379,94 +300,171 @@ pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int3
} }
extern int r_detailmapping, r_glowmapping, usehightile; #endif
bool GLInstance::ApplyTextureProps()
template<class T>
void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch)
{ {
int pal = palmanager.ActivePalswap(); for (int i = 0; i < x; ++i)
if (currentTexture == nullptr) return false;
auto rep = currentTexture->FindReplacement(pal);
VSMatrix texmat;
bool changed = false;
// texture scale
if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f)))
{ {
texmat.loadIdentity(); for (int j = 0; j < y; ++j)
texmat.scale(rep->scale.x, rep->scale.y, 1.0f);
GLInterface.SetMatrix(Matrix_Texture, &texmat);
}
if (r_detailmapping)
{
auto detailrep = currentTexture->FindReplacement(DETAILPAL);
if (detailrep)
{ {
UseDetailMapping(true); dst[i * y + j] = src[i + j * srcpitch];
//BindTexture(3, detailrep->faces[0], SamplerRepeat);
texmat.loadIdentity();
bool scaled = false;
if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f)))
{
texmat.scale(rep->scale.x, rep->scale.y, 1.0f);
scaled = true;
}
if ((detailrep->scale.x != 1.0f) || (detailrep->scale.y != 1.0f))
{
texmat.scale(detailrep->scale.x, detailrep->scale.y, 1.0f);
scaled = true;
}
if (scaled) GLInterface.SetMatrix(Matrix_Detail, &texmat);
changed |= scaled;
} }
} }
// glow texture
if (r_glowmapping)
{
auto glowrep = currentTexture->FindReplacement(GLOWPAL);
if (glowrep)
{
UseGlowMapping(true);
//BindTexture(4, glowrep->faces[0], SamplerRepeat);
}
}
auto brightrep = currentTexture->FindReplacement(BRIGHTPAL);
if (brightrep)
{
//UseGlowMapping(true);
//BindTexture(5, glowrep->faces[0], SamplerRepeat);
}
return false; // true if the matrices were changed, false otherwise
} }
//===========================================================================
//
// Create an indexed version of the requested texture
//
//===========================================================================
void GLInstance::SetTexture(FTexture* tex, int palette, int method) FHardwareTexture* CreateIndexedTexture(FTexture* tex)
{ {
auto siz = tex->GetSize();
bool npoty = false;
GLInterface.SetPalswap(fixpalswap >= 1 ? fixpalswap - 1 : globalpal); const uint8_t* p = tex->Get8BitPixels();
GLInterface.SetPalette(fixpalette >= 1 ? fixpalette - 1 : curbasepal); TArray<uint8_t> store(siz.x * siz.y, true);
if (!p)
{
tex->Create8BitPixels(store.Data());
p = store.Data();
}
auto glpic = GLInterface.NewTexture();
glpic->CreateTexture(siz.x, siz.y, true, false);
pthtyp* pth = texcache_fetch(globalpicnum, globalpal, getpalookup(1, globalshade), method | PTH_INDEXED); TArray<uint8_t> flipped(siz.x * siz.y, true);
GLInterface.BindTexture(0, pth->glpic, mSampler); FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y);
glpic->LoadTexture(flipped.Data());
return glpic;
}
// Fixme: Alpha test on shaders must be done differently. //===========================================================================
// Also: Consider a texture's alpha threshold. //
float const al = alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f / 255.f) : // Retrieve the texture to be used.
(pth->hicr && pth->hicr->alphacut >= 0.f ? pth->hicr->alphacut : 0.f); //
//===========================================================================
FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
{
if (textype == TT_TRUECOLOR && palid == 0) textype = TT_HICREPLACE; // true color tiles with the base palette won't get processed.
if (textype == TT_INDEXED)
{
auto hwtex = tex->GetHardwareTexture(-1);
if (hwtex) return hwtex;
else
{
hwtex = CreateIndexedTexture(tex);
tex->SetHardwareTexture(-1, hwtex);
return hwtex;
}
}
}
//===========================================================================
//
// Sets a texture for rendering
//
//===========================================================================
bool GLInstance::SetTexture(FTexture* tex, int palette, int method, int sampleroverride)
{
int usepalette = fixpalette >= 1 ? fixpalette - 1 : curbasepal;
int usepalswap = fixpalswap >= 1 ? fixpalswap - 1 : palette;
GLInterface.SetPalette(usepalette);
GLInterface.SetPalswap(usepalswap);
TextureType = r_useindexedcolortextures? TT_INDEXED : TT_TRUECOLOR;
int lookuppal = 0;
VSMatrix texmat;
auto rep = usehightile? currentTexture->FindReplacement(palette) : nullptr;
if (rep)
{
// Hightile replacements have only one texture representation and it is always the base.
tex = rep->faces[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 (!r_useindexedcolortextures) lookuppal = palmanager.LookupPalette(usepalette, usepalswap);
}
// Load the main texture
auto mtex = LoadTexture(tex, TextureType, lookuppal);
if (mtex)
{
auto sampler = (method & DAMETH_CLAMPED) ? (sampleroverride != -1 ? sampleroverride : SamplerClampXY) : SamplerRepeat;
BindTexture(0, mtex, sampler);
if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f)))
{
texmat.loadIdentity();
texmat.scale(rep->scale.x, rep->scale.y, 1.0f);
GLInterface.SetMatrix(Matrix_Texture, &texmat);
MatrixChange |= 1;
}
// Also load additional layers needed for this texture.
if (r_detailmapping && usehightile)
{
auto drep = currentTexture->FindReplacement(DETAILPAL);
if (drep)
{
auto htex = LoadTexture(drep->faces[0], TT_HICREPLACE, 0);
UseDetailMapping(true);
BindTexture(3, htex, SamplerRepeat);
texmat.loadIdentity();
if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f)))
{
texmat.scale(rep->scale.x, rep->scale.y, 1.0f);
MatrixChange |= 2;
}
if ((drep->scale.x != 1.0f) || (drep->scale.y != 1.0f))
{
texmat.scale(drep->scale.x, drep->scale.y, 1.0f);
MatrixChange |= 2;
}
if (MatrixChange & 2) GLInterface.SetMatrix(Matrix_Detail, &texmat);
}
}
if (r_glowmapping && usehightile)
{
auto drep = currentTexture->FindReplacement(GLOWPAL);
if (drep)
{
auto htex = LoadTexture(drep->faces[0], TT_HICREPLACE, 0);
UseGlowMapping(true);
BindTexture(4, htex, SamplerRepeat);
}
}
auto brep = currentTexture->FindReplacement(BRIGHTPAL);
if (brep)
{
auto htex = LoadTexture(brep->faces[0], TT_HICREPLACE, 0);
BindTexture(5, mtex, sampler);
}
}
float al = 0;
if (TextureType == TT_HICREPLACE)
{
al = /*alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f / 255.f) :*/
(tex->alphaThreshold >= 0.f ? tex->alphaThreshold : 0.f);
}
GLInterface.SetAlphaThreshold(al); GLInterface.SetAlphaThreshold(al);
} }
#endif
#endif

View file

@ -1188,7 +1188,8 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
} }
VSMatrix identity(0); VSMatrix identity(0);
GLInterface.SetMatrix(Matrix_ModelView, &identity); GLInterface.SetMatrix(Matrix_ModelView, &identity);
return 1; GLInterface.SetTinting(0, 0, PalEntry(255, 255, 255));
return 1;
} }
#endif #endif

View file

@ -43,6 +43,7 @@
class FImageSource; class FImageSource;
class FTexture; class FTexture;
class FHardwareTexture;
// picanm[].sf: // picanm[].sf:
// |bit(1<<7) // |bit(1<<7)
@ -249,6 +250,16 @@ public:
Hightiles.Clear(); Hightiles.Clear();
} }
void SetHardwareTexture(int palid, FHardwareTexture* htex)
{
HardwareTextures.Insert(palid, htex);
}
FHardwareTexture* GetHardwareTexture(int palid)
{
auto k = HardwareTextures.CheckKey(palid);
return k ? *k : nullptr;
}
HightileReplacement * FindReplacement(int palnum, bool skybox = false); HightileReplacement * FindReplacement(int palnum, bool skybox = false);
int alphaThreshold = 128; int alphaThreshold = 128;
@ -299,6 +310,8 @@ protected:
intptr_t CacheHandle = 0; // For tiles that do not have a static image but get accessed by the software renderer. intptr_t CacheHandle = 0; // For tiles that do not have a static image but get accessed by the software renderer.
uint8_t CacheLock = 0; uint8_t CacheLock = 0;
TArray<HightileReplacement> Hightiles; TArray<HightileReplacement> Hightiles;
// Don't waste too much effort on efficient storage here. Polymost performs so many calculations on a single draw call that the minor map lookup hardly matters.
TMap<int, FHardwareTexture*> HardwareTextures; // Note: These must be deleted by the backend. When the texture manager is taken down it may already be too late to delete them.
FTexture (const char *name = NULL); FTexture (const char *name = NULL);
}; };

View file

@ -39,6 +39,7 @@
#include "baselayer.h" #include "baselayer.h"
#include "resourcefile.h" #include "resourcefile.h"
#include "imagehelpers.h"
//=========================================================================== //===========================================================================
// //
@ -168,6 +169,10 @@ void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient)
return; return;
} }
palettemap[index] = FindPalette(data); palettemap[index] = FindPalette(data);
if (index == 0)
{
ImageHelpers::SetPalette((PalEntry*)data); // Palette 0 is always the reference for downconverting images
}
} }
//=========================================================================== //===========================================================================
@ -251,3 +256,24 @@ void PaletteManager::BindPalswap(int index)
} }
int PaletteManager::LookupPalette(int palette, int palswap)
{
int realpal = palettemap[palette];
int realswap = palswapmap[palswap];
int combined = realpal * 0x10000 + realswap;
int* combinedindex = swappedpalmap.CheckKey(combined);
if (combinedindex) return *combinedindex;
PaletteData* paldata = &palettes[realpal];
PalswapData* swapdata = &palswaps[realswap];
PalEntry swappedpalette[256];
for (int i = 0; i < 256; i++)
{
int swapi = swapdata->lookup[i];
swappedpalette[i] = paldata->colors[swapi];
}
int palid = FindPalette((uint8_t*)swappedpalette);
swappedpalmap.Insert(combined, palid);
return palid;
}

View file

@ -62,6 +62,7 @@ class PaletteManager
// All data is being stored in contiguous blocks that can be used as uniform buffers as-is. // All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
TArray<PaletteData> palettes; TArray<PaletteData> palettes;
TArray<PalswapData> palswaps; TArray<PalswapData> palswaps;
TMap<int, int> swappedpalmap;
FHardwareTexture* palswapTexture = nullptr; FHardwareTexture* palswapTexture = nullptr;
GLInstance* const inst; GLInstance* const inst;
@ -81,6 +82,7 @@ public:
void BindPalette(int index); void BindPalette(int index);
void BindPalswap(int index); void BindPalswap(int index);
int ActivePalswap() const { return lastsindex; } int ActivePalswap() const { return lastsindex; }
int LookupPalette(int palette, int palswap);
}; };
@ -186,6 +188,14 @@ enum EWinding
Winding_CCW, Winding_CCW,
Winding_CW Winding_CW
}; };
enum ETexType
{
TT_INDEXED,
TT_TRUECOLOR,
TT_HICREPLACE
};
class GLInstance class GLInstance
{ {
enum enum
@ -202,6 +212,8 @@ class GLInstance
int lastPalswapIndex = -1; int lastPalswapIndex = -1;
FHardwareTexture* texv; FHardwareTexture* texv;
FTexture* currentTexture = nullptr; FTexture* currentTexture = nullptr;
int TextureType;
int MatrixChange = 0;
VSMatrix matrices[NUMMATRICES]; VSMatrix matrices[NUMMATRICES];
@ -279,7 +291,7 @@ public:
void SetSurfaceShader(); void SetSurfaceShader();
void SetVPXShader(); void SetVPXShader();
void SetPalette(int palette); void SetPalette(int palette);
bool ApplyTextureProps(); bool ApplyTextureProps(FTexture *tex, int pal);
void RestoreTextureProps(); void RestoreTextureProps();
void ReadPixels(int w, int h, uint8_t* buffer); void ReadPixels(int w, int h, uint8_t* buffer);
@ -365,6 +377,8 @@ public:
// not yet implemented - only relevant for hires replacements. // not yet implemented - only relevant for hires replacements.
} }
FHardwareTexture* CreateIndexedTexture(FTexture* tex);
FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);
bool SetTexture(FTexture* tex, int palette, int method, int sampleroverride = -1); bool SetTexture(FTexture* tex, int palette, int method, int sampleroverride = -1);
}; };