Rework colormap stuff so that quakerally/tf/etc work, fixing related csqc deficiency. Also support _shirt and _pants textures for people using 24bit textures.

This commit is contained in:
Shpoike 2023-07-07 10:57:40 +01:00
parent d7e86a6592
commit c52a165ca5
14 changed files with 432 additions and 251 deletions

View file

@ -1401,6 +1401,17 @@ char *CL_PLColours_ToString(plcolour_t c)
return "0"; return "0";
} }
plcolour_t CL_PLColours_FromLegacy(int val)
{
plcolour_t c;
val&=0xf;
c.type = 1;
c.basic = val;
c.rgb[0] = c.rgb[1] = c.rgb[2] = val; //fixme... store proper palette?
return c;
}
plcolour_t CL_PLColours_Parse(const char *s) plcolour_t CL_PLColours_Parse(const char *s)
{ {
plcolour_t c; plcolour_t c;
@ -1408,17 +1419,13 @@ plcolour_t CL_PLColours_Parse(const char *s)
if (!strncmp(s, "0x", 2)) if (!strncmp(s, "0x", 2))
{ {
c.type = 2; c.type = 2;
c.basic = 0; c.basic = 0; //find nearest?
c.rgb[0] = 0xff&(v>>16); c.rgb[0] = 0xff&(v>>16);
c.rgb[1] = 0xff&(v>>8); c.rgb[1] = 0xff&(v>>8);
c.rgb[2] = 0xff&(v>>0); c.rgb[2] = 0xff&(v>>0);
} }
else if (*s) else if (*s)
{ return CL_PLColours_FromLegacy(v);
c.type = 1;
c.basic = v;
c.rgb[0] = c.rgb[1] = c.rgb[2] = v&0xf;
}
else else
{ {
c.type = 0; c.type = 0;
@ -1430,20 +1437,13 @@ plcolour_t CL_PLColours_Parse(const char *s)
static void CL_UserinfoChanged(scoreboard_t *sb) static void CL_UserinfoChanged(scoreboard_t *sb)
{ {
char tmp[64]; char tmp[64];
plcolour_t top, bot;
Info_GetKey(sb->userinfo, "name", sb->name, sizeof(sb->name)); Info_GetKey(sb->userinfo, "name", sb->name, sizeof(sb->name));
Info_GetKey(sb->userinfo, "topcolor", tmp, sizeof(tmp)); Info_GetKey(sb->userinfo, "topcolor", tmp, sizeof(tmp));
top = CL_PLColours_Parse(tmp); sb->shirt = CL_PLColours_Parse(*tmp?tmp:"0");
Info_GetKey(sb->userinfo, "bottomcolor", tmp, sizeof(tmp)); Info_GetKey(sb->userinfo, "bottomcolor", tmp, sizeof(tmp));
bot = CL_PLColours_Parse(tmp); sb->pants = CL_PLColours_Parse(*tmp?tmp:"0");
if (!CL_PLColours_Equals(top, sb->shirt) || !CL_PLColours_Equals(bot, sb->pants))
{
sb->shirt = top;
sb->pants = bot;
R_TranslateNewPlayerSkin (sb-cl.scores);
}
//for qw compat. remember that keys with an asterisk are blocked from setinfo (still changable via ssqc though). //for qw compat. remember that keys with an asterisk are blocked from setinfo (still changable via ssqc though).
sb->spectator = atoi(Info_GetKey(sb->userinfo, "*spectator", tmp, sizeof(tmp))); //0=regular player, 1=spectator, 2=spec-with-scores aka waiting their turn to (re)spawn. sb->spectator = atoi(Info_GetKey(sb->userinfo, "*spectator", tmp, sizeof(tmp))); //0=regular player, 1=spectator, 2=spec-with-scores aka waiting their turn to (re)spawn.
//Info_GetKey(sb->userinfo, "team", sb->team, sizeof(sb->team)); //Info_GetKey(sb->userinfo, "team", sb->team, sizeof(sb->team));

View file

@ -517,9 +517,9 @@ static unsigned int CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, c
{ {
/*news->glowsize =*/ MSG_ReadByte(); /*news->glowsize =*/ MSG_ReadByte();
/*news->glowcolour =*/ MSG_ReadByte(); /*news->glowcolour =*/ MSG_ReadByte();
/*news->glowmod[0] =*/ MSG_ReadByte(); news->glowmod[0] = MSG_ReadByte();
/*news->glowmod[1] =*/ MSG_ReadByte(); news->glowmod[1] = MSG_ReadByte();
/*news->glowmod[2] =*/ MSG_ReadByte(); news->glowmod[2] = MSG_ReadByte();
} }
if (bits & UF_FATNESS) if (bits & UF_FATNESS)
/*news->fatness =*/ MSG_ReadByte(); /*news->fatness =*/ MSG_ReadByte();
@ -587,13 +587,7 @@ static void CL_EntitiesDeltaed(void)
VectorCopy (ent->netstate.origin, ent->msg_origins[0]); VectorCopy (ent->netstate.origin, ent->msg_origins[0]);
VectorCopy (ent->netstate.angles, ent->msg_angles[0]); VectorCopy (ent->netstate.angles, ent->msg_angles[0]);
} }
skin = ent->netstate.skin; ent->skinnum = ent->netstate.skin;
if (skin != ent->skinnum)
{
ent->skinnum = skin;
if (newnum > 0 && newnum <= cl.maxclients)
R_TranslateNewPlayerSkin (newnum - 1); //johnfitz -- was R_TranslatePlayerSkin
}
ent->effects = ent->netstate.effects; ent->effects = ent->netstate.effects;
//johnfitz -- lerping for movetype_step entities //johnfitz -- lerping for movetype_step entities
@ -631,8 +625,6 @@ static void CL_EntitiesDeltaed(void)
} }
else else
forcelink = true; // hack to make null model players work forcelink = true; // hack to make null model players work
if (newnum > 0 && newnum <= cl.maxclients)
R_TranslateNewPlayerSkin (newnum - 1); //johnfitz -- was R_TranslatePlayerSkin
ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes
} }
@ -1063,9 +1055,9 @@ static void CLDP_ReadDelta(unsigned int entnum, entity_state_t *s, const entity_
} }
if (bits & E5_GLOWMOD) if (bits & E5_GLOWMOD)
{ {
/*s->glowmod[0] =*/ MSG_ReadByte(); s->glowmod[0] = MSG_ReadByte();
/*s->glowmod[1] =*/ MSG_ReadByte(); s->glowmod[1] = MSG_ReadByte();
/*s->glowmod[2] =*/ MSG_ReadByte(); s->glowmod[2] = MSG_ReadByte();
} }
if (bits & E5_COMPLEXANIMATION) if (bits & E5_COMPLEXANIMATION)
{ {
@ -1583,7 +1575,6 @@ static void CL_ParseUpdate (int bits)
qboolean forcelink; qboolean forcelink;
entity_t *ent; entity_t *ent;
int num; int num;
int skin;
if (cls.signon == SIGNONS - 1) if (cls.signon == SIGNONS - 1)
{ // first update is the final signon stage { // first update is the final signon stage
@ -1652,15 +1643,9 @@ static void CL_ParseUpdate (int bits)
if (bits & U_COLORMAP) if (bits & U_COLORMAP)
ent->netstate.colormap = MSG_ReadByte(); ent->netstate.colormap = MSG_ReadByte();
if (bits & U_SKIN) if (bits & U_SKIN)
skin = MSG_ReadByte(); ent->skinnum = MSG_ReadByte();
else else
skin = ent->baseline.skin; ent->skinnum = ent->baseline.skin;
if (skin != ent->skinnum)
{
ent->skinnum = skin;
if (num > 0 && num <= cl.maxclients)
R_TranslateNewPlayerSkin (num - 1); //johnfitz -- was R_TranslatePlayerSkin
}
if (bits & U_EFFECTS) if (bits & U_EFFECTS)
ent->effects = MSG_ReadByte(); ent->effects = MSG_ReadByte();
else else
@ -1777,8 +1762,6 @@ static void CL_ParseUpdate (int bits)
} }
else else
forcelink = true; // hack to make null model players work forcelink = true; // hack to make null model players work
if (num > 0 && num <= cl.maxclients)
R_TranslateNewPlayerSkin (num - 1); //johnfitz -- was R_TranslatePlayerSkin
ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes
} }
@ -2005,10 +1988,8 @@ static void CL_NewTranslation (int slot, int vanillacolour)
if (slot > cl.maxclients) if (slot > cl.maxclients)
Sys_Error ("CL_NewTranslation: slot > cl.maxclients"); Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
//clumsy, but ensures its initialised properly. cl.scores[slot].shirt = CL_PLColours_FromLegacy((vanillacolour>>4)&0xf);
cl.scores[slot].shirt = CL_PLColours_Parse(va("%i", (vanillacolour>>4)&0xf)); cl.scores[slot].pants = CL_PLColours_FromLegacy((vanillacolour>>0)&0xf);
cl.scores[slot].pants = CL_PLColours_Parse(va("%i", (vanillacolour>>0)&0xf));
R_TranslatePlayerSkin (slot);
} }
/* /*

View file

@ -1824,9 +1824,9 @@ static void COM_SetupNullState(void)
nullentitystate.colormod[0] = 32; nullentitystate.colormod[0] = 32;
nullentitystate.colormod[1] = 32; nullentitystate.colormod[1] = 32;
nullentitystate.colormod[2] = 32; nullentitystate.colormod[2] = 32;
// nullentitystate.glowmod[0] = 32; nullentitystate.glowmod[0] = 32;
// nullentitystate.glowmod[1] = 32; nullentitystate.glowmod[1] = 32;
// nullentitystate.glowmod[2] = 32; nullentitystate.glowmod[2] = 32;
nullentitystate.alpha = ENTALPHA_DEFAULT; //fte has 255 by default, with 0 for invisible. fitz uses 1 for invisible, 0 default, and 255=full alpha nullentitystate.alpha = ENTALPHA_DEFAULT; //fte has 255 by default, with 0 for invisible. fitz uses 1 for invisible, 0 default, and 255=full alpha
nullentitystate.scale = ENTSCALE_DEFAULT; nullentitystate.scale = ENTSCALE_DEFAULT;
nullentitystate.solidsize = ES_SOLID_NOT; nullentitystate.solidsize = ES_SOLID_NOT;

View file

@ -26,13 +26,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// draw.h -- these are the only functions outside the refresh allowed // draw.h -- these are the only functions outside the refresh allowed
// to touch the vid buffer // to touch the vid buffer
typedef struct typedef union
{ {
byte type; //0 for none, 1 for legacy colours, 2 for rgb. struct{
byte basic; byte type; //0 for none, 1 for legacy colours, 2 for rgb.
byte rgb[3]; byte rgb[3];
byte basic; //used in legacy contexts where an rgb value will not work.
};
int key; //for fast compares
} plcolour_t; } plcolour_t;
plcolour_t CL_PLColours_Parse(const char *s); plcolour_t CL_PLColours_Parse(const char *s);
plcolour_t CL_PLColours_FromLegacy(int val);
char *CL_PLColours_ToString(plcolour_t c); char *CL_PLColours_ToString(plcolour_t c);
byte *CL_PLColours_ToRGB(plcolour_t *c); byte *CL_PLColours_ToRGB(plcolour_t *c);
#define CL_PLColours_Equals(a,b) (!memcmp(&a,&b, sizeof(plcolour_t))) #define CL_PLColours_Equals(a,b) (!memcmp(&a,&b, sizeof(plcolour_t)))

View file

@ -517,7 +517,6 @@ qboolean Draw_ReloadTextures(qboolean force)
{ {
TexMgr_NewGame (); TexMgr_NewGame ();
Draw_NewGame (); Draw_NewGame ();
R_NewGame ();
Cache_Flush (); Cache_Flush ();

View file

@ -653,6 +653,8 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
{ {
char texturename[MAX_QPATH]; char texturename[MAX_QPATH];
char fullbrightname[MAX_QPATH]; char fullbrightname[MAX_QPATH];
char uppername[MAX_QPATH];
char lowername[MAX_QPATH];
char *ext; char *ext;
//texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names. //texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names.
//our texture manager is too lame to scan all 1000 possibilities //our texture manager is too lame to scan all 1000 possibilities
@ -672,16 +674,19 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
if (*ext) if (*ext)
*--ext = 0; *--ext = 0;
//luma has an extra postfix. //luma has an extra postfix.
q_snprintf(uppername, sizeof(fullbrightname), "%s_shirt", texturename);
q_snprintf(lowername, sizeof(fullbrightname), "%s_pants", texturename);
q_snprintf(fullbrightname, sizeof(fullbrightname), "%s_luma", texturename); q_snprintf(fullbrightname, sizeof(fullbrightname), "%s_luma", texturename);
osurf->gltextures[j][0] = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP); osurf->textures[j][0].base = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
osurf->fbtextures[j][0] = TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP); osurf->textures[j][0].lower = TexMgr_LoadImage(mod, lowername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, lowername, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
osurf->gltextures[j][3] = osurf->gltextures[j][2] = osurf->gltextures[j][1] = osurf->gltextures[j][0]; osurf->textures[j][0].upper = TexMgr_LoadImage(mod, uppername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, uppername, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
osurf->fbtextures[j][3] = osurf->fbtextures[j][2] = osurf->fbtextures[j][1] = osurf->fbtextures[j][0]; osurf->textures[j][0].luma = TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, fullbrightname, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP);
osurf->textures[j][3] = osurf->textures[j][2] = osurf->textures[j][1] = osurf->textures[j][0];
} }
if (osurf->numskins) if (osurf->numskins)
{ {
osurf->skinwidth = osurf->gltextures[0][0]->source_width; osurf->skinwidth = osurf->textures[0][0].base->source_width;
osurf->skinheight = osurf->gltextures[0][0]->source_height; osurf->skinheight = osurf->textures[0][0].base->source_height;
} }
} }
@ -1087,14 +1092,19 @@ static void Mod_LoadIQMSkin (qmodel_t *mod, const struct iqmheader *pinheader, a
{ {
const char *texturename = (const char *)pinheader + pinheader->ofs_text + sf->material_idx; const char *texturename = (const char *)pinheader + pinheader->ofs_text + sf->material_idx;
char hackytexturename[MAX_QPATH]; char hackytexturename[MAX_QPATH];
char filename2[MAX_QPATH];
COM_StripExtension(texturename, hackytexturename, sizeof(hackytexturename)); COM_StripExtension(texturename, hackytexturename, sizeof(hackytexturename));
osurf->gltextures[j][k] = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, hackytexturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP); osurf->textures[j][k].base = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, hackytexturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
osurf->fbtextures[j][k] = NULL;//TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, fullbrightname, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP); q_snprintf(filename2, sizeof(filename2), "%s_pants", hackytexturename);
osurf->textures[j][k].lower = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
q_snprintf(filename2, sizeof(filename2), "%s_shirt", hackytexturename);
osurf->textures[j][k].upper = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
q_snprintf(filename2, sizeof(filename2), "%s_luma", hackytexturename);
osurf->textures[j][k].luma = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP|TEXPREF_ALLOWMISSING);
} }
for (; k < 4; k++) for (; k < 4; k++)
{ {
osurf->gltextures[j][k] = osurf->gltextures[j][k%skin->countframes]; osurf->textures[j][k] = osurf->textures[j][k%skin->countframes];
osurf->fbtextures[j][k] = osurf->fbtextures[j][k%skin->countframes];
} }
} }
osurf->numskins = j; osurf->numskins = j;
@ -1105,7 +1115,7 @@ static void Mod_LoadIQMSkin (qmodel_t *mod, const struct iqmheader *pinheader, a
for (j = 0; j < 1; j++) for (j = 0; j < 1; j++)
{ {
char texturename[MAX_QPATH]; char texturename[MAX_QPATH];
char fullbrightname[MAX_QPATH]; char filename2[MAX_QPATH];
char *ext; char *ext;
//texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names. //texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names.
//our texture manager is too lame to scan all 1000 possibilities //our texture manager is too lame to scan all 1000 possibilities
@ -1125,17 +1135,21 @@ static void Mod_LoadIQMSkin (qmodel_t *mod, const struct iqmheader *pinheader, a
if (*ext) if (*ext)
*--ext = 0; *--ext = 0;
//luma has an extra postfix. //luma has an extra postfix.
q_snprintf(fullbrightname, sizeof(fullbrightname), "%s_luma", texturename); osurf->textures[j][0].base = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
osurf->gltextures[j][0] = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP); q_snprintf(filename2, sizeof(filename2), "%s_pants", texturename);
osurf->fbtextures[j][0] = NULL;//TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, fullbrightname, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP); osurf->textures[j][0].lower = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
osurf->gltextures[j][3] = osurf->gltextures[j][2] = osurf->gltextures[j][1] = osurf->gltextures[j][0]; q_snprintf(filename2, sizeof(filename2), "%s_shirt", texturename);
osurf->fbtextures[j][3] = osurf->fbtextures[j][2] = osurf->fbtextures[j][1] = osurf->fbtextures[j][0]; osurf->textures[j][0].upper = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
q_snprintf(filename2, sizeof(filename2), "%s_luma", texturename);
osurf->textures[j][0].luma = TexMgr_LoadImage(mod, filename2, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP|TEXPREF_ALLOWMISSING);
osurf->textures[j][3] = osurf->textures[j][2] = osurf->textures[j][1] = osurf->textures[j][0];
} }
} }
if (osurf->numskins) if (osurf->numskins)
{ {
osurf->skinwidth = osurf->gltextures[0][0]->source_width; osurf->skinwidth = osurf->textures[0][0].base->source_width;
osurf->skinheight = osurf->gltextures[0][0]->source_height; osurf->skinheight = osurf->textures[0][0].base->source_height;
} }
} }
@ -1867,7 +1881,7 @@ void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
qboolean malloced; qboolean malloced;
void *data; void *data;
int mark = Hunk_LowMark (); int mark = Hunk_LowMark ();
for (f = 0; f < countof(surf->gltextures[0]); f++) for (f = 0; f < countof(surf->textures[0]); f++)
{ {
q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u", com_token, surf->numskins, f); q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u", com_token, surf->numskins, f);
@ -1875,31 +1889,39 @@ void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
//now load whatever we found //now load whatever we found
if (data) //load external image if (data) //load external image
{ {
surf->gltextures[surf->numskins][f] = TexMgr_LoadImage (mod, texname, fwidth, fheight, fmt, data, texname, 0, TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP ); surf->textures[surf->numskins][f].base = TexMgr_LoadImage (mod, texname, fwidth, fheight, fmt, data, texname, 0, TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP );
surf->fbtextures[surf->numskins][f] = NULL; surf->textures[surf->numskins][f].lower = NULL;
surf->textures[surf->numskins][f].upper = NULL;
surf->textures[surf->numskins][f].luma = NULL;
if (fmt == SRC_INDEXED) if (fmt == SRC_INDEXED)
{ //8bit base texture. use it for fullbrights. { //8bit base texture. use it for fullbrights.
for (j = 0; j < fwidth*fheight; j++) for (j = 0; j < fwidth*fheight; j++)
{ {
if (((byte*)data)[j] > 223) if (((byte*)data)[j] > 223)
{ {
surf->fbtextures[surf->numskins][f] = TexMgr_LoadImage (mod, va("%s_luma", texname), fwidth, fheight, fmt, data, texname, 0, TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP ); surf->textures[surf->numskins][f].luma = TexMgr_LoadImage (mod, va("%s_luma", texname), fwidth, fheight, fmt, data, texname, 0, TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP );
break; break;
} }
} }
} }
else else
{ //we found a 32bit base texture. { //we found a 32bit base texture.
if (!surf->fbtextures[surf->numskins][f]) if (!surf->textures[surf->numskins][f].luma)
{ {
q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_glow", com_token, surf->numskins, f); q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_glow", com_token, surf->numskins, f);
surf->fbtextures[surf->numskins][f] = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP); surf->textures[surf->numskins][f].luma = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
} }
if (!surf->fbtextures[surf->numskins][f]) if (!surf->textures[surf->numskins][f].luma)
{ {
q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_luma", com_token, surf->numskins, f); q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_luma", com_token, surf->numskins, f);
surf->fbtextures[surf->numskins][f] = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP); surf->textures[surf->numskins][f].luma = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
} }
q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_pants", com_token, surf->numskins, f);
surf->textures[surf->numskins][f].lower = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
q_snprintf(texname, sizeof(texname), "progs/%s_%02u_%02u_shirt", com_token, surf->numskins, f);
surf->textures[surf->numskins][f].upper = TexMgr_LoadImage(mod, texname, surf->skinwidth, surf->skinheight, SRC_EXTERNAL, NULL, texname, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
} }
//now try to load glow/luma image from the same place //now try to load glow/luma image from the same place
@ -1915,23 +1937,17 @@ void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
//this stuff is hideous. //this stuff is hideous.
if (f < 2) if (f < 2)
{ surf->textures[surf->numskins][1] = surf->textures[surf->numskins][0];
surf->gltextures[surf->numskins][1] = surf->gltextures[surf->numskins][0];
surf->fbtextures[surf->numskins][1] = surf->fbtextures[surf->numskins][0];
}
if (f == 3) if (f == 3)
Con_Warning("progs/%s_%02u_##: 3 skinframes found...\n", com_token, surf->numskins); Con_Warning("progs/%s_%02u_##: 3 skinframes found...\n", com_token, surf->numskins);
if (f < 4) if (f < 4)
{ {
surf->gltextures[surf->numskins][3] = surf->gltextures[surf->numskins][1]; surf->textures[surf->numskins][3] = surf->textures[surf->numskins][1];
surf->gltextures[surf->numskins][2] = surf->gltextures[surf->numskins][0]; surf->textures[surf->numskins][2] = surf->textures[surf->numskins][0];
surf->fbtextures[surf->numskins][3] = surf->fbtextures[surf->numskins][1];
surf->fbtextures[surf->numskins][2] = surf->fbtextures[surf->numskins][0];
} }
} }
surf->skinwidth = surf->gltextures[0][0]?surf->gltextures[0][0]->width:1; surf->skinwidth = surf->textures[0][0].base?surf->textures[0][0].base->width:1;
surf->skinheight = surf->gltextures[0][0]?surf->gltextures[0][0]->height:1; surf->skinheight = surf->textures[0][0].base?surf->textures[0][0].base->height:1;
buffer = COM_Parse(buffer); buffer = COM_Parse(buffer);
MD5EXPECT("numverts"); MD5EXPECT("numverts");
surf->numverts_vbo = surf->numverts = MD5UINT(); surf->numverts_vbo = surf->numverts = MD5UINT();

View file

@ -26,8 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //spike - to ensure skins don't get screwed randomly.
qmodel_t *loadmodel; qmodel_t *loadmodel;
char loadname[32]; // for hunk tags char loadname[32]; // for hunk tags
@ -487,11 +485,6 @@ static qmodel_t *Mod_LoadModel (qmodel_t *mod, qboolean crash)
Mod_SetExtraFlags (mod); //johnfitz. spike -- moved this to be generic, because most of the flags are anyway. Mod_SetExtraFlags (mod); //johnfitz. spike -- moved this to be generic, because most of the flags are anyway.
if (cls.state == ca_connected)
for (i = 0; i < countof(playertextures); i++)
if (playertextures[i] && playertextures[i]->owner == mod)
R_TranslateNewPlayerSkin(i);
return mod; return mod;
} }
@ -3089,13 +3082,19 @@ static void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
//now load whatever we found //now load whatever we found
if (data) //load external image if (data) //load external image
{ {
pheader->gltextures[i][0] = TexMgr_LoadImage (loadmodel, filename, fwidth, fheight, pheader->textures[i][0].base = TexMgr_LoadImage (loadmodel, filename, fwidth, fheight,
fmt, data, filename, 0, TEXPREF_ALPHA|texflags|TEXPREF_MIPMAP ); fmt, data, filename, 0, TEXPREF_ALPHA|texflags|TEXPREF_MIPMAP );
if (malloced) if (malloced)
free(data); free(data);
Hunk_FreeToLowMark (mark); Hunk_FreeToLowMark (mark);
q_snprintf (filename2, sizeof(filename2), "%s_pants", filename);
pheader->textures[i][0].lower = TexMgr_LoadImage(loadmodel, filename2, fwidth, fheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
q_snprintf (filename2, sizeof(filename2), "%s_shirt", filename);
pheader->textures[i][0].upper = TexMgr_LoadImage(loadmodel, filename2, fwidth, fheight, SRC_EXTERNAL, NULL, filename2, 0, TEXPREF_ALLOWMISSING|TEXPREF_MIPMAP);
//now try to load glow/luma image from the same place //now try to load glow/luma image from the same place
q_snprintf (filename2, sizeof(filename2), "%s_glow", filename); q_snprintf (filename2, sizeof(filename2), "%s_glow", filename);
data = !gl_load24bit.value?NULL:Image_LoadImage (filename2, &fwidth, &fheight, &fmt, &malloced); data = !gl_load24bit.value?NULL:Image_LoadImage (filename2, &fwidth, &fheight, &fmt, &malloced);
@ -3106,10 +3105,10 @@ static void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
} }
if (data) if (data)
pheader->fbtextures[i][0] = TexMgr_LoadImage (loadmodel, filename2, fwidth, fheight, pheader->textures[i][0].luma = TexMgr_LoadImage (loadmodel, filename2, fwidth, fheight,
fmt, data, filename, 0, TEXPREF_ALPHA|texflags|TEXPREF_MIPMAP ); fmt, data, filename, 0, TEXPREF_ALPHA|texflags|TEXPREF_MIPMAP );
else else
pheader->fbtextures[i][0] = NULL; pheader->textures[i][0].luma = NULL;
if (malloced) if (malloced)
free(data); free(data);
@ -3122,22 +3121,24 @@ static void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
offset = (src_offset_t)(pskintype+1) - (src_offset_t)mod_base; offset = (src_offset_t)(pskintype+1) - (src_offset_t)mod_base;
if (Mod_CheckFullbrights ((byte *)(pskintype+1), size)) if (Mod_CheckFullbrights ((byte *)(pskintype+1), size))
{ {
pheader->gltextures[i][0] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][0].base = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags | TEXPREF_NOBRIGHT); SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags | TEXPREF_NOBRIGHT);
q_snprintf (fbr_mask_name, sizeof(fbr_mask_name), "%s:frame%i_glow", loadmodel->name, i); q_snprintf (fbr_mask_name, sizeof(fbr_mask_name), "%s:frame%i_glow", loadmodel->name, i);
pheader->fbtextures[i][0] = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][0].luma = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags | TEXPREF_FULLBRIGHT); SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags | TEXPREF_FULLBRIGHT);
} }
else else
{ {
pheader->gltextures[i][0] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][0].base = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags); SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, texflags);
pheader->fbtextures[i][0] = NULL; pheader->textures[i][0].luma = NULL;
} }
pheader->textures[i][0].upper = NULL;
pheader->textures[i][0].lower = NULL;
} }
pheader->gltextures[i][3] = pheader->gltextures[i][2] = pheader->gltextures[i][1] = pheader->gltextures[i][0]; pheader->textures[i][3] = pheader->textures[i][2] = pheader->textures[i][1] = pheader->textures[i][0];
pheader->fbtextures[i][3] = pheader->fbtextures[i][2] = pheader->fbtextures[i][1] = pheader->fbtextures[i][0];
//johnfitz //johnfitz
pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + size); pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + size);
@ -3166,25 +3167,27 @@ static void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
offset = (src_offset_t)(pskintype) - (src_offset_t)mod_base; //johnfitz offset = (src_offset_t)(pskintype) - (src_offset_t)mod_base; //johnfitz
if (Mod_CheckFullbrights ((byte *)(pskintype), size)) if (Mod_CheckFullbrights ((byte *)(pskintype), size))
{ {
pheader->gltextures[i][j&3] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][j&3].base = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags | TEXPREF_NOBRIGHT); SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags | TEXPREF_NOBRIGHT);
q_snprintf (fbr_mask_name, sizeof(fbr_mask_name), "%s:frame%i_%i_glow", loadmodel->name, i,j); q_snprintf (fbr_mask_name, sizeof(fbr_mask_name), "%s:frame%i_%i_glow", loadmodel->name, i,j);
pheader->fbtextures[i][j&3] = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][j&3].luma = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags | TEXPREF_FULLBRIGHT); SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags | TEXPREF_FULLBRIGHT);
} }
else else
{ {
pheader->gltextures[i][j&3] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight, pheader->textures[i][j&3].base = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags); SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, texflags);
pheader->fbtextures[i][j&3] = NULL; pheader->textures[i][j&3].luma = NULL;
} }
//johnfitz //johnfitz
pheader->textures[i][j&3].upper = NULL;
pheader->textures[i][j&3].lower = NULL;
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size); pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
} }
k = j; k = j;
for (/**/; j < 4; j++) for (/**/; j < 4; j++)
pheader->gltextures[i][j&3] = pheader->gltextures[i][j - k]; pheader->textures[i][j&3] = pheader->textures[i][j - k];
} }
} }

