Polymost: r_npotwallmode, emulating 8-bit for walls w/ nonpow2 height textures.

When that mode is enabled (see below for caveats), wall textures that have a
non-power-of-two height (call it 'h') will be modified to look like in classic:
Let 'H' be the next power of two greater than 'h'. The texture will be uploaded
with height 'H', made up from 'h' hlines of the original texture, followed by
'H'-'h' first hlines of the same.
No panning "corrections" will take place. The mode is disabled by default.

Caveats/notes:
 * the mode requires that r_hightile is disabled
 * it is not implemented in Polymer
 * in the Lunatic build, it is ineffective when a VX map is loaded, as those
   display walls with NPOT height textures correctly

git-svn-id: https://svn.eduke32.com/eduke32@4498 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2014-06-01 11:55:19 +00:00
parent d4cfdb7da0
commit 1e5549dc2f
5 changed files with 79 additions and 13 deletions

View file

@ -52,6 +52,7 @@ extern float alphahackarray[MAXTILES];
extern int32_t r_usenewshading;
extern int32_t r_usetileshades;
extern int32_t r_npotwallmode;
extern int16_t globalpicnum;
extern int32_t globalpal;
@ -94,16 +95,34 @@ static inline int32_t fogpal_shade(const sectortype *sec, int32_t shade)
return sec->fogpal ? 0 : shade;
}
static inline int check_nonpow2(int32_t xsiz, int32_t ysiz)
static inline int check_nonpow2(int32_t x)
{
return (xsiz > 1 && (xsiz&(xsiz-1)))
|| (ysiz > 1 && (ysiz&(ysiz-1)));
return (x > 1 && (x&(x-1)));
}
// Are we using the mode that uploads non-power-of-two wall textures like they
// render in classic?
static inline int polymost_is_npotmode(void)
{
// The glinfo.texnpot check is so we don't have to deal with that case in
// gloadtile_art().
return glinfo.texnpot &&
// r_npotwallmode is NYI for hightiles. We require r_hightile off
// because in calc_ypanning(), the repeat would be multiplied by a
// factor even if no modified texture were loaded.
!usehightile &&
#ifdef NEW_MAP_FORMAT
g_loadedMapVersion < 10 &&
#endif
r_npotwallmode;
}
// Flags of the <dameth> argument of various functions
enum {
DAMETH_CLAMPED = 4,
DAMETH_WALL = 32, // signals a texture for a wall (for r_npotwallmode)
DAMETH_NOCOMPRESS = 4096,
DAMETH_HI = 8192,
};
@ -111,6 +130,13 @@ enum {
// DAMETH_CLAMPED -> PTH_CLAMPED conversion
#define TO_PTH_CLAMPED(dameth) ((((dameth)&4))>>2)
// Do we want a NPOT-y-as-classic texture for this <dameth> and <ysiz>?
static inline int polymost_want_npotytex(int32_t dameth, int32_t ysiz)
{
return getrendermode() != REND_POLYMER && // r_npotwallmode NYI in Polymer
polymost_is_npotmode() && (dameth&DAMETH_WALL) && check_nonpow2(ysiz);
}
// pthtyp pth->flags bits
enum {
PTH_CLAMPED = 1,
@ -118,6 +144,7 @@ enum {
PTH_SKYBOX = 4,
PTH_HASALPHA = 8,
PTH_HASFULLBRIGHT = 16,
PTH_NPOTWALL = DAMETH_WALL, // r_npotwallmode=1 generated texture
PTH_INVALIDATED = 128,
};

View file

@ -877,7 +877,7 @@ int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf)
if (glinfo.texcompr && glusetexcompr && glusetexcache)
if (!gotcache)
{
const int32_t nonpow2 = check_nonpow2(xsiz, ysiz);
const int32_t nonpow2 = check_nonpow2(xsiz) || check_nonpow2(ysiz);
// save off the compressed version
cachead.quality = r_downsize;

View file

@ -2813,6 +2813,9 @@ static int32_t polymer_initwall(int16_t wallnum)
return (1);
}
// TODO: r_npotwallmode. Needs polymost_is_npotmode() handling among others.
#define DAMETH_WALL 0
static float calc_ypancoef(char curypanning, int16_t curpicnum, int32_t dopancor)
{
#ifdef NEW_MAP_FORMAT
@ -2967,7 +2970,7 @@ static void polymer_updatewall(int16_t wallnum)
else
curpicnum = walloverpicnum;
polymer_getbuildmaterial(&w->wall.material, curpicnum, wal->pal, wal->shade, sec->visibility, 0);
polymer_getbuildmaterial(&w->wall.material, curpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL);
if (wal->cstat & 4)
yref = sec->floorz;
@ -3037,7 +3040,7 @@ static void polymer_updatewall(int16_t wallnum)
curxpanning = wall[refwall].xpanning;
curypanning = wall[refwall].ypanning;
polymer_getbuildmaterial(&w->wall.material, curpicnum, curpal, curshade, sec->visibility, 0);
polymer_getbuildmaterial(&w->wall.material, curpicnum, curpal, curshade, sec->visibility, DAMETH_WALL);
if (!(wall[refwall].cstat&4))
yref = nsec->floorz;
@ -3104,12 +3107,12 @@ static void polymer_updatewall(int16_t wallnum)
else
curpicnum = wallpicnum;
polymer_getbuildmaterial(&w->over.material, curpicnum, wal->pal, wal->shade, sec->visibility, 0);
polymer_getbuildmaterial(&w->over.material, curpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL);
if ((wal->cstat & 16) || (wal->cstat & 32))
{
// mask
polymer_getbuildmaterial(&w->mask.material, walloverpicnum, wal->pal, wal->shade, sec->visibility, 0);
polymer_getbuildmaterial(&w->mask.material, walloverpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL);
if (wal->cstat & 128)
{

View file

@ -117,6 +117,7 @@ int32_t shadescale_unbounded = 0;
int32_t r_usenewshading = 3;
int32_t r_usetileshades = 2;
int32_t r_npotwallmode = 0;
static double gviewxrange, ghoriz;
double gyxscale, gxyaspect, ghalfx, grhalfxdown10, grhalfxdown10x;
@ -898,7 +899,7 @@ static void texture_setup(int32_t dameth)
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
{
coltype *pic;
int32_t xsiz, ysiz;
int32_t xsiz, ysiz, npoty = 0;
char hasalpha = 0, hasfullbright = 0;
static int32_t fullbrightloadingpass = 0;
@ -999,6 +1000,25 @@ void gloadtile_art(int32_t dapic, int32_t dapal, int32_t dashade, int32_t dameth
bglBindTexture(GL_TEXTURE_2D,pth->glpic);
fixtransparency(dapic, pic,tsizx,tsizy,xsiz,ysiz,dameth);
if (polymost_want_npotytex(dameth, ysiz) &&
tsizx==xsiz && tsizy==ysiz) // XXX
{
const int32_t nextpoty = 1<<((picsiz[dapic]>>4)+1);
const int32_t ydif = nextpoty - ysiz;
coltype *paddedpic;
Bassert(ydif > 0 && ydif < ysiz);
paddedpic = Xrealloc(pic, xsiz*nextpoty*sizeof(coltype));
pic = paddedpic;
Bmemcpy(&pic[xsiz*ysiz], pic, xsiz*ydif*sizeof(coltype));
ysiz = tsizy = nextpoty;
npoty = PTH_NPOTWALL;
}
uploadtexture(doalloc,xsiz,ysiz,hasalpha?GL_RGBA:GL_RGB,GL_RGBA,pic,tsizx,tsizy,dameth);
texture_setup(dameth);
@ -1009,7 +1029,7 @@ void gloadtile_art(int32_t dapic, int32_t dapal, int32_t dashade, int32_t dameth
pth->palnum = dapal;
pth->shade = dashade;
pth->effects = 0;
pth->flags = TO_PTH_CLAMPED(dameth) | (hasalpha*PTH_HASALPHA);
pth->flags = TO_PTH_CLAMPED(dameth) | (hasalpha*PTH_HASALPHA) | npoty;
pth->hicr = NULL;
if (hasfullbright && !fullbrightloadingpass)
@ -1274,7 +1294,7 @@ int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp
if (glinfo.texcompr && glusetexcompr && glusetexcache && !(hicr->flags & HICR_NOSAVE))
if (!gotcache)
{
const int32_t nonpow2 = check_nonpow2(xsiz, ysiz);
const int32_t nonpow2 = check_nonpow2(xsiz) || check_nonpow2(ysiz);
// save off the compressed version
if (hicr->flags & HICR_NOCOMPRESS) cachead.quality = 0;
@ -2290,7 +2310,12 @@ static void calc_ypanning(int32_t refposz, double ryp0, double ryp1,
i = tilesizy[globalpicnum];
else
#endif
if (dopancor)
if (polymost_is_npotmode())
{
t *= (double)tilesizy[globalpicnum] / i;
i = tilesizy[globalpicnum];
}
else if (dopancor)
{
// Carry out panning "correction" to make it look like classic in some
// cases, but failing in the general case.
@ -2959,6 +2984,9 @@ static void polymost_drawalls(int32_t bunch)
// (gvx*x0 + gvy*fy0 + gvo*1) = t
ogux = gux; oguy = guy; oguo = guo;
Bassert(domostpolymethod == 0);
domostpolymethod = DAMETH_WALL;
if (nextsectnum >= 0)
{
getzsofslope(nextsectnum,(int32_t)nx0,(int32_t)ny0,&cz,&fz);
@ -3065,6 +3093,8 @@ static void polymost_drawalls(int32_t bunch)
pow2xsplit = 1; domost(x0,-10000,x1,-10000);
}
domostpolymethod = 0;
if (nextsectnum >= 0)
if ((!(gotsector[nextsectnum>>3]&pow2char[nextsectnum&7])) && (testvisiblemost(x0,x1)))
polymost_scansector(nextsectnum);
@ -3615,6 +3645,7 @@ void polymost_drawmaskwall(int32_t damaskwallcnt)
method = 1; pow2xsplit = 1;
if (wal->cstat&128) { if (!(wal->cstat&512)) method = 2; else method = 3; }
method |= DAMETH_WALL;
calc_and_apply_fog(wal->picnum, fogpal_shade(sec, wal->shade), sec->visibility, get_floor_fogpal(sec));
@ -5181,6 +5212,10 @@ void polymost_initosdfuncs(void)
{ "r_swapinterval","sets the GL swap interval (VSync)",(void *) &vsync, CVAR_INT|CVAR_FUNCPTR, -1, 1 },
{ "r_texcache","enable/disable OpenGL compressed texture cache",(void *) &glusetexcache, CVAR_INT, 0, 2 },
{ "r_memcache","enable/disable texture cache memory cache",(void *) &glusememcache, CVAR_BOOL, 0, 1 },
{
"r_npotwallmode", "enable/disable emulation of walls with non-power-of-two height textures (Polymost, r_hightile 0)",
(void *) &r_npotwallmode, CVAR_BOOL, 0, 1
},
{ "r_texcompr","enable/disable OpenGL texture compression",(void *) &glusetexcompr, CVAR_BOOL, 0, 1 },
{ "r_textureanisotropy", "changes the OpenGL texture anisotropy setting", (void *) &glanisotropy, CVAR_INT|CVAR_FUNCPTR, 0, 16 },
{ "r_texturemaxsize","changes the maximum OpenGL texture size limit",(void *) &gltexmaxsize, CVAR_INT | CVAR_NOSAVE, 0, 4096 },

View file

@ -123,7 +123,8 @@ tryart:
// load from art
for (pth=texcache.list[j]; pth; pth=pth->next)
if (pth->picnum == dapicnum && pth->palnum == dapalnum && pth->shade == dashade &&
(pth->flags & (PTH_CLAMPED+PTH_HIGHTILE)) == TO_PTH_CLAMPED(dameth)
(pth->flags & (PTH_CLAMPED+PTH_HIGHTILE)) == TO_PTH_CLAMPED(dameth) &&
polymost_want_npotytex(dameth, tilesizy[dapicnum]) == !!(pth->flags&PTH_NPOTWALL)
)
{
if (pth->flags & PTH_INVALIDATED)