new cvars: r_lavaalpha, r_slimealpha, r_telealpha for fine-tuning specific liquid opacities (from DirectQ, RMQEngine)

new worldspawn keys: _wateralpha, _lavaalpha, _slimealpha, _telealpha, _skyfog (unique to Quakespasm)

The lava/slime/telealpha cvars are non-archived, and default to 0, which means to use the value of r_wateralpha, so they have no effect by default.

The worldspawn keys allow custom maps to set these values in a way that only applies while the map is loaded, and doesn't change the cvar value. (similar to the behaviour of the "fog" worldspawn key.) They are accepted with or without the underscore, like "fog".

see also:
http://forums.insideqc.com/viewtopic.php?f=3&t=5532
http://celephais.net/board/view_thread.php?id=60452&start=937

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1238 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Eric Wasylishen 2015-07-26 21:51:25 +00:00
parent 89a966d3c7
commit 01faf4e5b6
8 changed files with 197 additions and 15 deletions

View File

@ -1193,6 +1193,16 @@ void Mod_LoadFaces (lump_t *l, qboolean bsp2)
else if (out->texinfo->texture->name[0] == '*') // warp surface
{
out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
// detect special liquid types
if (!strncmp (out->texinfo->texture->name, "*lava", 5))
out->flags |= SURF_DRAWLAVA;
else if (!strncmp (out->texinfo->texture->name, "*slime", 6))
out->flags |= SURF_DRAWSLIME;
else if (!strncmp (out->texinfo->texture->name, "*tele", 5))
out->flags |= SURF_DRAWTELE;
else out->flags |= SURF_DRAWWATER;
Mod_PolyForUnlitSurface (out);
GL_SubdivideSurface (out);
}

View File

@ -108,6 +108,10 @@ typedef struct texture_s
#define SURF_UNDERWATER 0x80
#define SURF_NOTEXTURE 0x100 //johnfitz
#define SURF_DRAWFENCE 0x200
#define SURF_DRAWLAVA 0x400
#define SURF_DRAWSLIME 0x800
#define SURF_DRAWTELE 0x1000
#define SURF_DRAWWATER 0x2000
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct

View File

@ -103,6 +103,12 @@ extern cvar_t r_vfog;
cvar_t gl_zfix = {"gl_zfix", "0", CVAR_NONE}; // QuakeSpasm z-fighting fix
cvar_t r_lavaalpha = {"r_lavaalpha","0",CVAR_NONE};
cvar_t r_telealpha = {"r_telealpha","0",CVAR_NONE};
cvar_t r_slimealpha = {"r_slimealpha","0",CVAR_NONE};
float map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha;
qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz
//==============================================================================

View File

