Highpalookup support is more or less ready, also checked in sample script to

generate the highpalookup maps offline (only with a few incomplete pals right
now).

New DEF token: highpalookup [pal] [filename]
New cvar: r_pr_highpalookups



git-svn-id: https://svn.eduke32.com/eduke32@1748 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
plagman 2010-12-30 08:13:37 +00:00
parent b3231e5c9b
commit 3d2bcbfba8
5 changed files with 236 additions and 59 deletions

View file

@ -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

View file

@ -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;

View file

@ -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)
{
@ -4150,6 +4146,14 @@ static void polymer_getbuildmaterial(_prmaterial* material, int16_t tile
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)))
{
material->diffusemap = pth->glpic;
@ -4233,11 +4237,6 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
// --------- bit validation
// hack to dynamically insert highpalookup
if (debug1) {
material.highpalookupmap = globalhighpalookupmap;
}
// PR_BIT_ANIM_INTERPOLATION
if (material.nextframedata)
programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit;

View file

@ -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

View file

@ -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"