View file

@ -380,9 +380,14 @@ typedef struct {
PV_QUAKEFORGE, //trivertx16_t PV_QUAKEFORGE, //trivertx16_t
PV_IQM, //iqmvert_t PV_IQM, //iqmvert_t
} poseverttype; //spike } poseverttype; //spike
struct gltexture_s *gltextures[MAX_SKINS][4]; //johnfitz struct skintextures_s
struct gltexture_s *fbtextures[MAX_SKINS][4]; //johnfitz {
intptr_t texels[MAX_SKINS]; // only for player skins struct gltexture_s *base;
struct gltexture_s *luma;
struct gltexture_s *upper;
struct gltexture_s *lower;
} textures[MAX_SKINS][4]; //spike
intptr_t texels[MAX_SKINS]; // only for player skins
maliasframedesc_t frames[1]; // variable sized maliasframedesc_t frames[1]; // variable sized
} aliashdr_t; } aliashdr_t;

View file

@ -47,8 +47,6 @@ extern cvar_t r_noshadow_list;
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
cvar_t r_brokenturbbias = {"r_brokenturbbias", "1", CVAR_ARCHIVE}; //replicates QS's bug where it ignores texture coord offsets for water (breaking curved water volumes). we do NOT ignore scales though. cvar_t r_brokenturbbias = {"r_brokenturbbias", "1", CVAR_ARCHIVE}; //replicates QS's bug where it ignores texture coord offsets for water (breaking curved water volumes). we do NOT ignore scales though.
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
/* /*
==================== ====================
@ -245,84 +243,6 @@ void R_Init (void)
Fog_Init (); //johnfitz Fog_Init (); //johnfitz
} }
/*
===============
R_TranslatePlayerSkin -- johnfitz -- rewritten. also, only handles new colors, not new skins
===============
*/
void R_TranslatePlayerSkin (int playernum)
{
//FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors.
if (!gl_nocolors.value)
if (playertextures[playernum])
TexMgr_ReloadImage (playertextures[playernum], cl.scores[playernum].shirt, cl.scores[playernum].pants);
}
/*
===============
R_TranslateNewPlayerSkin -- johnfitz -- split off of TranslatePlayerSkin -- this is called when
the skin or model actually changes, instead of just new colors
added bug fix from bengt jardup
===============
*/
void R_TranslateNewPlayerSkin (int playernum)
{
char name[64];
byte *pixels;
aliashdr_t *paliashdr;
int skinnum;
//get correct texture pixels
currententity = &cl.entities[1+playernum];
if (!currententity->model || currententity->model->type != mod_alias)
return;
paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
skinnum = currententity->skinnum;
if (paliashdr->numskins)
{
//TODO: move these tests to the place where skinnum gets received from the server
if (skinnum < 0 || skinnum >= paliashdr->numskins)
{
Con_DPrintf("(%d): Invalid player skin #%d\n", playernum, skinnum);
skinnum = 0;
}
pixels = (byte *)paliashdr + paliashdr->texels[skinnum]; // This is not a persistent place!
//upload new image
q_snprintf(name, sizeof(name), "player_%i", playernum);
playertextures[playernum] = TexMgr_LoadImage (currententity->model, name, paliashdr->skinwidth, paliashdr->skinheight,
SRC_INDEXED, pixels, paliashdr->gltextures[skinnum][0]->source_file, paliashdr->gltextures[skinnum][0]->source_offset, TEXPREF_PAD | TEXPREF_OVERWRITE);
}
else
{
q_snprintf(name, sizeof(name), "player_%i", playernum);
playertextures[playernum] = TexMgr_LoadImage (currententity->model, name, paliashdr->skinwidth, paliashdr->skinheight,
SRC_EXTERNAL, NULL, "skins/base.pcx", 0, TEXPREF_PAD | TEXPREF_OVERWRITE);
}
//now recolor it
R_TranslatePlayerSkin (playernum);
}
/*
===============
R_NewGame -- johnfitz -- handle a game switch
===============
*/
void R_NewGame (void)
{
int i;
//clear playertexture pointers (the textures themselves were freed by texmgr_newgame)
for (i=0; i<MAX_SCOREBOARD; i++)
playertextures[i] = NULL;
}
/* /*
============= =============
R_ParseWorldspawn R_ParseWorldspawn

View file

@ -45,8 +45,8 @@ unsigned int d_8to24table_fbright_fence[256];
unsigned int d_8to24table_nobright[256]; unsigned int d_8to24table_nobright[256];
unsigned int d_8to24table_nobright_fence[256]; unsigned int d_8to24table_nobright_fence[256];
unsigned int d_8to24table_conchars[256]; unsigned int d_8to24table_conchars[256];
unsigned int d_8to24table_shirt[256];
unsigned int d_8to24table_pants[256]; static void TexMgr_ColormapTexture_Free(struct gltexture_s *basetex);
static struct static struct
{ {
@ -479,6 +479,9 @@ void TexMgr_FreeTexture (gltexture_t *kill)
return; return;
} }
if (kill->flags & TEXPREF_COLOURMAPPED)
TexMgr_ColormapTexture_Free(kill);
if (active_gltextures == kill) if (active_gltextures == kill)
{ {
active_gltextures = kill->next; active_gltextures = kill->next;
@ -552,6 +555,8 @@ void TexMgr_DeleteTextureObjects (void)
{ {
gltexture_t *glt; gltexture_t *glt;
TexMgr_ColormapTexture_Free(NULL);
for (glt = active_gltextures; glt; glt = glt->next) for (glt = active_gltextures; glt; glt = glt->next)
{ {
GL_DeleteTexture (glt); GL_DeleteTexture (glt);
@ -654,6 +659,8 @@ TexMgr_NewGame
*/ */
void TexMgr_NewGame (void) void TexMgr_NewGame (void)
{ {
TexMgr_ColormapTexture_Free(NULL);
TexMgr_FreeTextures (0, TEXPREF_PERSIST); //deletes all textures where TEXPREF_PERSIST is unset TexMgr_FreeTextures (0, TEXPREF_PERSIST); //deletes all textures where TEXPREF_PERSIST is unset
TexMgr_LoadPalette (); TexMgr_LoadPalette ();
} }
@ -1409,7 +1416,7 @@ static void TexMgr_LoadImage8 (gltexture_t *glt, byte *data)
} }
else if (glt->pants.type == 1) else if (glt->pants.type == 1)
{ {
pants = glt->pants.rgb[0] * 16; pants = glt->pants.basic * 16;
if (pants < 128) if (pants < 128)
{ {
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
@ -1693,6 +1700,8 @@ void TexMgr_ReloadImages (void)
// switching to a boolean flag. // switching to a boolean flag.
in_reload_images = true; in_reload_images = true;
TexMgr_ColormapTexture_Free(NULL); //just flush colourmapped cache instead of reloading them all unecessarily.
for (glt = active_gltextures; glt; glt = glt->next) for (glt = active_gltextures; glt; glt = glt->next)
{ {
glGenTextures(1, &glt->texnum); glGenTextures(1, &glt->texnum);
@ -1716,6 +1725,104 @@ void TexMgr_ReloadNobrightImages (void)
TexMgr_ReloadImage(glt, plcolour_none, plcolour_none); TexMgr_ReloadImage(glt, plcolour_none, plcolour_none);
} }
static struct
{
struct gltexture_s *basetex;
struct gltexture_s *coloured;
plcolour_t upper;
plcolour_t lower;
double usetime;
} colourmappedtexture[MAX_SCOREBOARD*2];
static size_t numcolourmappedtextures;
static void TexMgr_ColormapTexture_Free(struct gltexture_s *basetex)
{
int i;
if (basetex)
{ //kill a single one.
basetex->flags &= ~TEXPREF_COLOURMAPPED;
for (i = 0; i < numcolourmappedtextures; i++)
{
if (colourmappedtexture[i].basetex == basetex)
{
TexMgr_FreeTexture(colourmappedtexture[i].coloured);
colourmappedtexture[i].basetex = NULL;
colourmappedtexture[i].usetime = 0;
colourmappedtexture[i].coloured = NULL;
//may be multiple combinations of the same texture.
}
}
}
else
{ //kill em all
for (i = 0; i < numcolourmappedtextures; i++)
{
if (colourmappedtexture[i].coloured)
TexMgr_FreeTexture(colourmappedtexture[i].coloured);
colourmappedtexture[i].coloured = NULL;
}
numcolourmappedtextures = 0;
}
}
struct gltexture_s *TexMgr_ColormapTexture(struct gltexture_s *basetex, plcolour_t lower, plcolour_t upper)
{
int oldest;
float otime;
int i;
struct gltexture_s *glt;
for (i = 0; i < countof(colourmappedtexture); i++)
{
if (colourmappedtexture[i].basetex == basetex && colourmappedtexture[i].upper.key == upper.key && colourmappedtexture[i].lower.key == lower.key)
{
colourmappedtexture[i].usetime = realtime;
return colourmappedtexture[i].coloured;
}
}
if (numcolourmappedtextures < countof(colourmappedtexture))
oldest = numcolourmappedtextures++; //just use a new one
else
{
otime = colourmappedtexture[oldest=0].usetime;
for (i = 1; i < countof(colourmappedtexture); i++)
{
if (otime > colourmappedtexture[i].usetime)
otime = colourmappedtexture[oldest=i].usetime;
}
}
if (colourmappedtexture[oldest].coloured)
TexMgr_FreeTexture(colourmappedtexture[oldest].coloured); //was previously used...
colourmappedtexture[oldest].basetex = basetex;
colourmappedtexture[oldest].upper = upper;
colourmappedtexture[oldest].lower = lower;
//create the new texture from the existing one
colourmappedtexture[oldest].coloured = glt = TexMgr_NewTexture ();
glt->owner = NULL; //don't get clobbered by mistake
q_strlcpy (glt->name, basetex->name, sizeof(glt->name));
glt->width = basetex->width;
glt->height = basetex->height;
glt->flags = basetex->flags|TEXPREF_OVERWRITE;
glt->shirt = upper;
glt->pants = lower;
q_strlcpy (glt->source_file, basetex->source_file, sizeof(glt->source_file));
glt->source_offset = basetex->source_offset;
glt->source_format = basetex->source_format;
glt->source_width = basetex->source_width;
glt->source_height = basetex->source_height;
glt->source_crc = basetex->source_crc+1; //something wrong so we don't get found so easily...
//and now reload it so it gets the proper colours.
TexMgr_ReloadImage(glt, upper, lower);
basetex->flags |= TEXPREF_COLOURMAPPED; //so we clean up other textures spawned from it too.
colourmappedtexture[oldest].usetime = realtime;
return colourmappedtexture[oldest].coloured;
}
/* /*
================================================================================ ================================================================================
@ -1724,7 +1831,7 @@ void TexMgr_ReloadNobrightImages (void)
================================================================================ ================================================================================
*/ */
static GLuint currenttexture[3] = {GL_UNUSED_TEXTURE, GL_UNUSED_TEXTURE, GL_UNUSED_TEXTURE}; // to avoid unnecessary texture sets static GLuint currenttexture[4] = {GL_UNUSED_TEXTURE, GL_UNUSED_TEXTURE, GL_UNUSED_TEXTURE, GL_UNUSED_TEXTURE}; // to avoid unnecessary texture sets
static GLenum currenttarget = GL_TEXTURE0_ARB; static GLenum currenttarget = GL_TEXTURE0_ARB;
qboolean mtexenabled = false; qboolean mtexenabled = false;

View file

@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TEXPREF_WARPIMAGE 0x0800 // resize this texture when warpimagesize changes #define TEXPREF_WARPIMAGE 0x0800 // resize this texture when warpimagesize changes
#define TEXPREF_PREMULTIPLY 0x1000 // rgb = rgb*a; a=a; #define TEXPREF_PREMULTIPLY 0x1000 // rgb = rgb*a; a=a;
#define TEXPREF_ALLOWMISSING 0x2000 // TexMgr_LoadImage should return NULL if anything goes wrong (for use with SRC_EXTERNAL). #define TEXPREF_ALLOWMISSING 0x2000 // TexMgr_LoadImage should return NULL if anything goes wrong (for use with SRC_EXTERNAL).
#define TEXPREF_COLOURMAPPED 0x4000 // internal - this texture has at least one recoloured variant that needs cleaning up on destruction.
enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA, SRC_EXTERNAL, SRC_FIRSTCOMPRESSED}; enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA, SRC_EXTERNAL, SRC_FIRSTCOMPRESSED};
extern qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc, gl_texture_e5bgr9; extern qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc, gl_texture_e5bgr9;
@ -75,8 +76,6 @@ extern unsigned int d_8to24table[256];
extern unsigned int d_8to24table_fbright[256]; extern unsigned int d_8to24table_fbright[256];
extern unsigned int d_8to24table_nobright[256]; extern unsigned int d_8to24table_nobright[256];
extern unsigned int d_8to24table_conchars[256]; extern unsigned int d_8to24table_conchars[256];
extern unsigned int d_8to24table_shirt[256];
extern unsigned int d_8to24table_pants[256];
// TEXTURE MANAGER // TEXTURE MANAGER
@ -98,6 +97,7 @@ void TexMgr_BlockSize (enum srcformat format, int *bytes, int *width, int *heigh
// IMAGE LOADING // IMAGE LOADING
gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format, gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format,
byte *data, const char *source_file, src_offset_t source_offset, unsigned flags); byte *data, const char *source_file, src_offset_t source_offset, unsigned flags);
struct gltexture_s *TexMgr_ColormapTexture(struct gltexture_s *basetex, plcolour_t lower, plcolour_t upper);
void TexMgr_ReloadImage (gltexture_t *glt, plcolour_t shirt, plcolour_t pants); void TexMgr_ReloadImage (gltexture_t *glt, plcolour_t shirt, plcolour_t pants);
void TexMgr_ReloadImages (void); void TexMgr_ReloadImages (void);
void TexMgr_ReloadNobrightImages (void); void TexMgr_ReloadNobrightImages (void);

View file

@ -662,9 +662,82 @@ static plcolour_t setup_oldtop;
static plcolour_t setup_oldbottom; static plcolour_t setup_oldbottom;
static plcolour_t setup_top; static plcolour_t setup_top;
static plcolour_t setup_bottom; static plcolour_t setup_bottom;
extern qboolean keydown[];
//http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
static void rgbtohsv(byte *rgb, vec3_t result)
{ //helper for the setup menu
int r = rgb[0], g = rgb[1], b = rgb[2];
float maxc = q_max(r, q_max(g, b)), minc = q_min(r, q_min(g, b));
float h, s, l = (maxc + minc) / 2;
float d = maxc - minc;
if (maxc)
s = d / maxc;
else
s = 0;
if(maxc == minc)
{
h = 0; // achromatic
}
else
{
if (maxc == r)
h = (g - b) / d + ((g < b) ? 6 : 0);
else if (maxc == g)
h = (b - r) / d + 2;
else
h = (r - g) / d + 4;
h /= 6;
}
result[0] = h;
result[1] = s;
result[2] = l;
};
//http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
static void hsvtorgb(float inh, float s, float v, byte *out)
{ //helper for the setup menu
int r, g, b;
float h = inh - (int)floor(inh);
int i = h * 6;
float f = h * 6 - i;
float p = v * (1 - s);
float q = v * (1 - f * s);
float t = v * (1 - (1 - f) * s);
switch(i)
{
default:
case 0: r = v*0xff, g = t*0xff, b = p*0xff; break;
case 1: r = q*0xff, g = v*0xff, b = p*0xff; break;
case 2: r = p*0xff, g = v*0xff, b = t*0xff; break;
case 3: r = p*0xff, g = q*0xff, b = v*0xff; break;
case 4: r = t*0xff, g = p*0xff, b = v*0xff; break;
case 5: r = v*0xff, g = p*0xff, b = q*0xff; break;
}
out[0] = r;
out[1] = g;
out[2] = b;
};
void M_AdjustColour(plcolour_t *tr, int dir) void M_AdjustColour(plcolour_t *tr, int dir)
{ {
if (keydown[K_SHIFT])
{
vec3_t hsv;
rgbtohsv(CL_PLColours_ToRGB(tr), hsv);
hsv[0] += dir/128.0;
hsv[1] = 1;
hsv[2] = 1; //make these consistent and not inherited from any legacy colours. we're persisting in rgb with small hue changes so we can't actually handle greys, so whack the saturation and brightness right up.
tr->type = 2; //rgb...
tr->basic = 0; //no longer relevant.
hsvtorgb(hsv[0], hsv[1], hsv[2], tr->rgb);
}
else
{ {
tr->type = 1; tr->type = 1;
if (tr->basic+dir < 0) if (tr->basic+dir < 0)

View file

@ -482,6 +482,7 @@ typedef struct entity_state_s
unsigned short tagentity; unsigned short tagentity;
unsigned short pad; unsigned short pad;
unsigned char colormod[3]; //spike -- entity tints, *32 unsigned char colormod[3]; //spike -- entity tints, *32
unsigned char glowmod[3]; //spike -- entity tints, *32
unsigned char alpha; //johnfitz -- added unsigned char alpha; //johnfitz -- added
unsigned int solidsize; //for csqc prediction logic. unsigned int solidsize; //for csqc prediction logic.
#define ES_SOLID_NOT 0 #define ES_SOLID_NOT 0

View file

@ -27,9 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t r_drawflat, gl_overbright_models, gl_fullbrights, r_lerpmodels, r_lerpmove; //johnfitz extern cvar_t r_drawflat, gl_overbright_models, gl_fullbrights, r_lerpmodels, r_lerpmove; //johnfitz
extern cvar_t scr_fov, cl_gun_fovscale; extern cvar_t scr_fov, cl_gun_fovscale;
//up to 16 color translated skins
gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz -- changed to an array of pointers
#define NUMVERTEXNORMALS 162 #define NUMVERTEXNORMALS 162
float r_avertexnormals[NUMVERTEXNORMALS][3] = float r_avertexnormals[NUMVERTEXNORMALS][3] =
@ -88,10 +85,13 @@ typedef struct
// uniforms used in frag shader // uniforms used in frag shader
GLuint texLoc; GLuint texLoc;
GLuint lowerTexLoc;
GLuint upperTexLoc;
GLuint fullbrightTexLoc; GLuint fullbrightTexLoc;
GLuint useFullbrightTexLoc; GLuint useFullbrightTexLoc;
GLuint useOverbrightLoc; GLuint useOverbrightLoc;
GLuint useAlphaTestLoc; GLuint useAlphaTestLoc;
GLuint colorTintLoc;
} aliasglsl_t; } aliasglsl_t;
static aliasglsl_t r_alias_glsl[ALIAS_GLSL_MODES]; static aliasglsl_t r_alias_glsl[ALIAS_GLSL_MODES];
@ -241,23 +241,28 @@ void GLAlias_CreateShaders (void)
"#version 110\n" "#version 110\n"
"\n" "\n"
"uniform sampler2D Tex;\n" "uniform sampler2D Tex;\n"
"uniform sampler2D LowerTex;\n" //team colour
"uniform sampler2D UpperTex;\n" //personal colour
"uniform sampler2D FullbrightTex;\n" "uniform sampler2D FullbrightTex;\n"
"uniform bool UseFullbrightTex;\n" "uniform bool UseFullbrightTex;\n"
"uniform bool UseOverbright;\n" "uniform bool UseOverbright;\n"
"uniform bool UseAlphaTest;\n" "uniform bool UseAlphaTest;\n"
"uniform vec4 ColourTint[3];\n" //base+bot+top+fb
"\n" "\n"
"varying float FogFragCoord;\n" "varying float FogFragCoord;\n"
"\n" "\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" vec4 result = texture2D(Tex, gl_TexCoord[0].xy);\n" " vec4 result = texture2D(Tex, gl_TexCoord[0].xy);\n" //base
" if (ColourTint[0].a != 0.0) result.rgb += texture2D(LowerTex, gl_TexCoord[0].xy).rgb * ColourTint[0].rgb;\n" //team/lower/trousers
" if (ColourTint[1].a != 0.0) result.rgb += texture2D(UpperTex, gl_TexCoord[0].xy).rgb * ColourTint[1].rgb;\n" //personal/upper/torso
" if (UseAlphaTest && (result.a < 0.666))\n" " if (UseAlphaTest && (result.a < 0.666))\n"
" discard;\n" " discard;\n"
" result *= gl_Color;\n" " result *= gl_Color;\n" //vertex lighting results (and colormod).
" if (UseOverbright)\n" " if (UseOverbright)\n"
" result.rgb *= 2.0;\n" " result.rgb *= 2.0;\n"
" if (UseFullbrightTex)\n" " if (UseFullbrightTex)\n"
" result += texture2D(FullbrightTex, gl_TexCoord[0].xy);\n" " result += texture2D(FullbrightTex, gl_TexCoord[0].xy) * ColourTint[2];\n" //fullbrights (with glowmod)
" result = clamp(result, 0.0, 1.0);\n" " result = clamp(result, 0.0, 1.0);\n"
" float fog = exp(-gl_Fog.density * gl_Fog.density * FogFragCoord * FogFragCoord);\n" " float fog = exp(-gl_Fog.density * gl_Fog.density * FogFragCoord * FogFragCoord);\n"
" fog = clamp(fog, 0.0, 1.0) * gl_Fog.color.a;\n" " fog = clamp(fog, 0.0, 1.0) * gl_Fog.color.a;\n"
@ -303,10 +308,21 @@ void GLAlias_CreateShaders (void)
glsl->shadevectorLoc = GL_GetUniformLocation (&glsl->program, "ShadeVector"); glsl->shadevectorLoc = GL_GetUniformLocation (&glsl->program, "ShadeVector");
glsl->lightColorLoc = GL_GetUniformLocation (&glsl->program, "LightColor"); glsl->lightColorLoc = GL_GetUniformLocation (&glsl->program, "LightColor");
glsl->texLoc = GL_GetUniformLocation (&glsl->program, "Tex"); glsl->texLoc = GL_GetUniformLocation (&glsl->program, "Tex");
glsl->lowerTexLoc = GL_GetUniformLocation (&glsl->program, "LowerTex");
glsl->upperTexLoc = GL_GetUniformLocation (&glsl->program, "UpperTex");
glsl->fullbrightTexLoc = GL_GetUniformLocation (&glsl->program, "FullbrightTex"); glsl->fullbrightTexLoc = GL_GetUniformLocation (&glsl->program, "FullbrightTex");
glsl->useFullbrightTexLoc = GL_GetUniformLocation (&glsl->program, "UseFullbrightTex"); glsl->useFullbrightTexLoc = GL_GetUniformLocation (&glsl->program, "UseFullbrightTex");
glsl->useOverbrightLoc = GL_GetUniformLocation (&glsl->program, "UseOverbright"); glsl->useOverbrightLoc = GL_GetUniformLocation (&glsl->program, "UseOverbright");
glsl->useAlphaTestLoc = GL_GetUniformLocation (&glsl->program, "UseAlphaTest"); glsl->useAlphaTestLoc = GL_GetUniformLocation (&glsl->program, "UseAlphaTest");
glsl->colorTintLoc = GL_GetUniformLocation (&glsl->program, "ColourTint");
//we can do this here, its not going to change.
GL_UseProgramFunc (glsl->program);
GL_Uniform1iFunc (glsl->texLoc, 0);
GL_Uniform1iFunc (glsl->fullbrightTexLoc, 1);
GL_Uniform1iFunc (glsl->lowerTexLoc, 2);
GL_Uniform1iFunc (glsl->upperTexLoc, 3);
GL_UseProgramFunc (0);
} }
} }
} }
@ -325,8 +341,9 @@ Supports optional overbright, optional fullbright pixels.
Based on code by MH from RMQEngine Based on code by MH from RMQEngine
============= =============
*/ */
void GL_DrawAliasFrame_GLSL (aliasglsl_t *glsl, aliashdr_t *paliashdr, lerpdata_t lerpdata, gltexture_t *tx, gltexture_t *fb) static void GL_DrawAliasFrame_GLSL (aliasglsl_t *glsl, aliashdr_t *paliashdr, lerpdata_t lerpdata, struct skintextures_s tex, entity_t *e)
{ {
GLfloat tints[3][4];
float blend; float blend;
if (lerpdata.pose1 != lerpdata.pose2) if (lerpdata.pose1 != lerpdata.pose2)
@ -394,28 +411,65 @@ void GL_DrawAliasFrame_GLSL (aliasglsl_t *glsl, aliashdr_t *paliashdr, lerpdata_
break; break;
} }
#define MyVectorScale(a,s,b) do{(b)[0]=(s)*(a)[0];(b)[1]=(s)*(a)[1];(b)[2]=(s)*(a)[2];}while(0)
if (e->netstate.colormap > 0 && e->netstate.colormap <= cl.maxclients)
{
scoreboard_t *sb = &cl.scores[e->netstate.colormap-1];
byte *pal;
pal = CL_PLColours_ToRGB(&sb->pants);
MyVectorScale(pal, 1.0/255, tints[0]);
pal = CL_PLColours_ToRGB(&sb->shirt);
MyVectorScale(pal, 1.0/255, tints[1]);
}
else
{
MyVectorScale((byte*)&d_8to24table[BOTTOM_RANGE+15], 1.0/255, tints[0]);
MyVectorScale((byte*)&d_8to24table[TOP_RANGE+15], 1.0/255, tints[1]);
}
tints[0][3] = 1;
tints[1][3] = 1;
MyVectorScale(e->netstate.glowmod, 1.0/32, tints[2]); tints[2][3] = 1;
// set textures
GL_SelectTexture (GL_TEXTURE0);
GL_Bind (tex.base);
if (tex.luma)
{
GL_SelectTexture (GL_TEXTURE1);
GL_Bind (tex.luma);
}
else
tints[2][0] = tints[2][1] = tints[2][2] = tints[2][3] = 0;
if (tex.lower)
{
GL_SelectTexture (GL_TEXTURE2);
GL_Bind (tex.lower);
}
else
tints[0][0] = tints[0][1] = tints[0][2] = tints[0][3] = 0; //ask the glsl to not read it
if (tex.upper)
{
GL_SelectTexture (GL_TEXTURE3);
GL_Bind (tex.upper);
}
else
tints[1][0] = tints[1][1] = tints[1][2] = tints[1][3] = 0;
// set uniforms // set uniforms
if (glsl->blendLoc != -1) if (glsl->blendLoc != -1)
GL_Uniform1fFunc (glsl->blendLoc, blend); GL_Uniform1fFunc (glsl->blendLoc, blend);
if (glsl->bonesLoc != -1) if (glsl->bonesLoc != -1)
GL_Uniform4fvFunc (glsl->bonesLoc, paliashdr->numbones*3, lerpdata.bonestate->mat); GL_Uniform4fvFunc (glsl->bonesLoc, paliashdr->numbones*3, lerpdata.bonestate->mat);
GL_Uniform3fFunc (glsl->shadevectorLoc, shadevector[0], shadevector[1], shadevector[2]); GL_Uniform3fFunc (glsl->shadevectorLoc, shadevector[0], shadevector[1], shadevector[2]);
GL_Uniform4fFunc (glsl->lightColorLoc, lightcolor[0], lightcolor[1], lightcolor[2], entalpha); GL_Uniform4fFunc (glsl->lightColorLoc, lightcolor[0], lightcolor[1], lightcolor[2], entalpha); //this includes colormod
GL_Uniform1iFunc (glsl->texLoc, 0); GL_Uniform1iFunc (glsl->useFullbrightTexLoc, (tex.luma != NULL) ? 1 : 0);
GL_Uniform1iFunc (glsl->fullbrightTexLoc, 1);
GL_Uniform1iFunc (glsl->useFullbrightTexLoc, (fb != NULL) ? 1 : 0);
GL_Uniform1fFunc (glsl->useOverbrightLoc, overbright ? 1 : 0); GL_Uniform1fFunc (glsl->useOverbrightLoc, overbright ? 1 : 0);
GL_Uniform1iFunc (glsl->useAlphaTestLoc, (currententity->model->flags & MF_HOLEY) ? 1 : 0); GL_Uniform1iFunc (glsl->useAlphaTestLoc, (currententity->model->flags & MF_HOLEY) ? 1 : 0);
GL_Uniform4fvFunc(glsl->colorTintLoc, countof(tints), tints[0]); //colourmapping and glowmod.
// set textures
GL_SelectTexture (GL_TEXTURE0);
GL_Bind (tx);
if (fb)
{
GL_SelectTexture (GL_TEXTURE1);
GL_Bind (fb);
}
// draw // draw
glDrawElements (GL_TRIANGLES, paliashdr->numindexes, GL_UNSIGNED_SHORT, currententity->model->meshindexesvboptr+paliashdr->eboofs); glDrawElements (GL_TRIANGLES, paliashdr->numindexes, GL_UNSIGNED_SHORT, currententity->model->meshindexesvboptr+paliashdr->eboofs);
@ -1054,7 +1108,7 @@ void R_DrawAliasModel (entity_t *e)
aliasglsl_t *glsl; aliasglsl_t *glsl;
aliashdr_t *paliashdr; aliashdr_t *paliashdr;
int anim, skinnum; int anim, skinnum;
gltexture_t *tx, *fb; struct skintextures_s tex;
lerpdata_t lerpdata; lerpdata_t lerpdata;
qboolean alphatest = !!(e->model->flags & MF_HOLEY); qboolean alphatest = !!(e->model->flags & MF_HOLEY);
int surf; int surf;
@ -1152,21 +1206,39 @@ void R_DrawAliasModel (entity_t *e)
} }
if (paliashdr->numskins <= 0) if (paliashdr->numskins <= 0)
{ {
tx = NULL; // NULL will give the checkerboard texture tex.base = tex.luma = tex.lower = tex.upper = NULL; // NULL will give the checkerboard texture
fb = NULL;
} }
else else
tex = paliashdr->textures[skinnum][anim];
if (!gl_nocolors.value)
{ {
tx = paliashdr->gltextures[skinnum][anim]; if (e->eflags & EFLAGS_COLOURMAPPED)
fb = paliashdr->fbtextures[skinnum][anim]; { //support for dp's self.colormap = 4096 | top*16 | bottom; thing (solves corpses changing colours, can't handle rich colours though)
} if (tex.base && tex.base->source_format == SRC_INDEXED && !tex.upper && !tex.lower)
if (e->netstate.colormap && !gl_nocolors.value) {
{ struct gltexture_s *t = TexMgr_ColormapTexture(tex.base, CL_PLColours_FromLegacy(e->netstate.colormap&15), CL_PLColours_FromLegacy(e->netstate.colormap>>4));
if ((uintptr_t)e >= (uintptr_t)&cl.entities[1] && (uintptr_t)e <= (uintptr_t)&cl.entities[cl.maxclients]) /* && !strcmp (currententity->model->name, "progs/player.mdl") */ if (t)
tx = playertextures[e - cl.entities - 1]; tex.base = t;
}
}
else if (e->netstate.colormap>=1&&e->netstate.colormap<=cl.maxclients)
{ //despite being able to handle _shirt+_pants textures in our glsl, we still prefer to generate per-player textures.
//1) works with non-glsl.
//2) preserves the weird non-linear ranges.
//3) ... and without breaking those ranges on models that are NOT colourmapped (the lower's remapped range is the worst of the non-linear ranges, so would make too many models ugly).
//so we only use the shirt+pans stuff when using external textures
//on the plus side, we do use a lookup so we don't break quakerally. csqc also benefits from not needing to worry about edict numbers.
if (tex.base && tex.base->source_format == SRC_INDEXED && !tex.upper && !tex.lower)
{
scoreboard_t *sb = &cl.scores[e->netstate.colormap-1];
struct gltexture_s *t = TexMgr_ColormapTexture(tex.base, sb->pants, sb->shirt);
if (t)
tex.base = t;
}
}
} }
if (!gl_fullbrights.value) if (!gl_fullbrights.value)
fb = NULL; tex.luma = NULL;
// //
// draw it // draw it
@ -1180,14 +1252,14 @@ void R_DrawAliasModel (entity_t *e)
} }
else if (r_fullbright_cheatsafe) else if (r_fullbright_cheatsafe)
{ {
GL_Bind (tx); GL_Bind (tex.base);
shading = false; shading = false;
glColor4f(1,1,1,entalpha); glColor4f(1,1,1,entalpha);
GL_DrawAliasFrame (paliashdr, lerpdata); GL_DrawAliasFrame (paliashdr, lerpdata);
if (fb) if (tex.luma)
{ {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb); GL_Bind(tex.luma);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE); glBlendFunc (GL_ONE, GL_ONE);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -1212,20 +1284,20 @@ void R_DrawAliasModel (entity_t *e)
// r_alias_program will be 0. // r_alias_program will be 0.
else if (glsl->program != 0 && (paliashdr->numbones <= glsl->maxbones||!lerpdata.bonestate)) else if (glsl->program != 0 && (paliashdr->numbones <= glsl->maxbones||!lerpdata.bonestate))
{ {
GL_DrawAliasFrame_GLSL (glsl, paliashdr, lerpdata, tx, fb); GL_DrawAliasFrame_GLSL (glsl, paliashdr, lerpdata, tex, e);
} }
else if (overbright) else if (overbright)
{ {
if (gl_texture_env_combine && gl_mtexable && gl_texture_env_add && fb) //case 1: everything in one pass if (gl_texture_env_combine && gl_mtexable && gl_texture_env_add && tex.luma) //case 1: everything in one pass
{ {
GL_Bind (tx); GL_Bind (tex.base);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
GL_EnableMultitexture(); // selects TEXTURE1 GL_EnableMultitexture(); // selects TEXTURE1
GL_Bind (fb); GL_Bind (tex.luma);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
// glEnable(GL_BLEND); // glEnable(GL_BLEND);
GL_DrawAliasFrame (paliashdr, lerpdata); GL_DrawAliasFrame (paliashdr, lerpdata);
@ -1236,7 +1308,7 @@ void R_DrawAliasModel (entity_t *e)
else if (gl_texture_env_combine) //case 2: overbright in one pass, then fullbright pass else if (gl_texture_env_combine) //case 2: overbright in one pass, then fullbright pass
{ {
// first pass // first pass
GL_Bind(tx); GL_Bind(tex.base);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
@ -1246,10 +1318,10 @@ void R_DrawAliasModel (entity_t *e)
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// second pass // second pass
if (fb) if (tex.luma)
{ {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb); GL_Bind(tex.luma);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE); glBlendFunc (GL_ONE, GL_ONE);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -1267,7 +1339,7 @@ void R_DrawAliasModel (entity_t *e)
else //case 3: overbright in two passes, then fullbright pass else //case 3: overbright in two passes, then fullbright pass
{ {
// first pass // first pass
GL_Bind(tx); GL_Bind(tex.base);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_DrawAliasFrame (paliashdr, lerpdata); GL_DrawAliasFrame (paliashdr, lerpdata);
// second pass -- additive with black fog, to double the object colors but not the fog color // second pass -- additive with black fog, to double the object colors but not the fog color
@ -1282,10 +1354,10 @@ void R_DrawAliasModel (entity_t *e)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND); glDisable(GL_BLEND);
// third pass // third pass
if (fb) if (tex.luma)
{ {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb); GL_Bind(tex.luma);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE); glBlendFunc (GL_ONE, GL_ONE);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -1303,13 +1375,13 @@ void R_DrawAliasModel (entity_t *e)
} }
else else
{ {
if (gl_mtexable && gl_texture_env_add && fb) //case 4: fullbright mask using multitexture if (gl_mtexable && gl_texture_env_add && tex.luma) //case 4: fullbright mask using multitexture
{ {
GL_DisableMultitexture(); // selects TEXTURE0 GL_DisableMultitexture(); // selects TEXTURE0
GL_Bind (tx); GL_Bind (tex.base);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_EnableMultitexture(); // selects TEXTURE1 GL_EnableMultitexture(); // selects TEXTURE1
GL_Bind (fb); GL_Bind (tex.luma);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
glEnable(GL_BLEND); glEnable(GL_BLEND);
GL_DrawAliasFrame (paliashdr, lerpdata); GL_DrawAliasFrame (paliashdr, lerpdata);
@ -1320,13 +1392,13 @@ void R_DrawAliasModel (entity_t *e)
else //case 5: fullbright mask without multitexture else //case 5: fullbright mask without multitexture
{ {
// first pass // first pass
GL_Bind(tx); GL_Bind(tex.base);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_DrawAliasFrame (paliashdr, lerpdata); GL_DrawAliasFrame (paliashdr, lerpdata);
// second pass // second pass
if (fb) if (tex.luma)
{ {
GL_Bind(fb); GL_Bind(tex.luma);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE); glBlendFunc (GL_ONE, GL_ONE);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);