@ -109,6 +109,64 @@ static void R_Model_ExtraFlags_List_f (cvar_t *var)
Mod_SetExtraFlags (cl.model_precache[i]);
}
/*
====================
R_SetWateralpha_f -- ericw
====================
*/
static void R_SetWateralpha_f (cvar_t *var)
{
map_wateralpha = var->value;
}
/*
====================
R_SetLavaalpha_f -- ericw
====================
*/
static void R_SetLavaalpha_f (cvar_t *var)
{
map_lavaalpha = var->value;
}
/*
====================
R_SetTelealpha_f -- ericw
====================
*/
static void R_SetTelealpha_f (cvar_t *var)
{
map_telealpha = var->value;
}
/*
====================
R_SetSlimealpha_f -- ericw
====================
*/
static void R_SetSlimealpha_f (cvar_t *var)
{
map_slimealpha = var->value;
}
/*
====================
GL_WaterAlphaForSurfface -- ericw
====================
*/
float GL_WaterAlphaForSurface (msurface_t *fa)
{
if (fa->flags & SURF_DRAWLAVA)
return map_lavaalpha > 0 ? map_lavaalpha : map_wateralpha;
else if (fa->flags & SURF_DRAWTELE)
return map_telealpha > 0 ? map_telealpha : map_wateralpha;
else if (fa->flags & SURF_DRAWSLIME)
return map_slimealpha > 0 ? map_slimealpha : map_wateralpha;
else
return map_wateralpha;
}
/*
===============
R_Init
@ -128,6 +186,7 @@ void R_Init (void)
Cvar_RegisterVariable (&r_drawviewmodel);
Cvar_RegisterVariable (&r_shadows);
Cvar_RegisterVariable (&r_wateralpha);
Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f);
Cvar_RegisterVariable (&r_dynamic);
Cvar_RegisterVariable (&r_novis);
Cvar_SetCallback (&r_novis, R_VisChanged);
@ -173,6 +232,12 @@ void R_Init (void)
//johnfitz
Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
Cvar_RegisterVariable (&r_lavaalpha);
Cvar_RegisterVariable (&r_telealpha);
Cvar_RegisterVariable (&r_slimealpha);
Cvar_SetCallback (&r_lavaalpha, R_SetLavaalpha_f);
Cvar_SetCallback (&r_telealpha, R_SetTelealpha_f);
Cvar_SetCallback (&r_slimealpha, R_SetSlimealpha_f);
R_InitParticles ();
R_SetClearColor_f (&r_clearcolor); //johnfitz
@ -255,6 +320,61 @@ void R_NewGame (void)
playertextures[i] = NULL;
}
/*
=============
R_ParseWorldspawn
called at map load
=============
*/
static void R_ParseWorldspawn (void)
{
char key[128], value[4096];
const char *data;
map_wateralpha = r_wateralpha.value;
map_lavaalpha = r_lavaalpha.value;
map_telealpha = r_telealpha.value;
map_slimealpha = r_slimealpha.value;
data = COM_Parse(cl.worldmodel->entities);
if (!data)
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
data = COM_Parse(data);
if (!data)
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
if (com_token[0] == '_')
strcpy(key, com_token + 1);
else
strcpy(key, com_token);
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
data = COM_Parse(data);
if (!data)
return; // error
strcpy(value, com_token);
if (!strcmp("wateralpha", key))
map_wateralpha = atof(value);
if (!strcmp("lavaalpha", key))
map_lavaalpha = atof(value);
if (!strcmp("telealpha", key))
map_telealpha = atof(value);
if (!strcmp("slimealpha", key))
map_slimealpha = atof(value);
}
}
/*
===============
R_NewMap
@ -284,6 +404,7 @@ void R_NewMap (void)
Sky_NewMap (); //johnfitz -- skybox in worldspawn
Fog_NewMap (); //johnfitz -- global fog in worldspawn
R_ParseWorldspawn (); //ericw -- wateralpha, lavaalpha, telealpha, slimealpha in worldspawn
load_subdivide_size = gl_subdivide_size.value; //johnfitz -- is this the right place to set this?
}

View File

@ -77,6 +77,8 @@ int vec_to_st[6][3] =
{-2,1,-3}
};
float skyfog; // ericw
//==============================================================================
//
// INIT
@ -223,6 +225,7 @@ void Sky_NewMap (void)
skybox_name[0] = 0;
for (i=0; i<6; i++)
skybox_textures[i] = NULL;
skyfog = r_skyfog.value;
//
// read worldspawn (this is so ugly, and shouldn't it be done on the server?)
@ -258,6 +261,9 @@ void Sky_NewMap (void)
if (!strcmp("sky", key))
Sky_LoadSkyBox(value);
if (!strcmp("skyfog", key))
skyfog = atof(value);
#if 1 //also accept non-standard keys
else if (!strcmp("skyname", key)) //half-life
Sky_LoadSkyBox(value);
@ -287,6 +293,17 @@ void Sky_SkyCommand_f (void)
}
}
/*
====================
R_SetSkyfog_f -- ericw
====================
*/
static void R_SetSkyfog_f (cvar_t *var)
{
// clear any skyfog setting from worldspawn
skyfog = var->value;
}
/*
=============
Sky_Init
@ -300,6 +317,7 @@ void Sky_Init (void)
Cvar_RegisterVariable (&r_sky_quality);
Cvar_RegisterVariable (&r_skyalpha);
Cvar_RegisterVariable (&r_skyfog);
Cvar_SetCallback (&r_skyfog, R_SetSkyfog_f);
Cmd_AddCommand ("sky",Sky_SkyCommand_f);
@ -699,14 +717,14 @@ void Sky_DrawSkyBox (void)
rs_skypolys++;
rs_skypasses++;
if (Fog_GetDensity() > 0 && r_skyfog.value > 0)
if (Fog_GetDensity() > 0 && skyfog > 0)
{
float *c;
c = Fog_GetColor();
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (c[0],c[1],c[2], CLAMP(0.0,r_skyfog.value,1.0));
glColor4f (c[0],c[1],c[2], CLAMP(0.0,skyfog,1.0));
glBegin (GL_QUADS);
Sky_EmitSkyBoxVertex (skymins[0][i], skymins[1][i], i);
@ -850,14 +868,14 @@ void Sky_DrawFaceQuad (glpoly_t *p)
rs_skypasses += 2;
}
if (Fog_GetDensity() > 0 && r_skyfog.value > 0)
if (Fog_GetDensity() > 0 && skyfog > 0)
{
float *c;
c = Fog_GetColor();
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (c[0],c[1],c[2], CLAMP(0.0,r_skyfog.value,1.0));
glColor4f (c[0],c[1],c[2], CLAMP(0.0,skyfog,1.0));
glBegin (GL_QUADS);
for (i=0, v=p->verts[0] ; i<4 ; i++, v+=VERTEXSIZE)
@ -993,7 +1011,7 @@ void Sky_DrawSky (void)
//
// render slow sky: cloud layers or skybox
//
if (!r_fastsky.value && !(Fog_GetDensity() > 0 && r_skyfog.value >= 1))
if (!r_fastsky.value && !(Fog_GetDensity() > 0 && skyfog >= 1))
{
glDepthFunc(GL_GEQUAL);
glDepthMask(0);

View File

@ -132,6 +132,9 @@ extern cvar_t r_fullbright;
extern cvar_t r_lightmap;
extern cvar_t r_shadows;
extern cvar_t r_wateralpha;
extern cvar_t r_lavaalpha;
extern cvar_t r_telealpha;
extern cvar_t r_slimealpha;
extern cvar_t r_dynamic;
extern cvar_t r_novis;
@ -296,6 +299,8 @@ typedef struct glsl_attrib_binding_s {
GLuint attrib;
} glsl_attrib_binding_t;
extern float map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha; //ericw
//johnfitz -- fog functions called from outside gl_fog.c
void Fog_ParseServerMessage (void);
float *Fog_GetColor (void);
@ -383,5 +388,7 @@ void GL_ClearBufferBindings ();
void GLSLGamma_DeleteTexture (void);
void GLSLGamma_GammaCorrect (void);
float GL_WaterAlphaForSurface (msurface_t *fa);
#endif /* __GLQUAKE_H */

