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 int32_t pr_overridespecular;
extern float pr_specularpower; extern float pr_specularpower;
extern float pr_specularfactor; extern float pr_specularfactor;
extern int32_t pr_highpalookups;
extern int32_t pr_ati_fboworkaround; extern int32_t pr_ati_fboworkaround;
extern int32_t pr_ati_nodepthoffset; extern int32_t pr_ati_nodepthoffset;
#ifdef __APPLE__ #ifdef __APPLE__
@ -156,6 +157,11 @@ typedef struct s_prrograminfo {
} _prprograminfo; } _prprograminfo;
#define PR_INFO_LOG_BUFFER_SIZE 8192 #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 { typedef struct s_prprogrambit {
int32_t bit; int32_t bit;
@ -259,6 +265,11 @@ typedef struct s_prmirror {
int16_t wallnum; int16_t wallnum;
} _prmirror; } _prmirror;
typedef struct s_prhighpalookup {
char *data;
GLuint map;
} _prhighpalookup;
typedef void (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t); typedef void (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t);
typedef struct s_pranimatespritesinfo { typedef struct s_pranimatespritesinfo {
@ -283,6 +294,7 @@ int16_t polymer_addlight(_prlight* light);
void polymer_deletelight(int16_t lighti); void polymer_deletelight(int16_t lighti);
void polymer_invalidatelights(void); void polymer_invalidatelights(void);
void polymer_texinvalidate(void); void polymer_texinvalidate(void);
void polymer_definehighpalookup(char palnum, char *fn);
# ifdef POLYMER_C # ifdef POLYMER_C

View file

@ -63,6 +63,7 @@ enum scripttoken_t
T_VOXEL, T_VOXEL,
T_SKYBOX, T_SKYBOX,
T_FRONT,T_RIGHT,T_BACK,T_LEFT,T_TOP,T_BOTTOM, T_FRONT,T_RIGHT,T_BACK,T_LEFT,T_TOP,T_BOTTOM,
T_HIGHPALOOKUP,
T_TINT,T_RED,T_GREEN,T_BLUE, 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_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, T_UNDEFMODEL,T_UNDEFMODELRANGE,T_UNDEFMODELOF,T_UNDEFTEXTURE,T_UNDEFTEXTURERANGE,
@ -140,6 +141,7 @@ static int32_t defsparser(scriptfile *script)
{ "model", T_MODEL }, { "model", T_MODEL },
{ "voxel", T_VOXEL }, { "voxel", T_VOXEL },
{ "skybox", T_SKYBOX }, { "skybox", T_SKYBOX },
{ "highpalookup", T_HIGHPALOOKUP },
{ "tint", T_TINT }, { "tint", T_TINT },
{ "texture", T_TEXTURE }, { "texture", T_TEXTURE },
{ "tile", T_TEXTURE }, { "tile", T_TEXTURE },
@ -1427,6 +1429,88 @@ static int32_t defsparser(scriptfile *script)
hicsetskybox(tile,pal,fn); hicsetskybox(tile,pal,fn);
} }
break; 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: case T_TINT:
{ {
char *tinttokptr = script->ltextptr; char *tinttokptr = script->ltextptr;

View file

@ -30,6 +30,7 @@ float pr_parallaxbias = 0.0f;
int32_t pr_overridespecular = 0; int32_t pr_overridespecular = 0;
float pr_specularpower = 15.0f; float pr_specularpower = 15.0f;
float pr_specularfactor = 1.0f; float pr_specularfactor = 1.0f;
int32_t pr_highpalookups = 1;
int32_t pr_ati_fboworkaround = 0; int32_t pr_ati_fboworkaround = 0;
int32_t pr_ati_nodepthoffset = 0; int32_t pr_ati_nodepthoffset = 0;
@ -43,6 +44,7 @@ _prsector *prsectors[MAXSECTORS];
_prwall *prwalls[MAXWALLS]; _prwall *prwalls[MAXWALLS];
_prsprite *prsprites[MAXSPRITES]; _prsprite *prsprites[MAXSPRITES];
_prmaterial mdspritematerial; _prmaterial mdspritematerial;
_prhighpalookup prhighpalookups[MAXPALOOKUPS];
static const GLfloat vertsprite[4 * 5] = static const GLfloat vertsprite[4 * 5] =
{ {
@ -578,9 +580,6 @@ int32_t globaloldoverridematerial;
// RENDER TARGETS // RENDER TARGETS
_prrt *prrts; _prrt *prrts;
// HIGHPALOOKUP MAP NAMES
GLuint globalhighpalookupmap;
// CONTROL // CONTROL
GLfloat spritemodelview[16]; GLfloat spritemodelview[16];
GLfloat mdspritespace[4][4]; GLfloat mdspritespace[4][4];
@ -673,60 +672,34 @@ int32_t polymer_init(void)
polymer_initrendertargets(pr_shadowcount + 1); polymer_initrendertargets(pr_shadowcount + 1);
// test highpalookup // Prime highpalookup maps
int32_t j, k; i = 0;
int32_t xbits = 6, ybits = 6, zbits = 6; // depth while (i < MAXPALOOKUPS)
int32_t x = 1 << xbits, y = 1 << ybits, z = 1 << zbits; // dimensions {
int32_t bitdiff; if (prhighpalookups[i].data)
coltype *highpalookup; {
bglGenTextures(1, &prhighpalookups[i].map);
highpalookup = malloc(x*y*z*sizeof(coltype)); bglBindTexture(GL_TEXTURE_3D, prhighpalookups[i].map);
bglTexImage3D(GL_TEXTURE_3D, // target
k = 0; 0, // mip level
while (k < z) { GL_RGBA, // internalFormat
j = 0; PR_HIGHPALOOKUP_DIM, // width
while (j < y) { PR_HIGHPALOOKUP_DIM, // height
i = 0; PR_HIGHPALOOKUP_DIM, // depth
while (i < x) { 0, // border
bitdiff = 8 - xbits; GL_BGRA, // upload format
highpalookup[k * z * y + j * y + i].r = (i << bitdiff) | (i & ((1 << bitdiff) - 1)); GL_UNSIGNED_BYTE, // upload component type
prhighpalookups[i].data); // data pointer
bitdiff = 8 - ybits; bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
highpalookup[k * z * y + j * y + i].g = (j << bitdiff) | (j & ((1 << bitdiff) - 1)); 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);
bitdiff = 8 - zbits; bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
highpalookup[k * z * y + j * y + i].b = (k << bitdiff) | (k & ((1 << bitdiff) - 1)); bglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
bglBindTexture(GL_TEXTURE_3D, 0);
// unneeded padding, will make the texture upload faster
highpalookup[k * z * y + j * y + i].a = 0;
i++;
}
j++;
} }
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"); if (pr_verbosity >= 1) OSD_Printf("PR : Initialization complete.\n");
return (1); return (1);
@ -734,7 +707,23 @@ int32_t polymer_init(void)
void polymer_uninit(void) void polymer_uninit(void)
{ {
int32_t i;
polymer_freeboard(); 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) void polymer_glinit(void)
@ -1669,6 +1658,13 @@ void polymer_texinvalidate(void)
while (i >= 0); 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 // CORE
static void polymer_displayrooms(int16_t dacursectnum) static void polymer_displayrooms(int16_t dacursectnum)
{ {
@ -4150,6 +4146,14 @@ static void polymer_getbuildmaterial(_prmaterial* material, int16_t tile
if (!waloff[tilenum]) if (!waloff[tilenum])
loadtile(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))) if ((pth = gltexcache(tilenum, pal, cmeth)))
{ {
material->diffusemap = pth->glpic; material->diffusemap = pth->glpic;
@ -4233,11 +4237,6 @@ static int32_t polymer_bindmaterial(_prmaterial material, int16_t* lights,
// --------- bit validation // --------- bit validation
// hack to dynamically insert highpalookup
if (debug1) {
material.highpalookupmap = globalhighpalookupmap;
}
// PR_BIT_ANIM_INTERPOLATION // PR_BIT_ANIM_INTERPOLATION
if (material.nextframedata) if (material.nextframedata)
programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit; 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_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_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_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_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 }, { "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 #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"