diff --git a/polymer/eduke32/build/include/polymer.h b/polymer/eduke32/build/include/polymer.h index a13c5abdd..1e6b04ec1 100644 --- a/polymer/eduke32/build/include/polymer.h +++ b/polymer/eduke32/build/include/polymer.h @@ -52,6 +52,7 @@ extern float pr_parallaxbias; extern int32_t pr_overridespecular; extern float pr_specularpower; extern float pr_specularfactor; +extern int32_t pr_highpalookups; extern int32_t pr_ati_fboworkaround; extern int32_t pr_ati_nodepthoffset; #ifdef __APPLE__ @@ -156,6 +157,11 @@ typedef struct s_prrograminfo { } _prprograminfo; #define PR_INFO_LOG_BUFFER_SIZE 8192 +#define PR_HIGHPALOOKUP_BIT_DEPTH 7 +#define PR_HIGHPALOOKUP_DIM (1 << PR_HIGHPALOOKUP_BIT_DEPTH) +#define PR_HIGHPALOOKUP_DATA_SIZE (4 * PR_HIGHPALOOKUP_DIM * \ + PR_HIGHPALOOKUP_DIM * \ + PR_HIGHPALOOKUP_DIM) typedef struct s_prprogrambit { int32_t bit; @@ -259,6 +265,11 @@ typedef struct s_prmirror { int16_t wallnum; } _prmirror; +typedef struct s_prhighpalookup { + char *data; + GLuint map; +} _prhighpalookup; + typedef void (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t); typedef struct s_pranimatespritesinfo { @@ -283,6 +294,7 @@ int16_t polymer_addlight(_prlight* light); void polymer_deletelight(int16_t lighti); void polymer_invalidatelights(void); void polymer_texinvalidate(void); +void polymer_definehighpalookup(char palnum, char *fn); # ifdef POLYMER_C diff --git a/polymer/eduke32/build/src/defs.c b/polymer/eduke32/build/src/defs.c index 09156e4b8..264574b0e 100644 --- a/polymer/eduke32/build/src/defs.c +++ b/polymer/eduke32/build/src/defs.c @@ -63,6 +63,7 @@ enum scripttoken_t T_VOXEL, T_SKYBOX, T_FRONT,T_RIGHT,T_BACK,T_LEFT,T_TOP,T_BOTTOM, + T_HIGHPALOOKUP, T_TINT,T_RED,T_GREEN,T_BLUE, T_TEXTURE,T_ALPHACUT,T_XSCALE,T_YSCALE,T_SPECPOWER,T_SPECFACTOR,T_NOCOMPRESS,T_NODOWNSIZE, T_UNDEFMODEL,T_UNDEFMODELRANGE,T_UNDEFMODELOF,T_UNDEFTEXTURE,T_UNDEFTEXTURERANGE, @@ -140,6 +141,7 @@ static int32_t defsparser(scriptfile *script) { "model", T_MODEL }, { "voxel", T_VOXEL }, { "skybox", T_SKYBOX }, + { "highpalookup", T_HIGHPALOOKUP }, { "tint", T_TINT }, { "texture", T_TEXTURE }, { "tile", T_TEXTURE }, @@ -1427,6 +1429,88 @@ static int32_t defsparser(scriptfile *script) hicsetskybox(tile,pal,fn); } break; + case T_HIGHPALOOKUP: + { + char *highpaltokptr = script->ltextptr; + int32_t pal=-1, oldpathsearchmode, fd, datasize, dataread; + char *fn = NULL, *tfn = NULL; + char *highpalend; + char *highpaldata; + + static const tokenlist highpaltokens[] = + { + { "pal", T_PAL }, + { "file", T_FILE } + }; + + if (scriptfile_getbraces(script,&highpalend)) break; + while (script->textptr < highpalend) + { + switch (getatoken(script,highpaltokens,sizeof(highpaltokens)/sizeof(tokenlist))) + { + case T_PAL: + scriptfile_getsymbol(script,&pal); break; + case T_FILE: + scriptfile_getstring(script,&fn); break; + } + } + + if ((unsigned)pal >= ((unsigned)MAXPALOOKUPS - RESERVEDPALS)) + { + initprintf("Error: missing or invalid 'palette number' for highpalookup definition near " + "line %s:%d\n", script->filename, scriptfile_getlinum(script,highpaltokptr)); + break; + } + if (!fn) + { + initprintf("Error: missing 'file name' for highpalookup definition near line %s:%d\n", + script->filename, scriptfile_getlinum(script,highpaltokptr)); + break; + } + + oldpathsearchmode = pathsearchmode; + pathsearchmode = 1; + if (findfrompath(fn,&tfn) < 0) + { + char buf[BMAX_PATH]; + + Bstrcpy(buf,fn); + kzfindfilestart(buf); + if (!kzfindfile(buf)) + { + initprintf("Error: file '%s' does not exist\n",fn); + pathsearchmode = oldpathsearchmode; + break; + } + } + else Bfree(tfn); + pathsearchmode = oldpathsearchmode; + + // load the highpalookup and send it to polymer + datasize = PR_HIGHPALOOKUP_DATA_SIZE; + + highpaldata = Bmalloc(datasize); + + fd = kopen4load(fn, 0); + // skip the TGA header + klseek(fd, 18, SEEK_SET); + + dataread = 0; + + while (1) { + dataread += kread(fd, highpaldata + dataread, datasize - dataread); + if (dataread == datasize) + break; + } + + // ignore whatever image editors might have put after the interesting stuff + kclose(fd); + + polymer_definehighpalookup(pal, highpaldata); + + Bfree(highpaldata); + } + break; case T_TINT: { char *tinttokptr = script->ltextptr; diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index 57e257697..38b018faf 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -30,6 +30,7 @@ float pr_parallaxbias = 0.0f; int32_t pr_overridespecular = 0; float pr_specularpower = 15.0f; float pr_specularfactor = 1.0f; +int32_t pr_highpalookups = 1; int32_t pr_ati_fboworkaround = 0; int32_t pr_ati_nodepthoffset = 0; @@ -43,6 +44,7 @@ _prsector *prsectors[MAXSECTORS]; _prwall *prwalls[MAXWALLS]; _prsprite *prsprites[MAXSPRITES]; _prmaterial mdspritematerial; +_prhighpalookup prhighpalookups[MAXPALOOKUPS]; static const GLfloat vertsprite[4 * 5] = { @@ -578,9 +580,6 @@ int32_t globaloldoverridematerial; // RENDER TARGETS _prrt *prrts; -// HIGHPALOOKUP MAP NAMES -GLuint globalhighpalookupmap; - // CONTROL GLfloat spritemodelview[16]; GLfloat mdspritespace[4][4]; @@ -673,60 +672,34 @@ int32_t polymer_init(void) polymer_initrendertargets(pr_shadowcount + 1); - // test highpalookup - int32_t j, k; - int32_t xbits = 6, ybits = 6, zbits = 6; // depth - int32_t x = 1 << xbits, y = 1 << ybits, z = 1 << zbits; // dimensions - int32_t bitdiff; - coltype *highpalookup; - - highpalookup = malloc(x*y*z*sizeof(coltype)); - - k = 0; - while (k < z) { - j = 0; - while (j < y) { - i = 0; - while (i < x) { - bitdiff = 8 - xbits; - highpalookup[k * z * y + j * y + i].r = (i << bitdiff) | (i & ((1 << bitdiff) - 1)); - - bitdiff = 8 - ybits; - highpalookup[k * z * y + j * y + i].g = (j << bitdiff) | (j & ((1 << bitdiff) - 1)); - - bitdiff = 8 - zbits; - highpalookup[k * z * y + j * y + i].b = (k << bitdiff) | (k & ((1 << bitdiff) - 1)); - - // unneeded padding, will make the texture upload faster - highpalookup[k * z * y + j * y + i].a = 0; - i++; - } - j++; + // Prime highpalookup maps + i = 0; + while (i < MAXPALOOKUPS) + { + if (prhighpalookups[i].data) + { + bglGenTextures(1, &prhighpalookups[i].map); + bglBindTexture(GL_TEXTURE_3D, prhighpalookups[i].map); + bglTexImage3D(GL_TEXTURE_3D, // target + 0, // mip level + GL_RGBA, // internalFormat + PR_HIGHPALOOKUP_DIM, // width + PR_HIGHPALOOKUP_DIM, // height + PR_HIGHPALOOKUP_DIM, // depth + 0, // border + GL_BGRA, // upload format + GL_UNSIGNED_BYTE, // upload component type + prhighpalookups[i].data); // data pointer + bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); + bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); + bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); + bglBindTexture(GL_TEXTURE_3D, 0); } - k++; + i++; } - bglGenTextures(1, &globalhighpalookupmap); - bglBindTexture(GL_TEXTURE_3D, globalhighpalookupmap); - bglTexImage3D(GL_TEXTURE_3D, // target - 0, // mip level - GL_RGBA, // internalFormat - x, // width - y, // height - z, // depth - 0, // border - GL_RGBA, // upload format - GL_UNSIGNED_BYTE, // upload component type - highpalookup); // data pointer - bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - bglBindTexture(GL_TEXTURE_3D, 0); - - free(highpalookup); - if (pr_verbosity >= 1) OSD_Printf("PR : Initialization complete.\n"); return (1); @@ -734,7 +707,23 @@ int32_t polymer_init(void) void polymer_uninit(void) { + int32_t i; + polymer_freeboard(); + + i = 0; + while (i < MAXPALOOKUPS) + { + if (prhighpalookups[i].data) { + Bfree(prhighpalookups[i].data); + prhighpalookups[i].data = NULL; + } + if (prhighpalookups[i].map) { + bglDeleteTextures(1, &prhighpalookups[i].map); + prhighpalookups[i].map = 0; + } + i++; + } } void polymer_glinit(void) @@ -1669,6 +1658,13 @@ void polymer_texinvalidate(void) while (i >= 0); } +void polymer_definehighpalookup(char palnum, char *data) +{ + prhighpalookups[palnum].data = Bmalloc(PR_HIGHPALOOKUP_DATA_SIZE); + + Bmemcpy(prhighpalookups[palnum].data, data, PR_HIGHPALOOKUP_DATA_SIZE); +} + // CORE static void polymer_displayrooms(int16_t dacursectnum) { @@ -4149,6 +4145,14 @@ static void polymer_getbuildmaterial(_prmaterial* material, int16_t tile // PR_BIT_DIFFUSE_MAP if (!waloff[tilenum]) loadtile(tilenum); + + // PR_BIT_HIGHPALOOKUP_MAP + if (pal > 0 && pr_highpalookups && prhighpalookups[pal].map && + hicfindsubst(tilenum, 0, 0) && (hicfindsubst(tilenum, pal, 0)->palnum != pal)) + { + material->highpalookupmap = prhighpalookups[pal].map; + pal = 0; + } if ((pth = gltexcache(tilenum, pal, cmeth))) { @@ -4232,11 +4236,6 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights, programbits = 0; // --------- bit validation - - // hack to dynamically insert highpalookup - if (debug1) { - material.highpalookupmap = globalhighpalookupmap; - } // PR_BIT_ANIM_INTERPOLATION if (material.nextframedata) diff --git a/polymer/eduke32/build/src/polymost.c b/polymer/eduke32/build/src/polymost.c index ef4cfa160..0dced298d 100644 --- a/polymer/eduke32/build/src/polymost.c +++ b/polymer/eduke32/build/src/polymost.c @@ -6199,6 +6199,7 @@ void polymost_initosdfuncs(void) { "r_pr_overridespecular", "r_pr_overridespecular: overrides specular material power and factor values with values from the pr_specularpower and pr_specularfactor cvars; use it to fine-tune DEF tokens", (void*)&pr_overridespecular, CVAR_BOOL | CVAR_NOSAVE, 0, 1 }, { "r_pr_specularpower", "r_pr_specularpower: overriden specular material power", (void*)&pr_specularpower, CVAR_FLOAT | CVAR_NOSAVE, -10, 1000 }, { "r_pr_specularfactor", "r_pr_specularfactor: overriden specular material factor", (void*)&pr_specularfactor, CVAR_FLOAT | CVAR_NOSAVE, -10, 1000 }, + { "r_pr_highpalookups", "r_pr_highpalookups: enable/disable highpalookups", (void*)&pr_highpalookups, CVAR_BOOL, 0, 1 }, { "r_pr_ati_fboworkaround", "r_pr_ati_fboworkaround: enable this to workaround an ATI driver bug that causes sprite shadows to be square - you need to restart the renderer for it to take effect", (void*)&pr_ati_fboworkaround, CVAR_BOOL | CVAR_NOSAVE, 0, 1 }, { "r_pr_ati_nodepthoffset", "r_pr_ati_nodepthoffset: enable this to workaround an ATI driver bug that causes sprite drawing to freeze the game on Radeon X1x00 hardware - you need to restart the renderer for it to take effect", (void*)&pr_ati_nodepthoffset, CVAR_BOOL | CVAR_NOSAVE, 0, 1 }, #endif diff --git a/polymer/highpalookupmaker.py b/polymer/highpalookupmaker.py new file mode 100644 index 000000000..374216a16 --- /dev/null +++ b/polymer/highpalookupmaker.py @@ -0,0 +1,81 @@ +def makehighpalookuppixel(pal, rgb): + hsv = list(colorsys.rgb_to_hsv(*rgb)) + if pal == 0: + # no-op, pass through + return rgb + # frozen, blue light + elif pal == 1: + # make everything blueish + hsv[0] = 0.66 + return list(colorsys.hsv_to_rgb(*hsv)) + # nightvision + elif pal == 6: + # make everything green and reverse brightness + hsv[0] = 0.33 + hsv[2] = 1.0 - hsv[2] + #hsv[1] = 0.5 + return list(colorsys.hsv_to_rgb(*hsv)) + # pal 20 + elif pal == 20: + # blue to gray by removing all saturation + if (hsv[0] > 0.6 and hsv[0] < 0.7): + hsv[1] = 0 + # orange and brown to blue + if (hsv[0] > 0.04 and hsv[0] < 0.13): + hsv[0] = 0.66 + # purple and reddish to blue + if (hsv[0] > 0.7 and hsv[0] < 0.9): + hsv[0] = 0.66 + # green to blue + if (hsv[0] > 0.30 and hsv[0] < 0.36): + hsv[0] = 0.66 + return list(colorsys.hsv_to_rgb(*hsv)) + else: + print "unknown pal!" + sys.exit() + +import colorsys +import sys +import struct + +if (len(sys.argv) != 3): + print "Usage: python highpalookupmaker.py palnum outfile" + sys.exit() + +# bit depth per dimension +xbits = 7 +ybits = 7 +zbits = 7 + +xdim = 1 << xbits +ydim = 1 << ybits +zdim = 1 << zbits + +palnum = int(sys.argv[1]) + +pixels = [] +pixelcount = xdim * ydim * zdim +curpix = 0.0 + +fo = open(sys.argv[2], "w") + +# throw in a TGA header in there, this way they'll be able to directly edit it if they feel like it +fo.write(struct.pack("=BBBHHBHHHHBB", 0, 0, 2, 0, 0, 0, 0, 0, 16384, 128, 32, 0)) + +print "Creating highpalookup map %s for palette %d with depth %d:%d:%d..." % (sys.argv[2], palnum, xbits, ybits, zbits) + +for k in range(zdim): + for j in range(ydim): + for i in range(xdim): + rgb = [float(i) / (xdim - 1), float(j) / (ydim - 1), float(k) / (zdim - 1)] + rgb = makehighpalookuppixel(palnum, rgb) + # save as BGRA as that's what TGA uses + pixels.append(struct.pack('BBBB', int(rgb[2] * 255), int(rgb[1] * 255), int(rgb[0] * 255), 255)) + curpix += 1 + if (curpix % 128 == 0): + print "\r%f%% done." % (curpix * 100 / pixelcount), + +fo.writelines(pixels) +fo.close() + +print "\n" \ No newline at end of file