View File

@ -248,7 +248,7 @@ void R_DrawSequentialPoly (msurface_t *s)
if (s->flags & SURF_DRAWTURB)
{
if (currententity->alpha == ENTALPHA_DEFAULT)
entalpha = CLAMP(0.0,r_wateralpha.value,1.0);
entalpha = CLAMP(0.0, GL_WaterAlphaForSurface(s), 1.0);
if (entalpha < 1)
{

View File

@ -636,6 +636,23 @@ void R_DrawTextureChains_TextureOnly (qmodel_t *model, entity_t *ent, texchain_t
}
}
/*
================
GL_WaterAlphaForEntitySurface -- ericw
Returns the water alpha to use for the entity and surface combination.
================
*/
float GL_WaterAlphaForEntitySurface (entity_t *ent, msurface_t *s)
{
float entalpha;
if (ent == NULL || ent->alpha == ENTALPHA_DEFAULT)
entalpha = GL_WaterAlphaForSurface(s);
else
entalpha = ENTALPHA_DECODE(ent->alpha);
return entalpha;
}
/*
================
R_DrawTextureChains_Water -- johnfitz
@ -653,13 +670,6 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) // ericw -- !r_drawworld_cheatsafe check moved to R_DrawWorld_Water ()
return;
if (ent == NULL || ent->alpha == ENTALPHA_DEFAULT)
entalpha = r_wateralpha.value;
else
entalpha = ENTALPHA_DECODE(ent->alpha);
R_BeginTransparentDrawing (entalpha);
if (r_oldwater.value)
{
for (i=0 ; i<model->numtextures ; i++)
@ -668,11 +678,14 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
if (!t || !t->texturechains[chain] || !(t->texturechains[chain]->flags & SURF_DRAWTURB))
continue;
bound = false;
entalpha = 1.0f;
for (s = t->texturechains[chain]; s; s = s->texturechain)
if (!s->culled)
{
if (!bound) //only bind once we are sure we need this texture
{
entalpha = GL_WaterAlphaForEntitySurface (ent, s);
R_BeginTransparentDrawing (entalpha);
GL_Bind (t->gltexture);
bound = true;
}
@ -682,6 +695,7 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
rs_brushpasses++;
}
}
R_EndTransparentDrawing (entalpha);
}
}
else
@ -692,11 +706,14 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
if (!t || !t->texturechains[chain] || !(t->texturechains[chain]->flags & SURF_DRAWTURB))
continue;
bound = false;
entalpha = 1.0f;
for (s = t->texturechains[chain]; s; s = s->texturechain)
if (!s->culled)
{
if (!bound) //only bind once we are sure we need this texture
{
entalpha = GL_WaterAlphaForEntitySurface (ent, s);
R_BeginTransparentDrawing (entalpha);
GL_Bind (t->warpimage);
if (model != cl.worldmodel)
@ -712,10 +729,9 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
DrawGLPoly (s->polys);
rs_brushpasses++;
}
R_EndTransparentDrawing (entalpha);
}
}
R_EndTransparentDrawing (entalpha);
}
/*