From 1e5549dc2f2406bda8319c548293c169626f4a85 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 1 Jun 2014 11:55:19 +0000 Subject: [PATCH] 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 --- polymer/eduke32/build/include/polymost.h | 33 ++++++++++++++++-- polymer/eduke32/build/src/mdsprite.c | 2 +- polymer/eduke32/build/src/polymer.c | 11 +++--- polymer/eduke32/build/src/polymost.c | 43 +++++++++++++++++++++--- polymer/eduke32/build/src/texcache.c | 3 +- 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/polymer/eduke32/build/include/polymost.h b/polymer/eduke32/build/include/polymost.h index 1f1b91f5e..11edb09c6 100644 --- a/polymer/eduke32/build/include/polymost.h +++ b/polymer/eduke32/build/include/polymost.h @@ -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 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 and ? +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, }; diff --git a/polymer/eduke32/build/src/mdsprite.c b/polymer/eduke32/build/src/mdsprite.c index 2f74f1607..9f0ae69e4 100644 --- a/polymer/eduke32/build/src/mdsprite.c +++ b/polymer/eduke32/build/src/mdsprite.c @@ -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; diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index f988094b6..22ef800eb 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -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) { diff --git a/polymer/eduke32/build/src/polymost.c b/polymer/eduke32/build/src/polymost.c index 6478af840..322e5cc14 100644 --- a/polymer/eduke32/build/src/polymost.c +++ b/polymer/eduke32/build/src/polymost.c @@ -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 }, diff --git a/polymer/eduke32/build/src/texcache.c b/polymer/eduke32/build/src/texcache.c index 794938e9d..9d4e31911 100644 --- a/polymer/eduke32/build/src/texcache.c +++ b/polymer/eduke32/build/src/texcache.c @@ -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)