mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-01-31 12:40:43 +00:00
saneified dynamic light colour values.
added preliminary support for some rtlight cubemaps. no longer using tmpfile in win32 - its too unreliable. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3942 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
54358b62b2
commit
f32a88f684
24 changed files with 458 additions and 467 deletions
|
@ -800,7 +800,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
|
|||
case CG_R_ADDLIGHTTOSCENE: //add light to scene.
|
||||
{
|
||||
float *org = VM_POINTER(arg[0]);
|
||||
CL_NewDlightRGB(-1, org, VM_FLOAT(arg[1]), 0, VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]));
|
||||
CL_NewDlight(-1, org, VM_FLOAT(arg[1]), 0, VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]));
|
||||
}
|
||||
break;
|
||||
case CG_R_RENDERSCENE: //render scene
|
||||
|
|
|
@ -189,27 +189,7 @@ dlight_t *CL_AllocDlight (int key)
|
|||
CL_NewDlight
|
||||
===============
|
||||
*/
|
||||
dlight_t *CL_NewDlight (int key, const vec3_t org, float radius, float time, int type)
|
||||
{
|
||||
static const vec3_t lightcolour[] =
|
||||
{
|
||||
{0.2, 0.1, 0.05},
|
||||
{0.05, 0.05, 0.3},
|
||||
{0.5, 0.05, 0.05},
|
||||
{0.5, 0.05, 0.4}
|
||||
};
|
||||
dlight_t *dl;
|
||||
if (type >= sizeof(lightcolour)/sizeof(lightcolour[0]))
|
||||
type = 0;
|
||||
|
||||
dl = CL_AllocDlight (key);
|
||||
VectorCopy(org, dl->origin);
|
||||
dl->radius = radius;
|
||||
dl->die = (float)cl.time + time;
|
||||
VectorCopy(lightcolour[type], dl->color);
|
||||
return dl;
|
||||
}
|
||||
dlight_t *CL_NewDlightRGB (int key, const vec3_t org, float radius, float time,
|
||||
dlight_t *CL_NewDlight (int key, const vec3_t org, float radius, float time,
|
||||
float r, float g, float b)
|
||||
{
|
||||
dlight_t *dl;
|
||||
|
@ -225,6 +205,12 @@ dlight_t *CL_NewDlightRGB (int key, const vec3_t org, float radius, float time,
|
|||
return dl;
|
||||
}
|
||||
|
||||
dlight_t *CL_NewDlightRGB(int key, const vec3_t org, float radius, float time,
|
||||
float r, float g, float b)
|
||||
{
|
||||
return CL_NewDlight(key, org, radius, time, r*5, g*5, b*5);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
|
@ -2050,36 +2036,36 @@ void CL_LinkPacketEntities (void)
|
|||
if (state->effects & EF_BRIGHTLIGHT)
|
||||
{
|
||||
radius = max(radius,400);
|
||||
colour[0] += 0.2;
|
||||
colour[1] += 0.1;
|
||||
colour[2] += 0.05;
|
||||
colour[0] += 2.0;
|
||||
colour[1] += 1.0;
|
||||
colour[2] += 0.5;
|
||||
}
|
||||
if (state->effects & EF_DIMLIGHT)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.2;
|
||||
colour[1] += 0.1;
|
||||
colour[2] += 0.05;
|
||||
colour[0] += 2.0;
|
||||
colour[1] += 1.0;
|
||||
colour[2] += 0.5;
|
||||
}
|
||||
if (state->effects & EF_BLUE)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.05;
|
||||
colour[1] += 0.05;
|
||||
colour[2] += 0.3;
|
||||
colour[0] += 0.5;
|
||||
colour[1] += 0.5;
|
||||
colour[2] += 3.0;
|
||||
}
|
||||
if (state->effects & EF_RED)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.5;
|
||||
colour[1] += 0.05;
|
||||
colour[2] += 0.05;
|
||||
colour[0] += 5.0;
|
||||
colour[1] += 0.5;
|
||||
colour[2] += 0.5;
|
||||
}
|
||||
|
||||
if (radius)
|
||||
{
|
||||
radius += r_lightflicker.value?((flicker + state->number)&31):0;
|
||||
CL_NewDlightRGB(state->number, state->origin, radius, 0.1, colour[0], colour[1], colour[2]);
|
||||
CL_NewDlight(state->number, state->origin, radius, 0.1, colour[0], colour[1], colour[2]);
|
||||
}
|
||||
}
|
||||
if (state->lightpflags & PFLAGS_FULLDYNAMIC)
|
||||
|
@ -2095,7 +2081,8 @@ void CL_LinkPacketEntities (void)
|
|||
colour[1] = state->light[1]/1024.0f;
|
||||
colour[2] = state->light[2]/1024.0f;
|
||||
}
|
||||
CL_NewDlightRGB(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
|
||||
CL_NewDlight(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
|
||||
/*FIXME: .skin is meant to be "cubemaps/%i" */
|
||||
}
|
||||
|
||||
// if set to invisible, skip
|
||||
|
@ -2998,23 +2985,23 @@ void CL_LinkPlayers (void)
|
|||
if (state->effects & EF_DIMLIGHT)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.2;
|
||||
colour[1] += 0.1;
|
||||
colour[2] += 0.05;
|
||||
colour[0] += 2.0;
|
||||
colour[1] += 1.0;
|
||||
colour[2] += 0.5;
|
||||
}
|
||||
if (state->effects & EF_BLUE)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.05;
|
||||
colour[1] += 0.05;
|
||||
colour[2] += 0.3;
|
||||
colour[0] += 0.5;
|
||||
colour[1] += 0.5;
|
||||
colour[2] += 3.0;
|
||||
}
|
||||
if (state->effects & EF_RED)
|
||||
{
|
||||
radius = max(radius,200);
|
||||
colour[0] += 0.5;
|
||||
colour[1] += 0.05;
|
||||
colour[2] += 0.05;
|
||||
colour[0] += 5.0;
|
||||
colour[1] += 0.5;
|
||||
colour[2] += 0.5;
|
||||
}
|
||||
|
||||
if (radius)
|
||||
|
@ -3039,7 +3026,7 @@ void CL_LinkPlayers (void)
|
|||
}
|
||||
radius += (flicker+j)&31;
|
||||
}
|
||||
CL_NewDlightRGB(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_FLASHBLEND;
|
||||
CL_NewDlight(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_FLASHBLEND;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3176,7 +3163,7 @@ void CL_LinkPlayers (void)
|
|||
if (r_torch.ival)
|
||||
{
|
||||
dlight_t *dl;
|
||||
dl = CL_NewDlightRGB(j+1, ent->origin, 300, r_torch.ival, 0.05, 0.05, 0.02);
|
||||
dl = CL_NewDlight(j+1, ent->origin, 300, r_torch.ival, 0.5, 0.5, 0.2);
|
||||
dl->flags |= LFLAG_SHADOWMAP|LFLAG_FLASHBLEND;
|
||||
dl->fov = 60;
|
||||
angles[0] *= 3;
|
||||
|
|
|
@ -1077,9 +1077,9 @@ void CL_ParseTEnt (void)
|
|||
dl->die = cl.time + 1;
|
||||
dl->decay = 300;
|
||||
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.155;
|
||||
dl->color[2] = 0.05;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.775;
|
||||
dl->color[2] = 0.25;
|
||||
dl->channelfade[0] = 0.196;
|
||||
dl->channelfade[1] = 0.23;
|
||||
dl->channelfade[2] = 0.12;
|
||||
|
@ -1117,9 +1117,9 @@ void CL_ParseTEnt (void)
|
|||
dl->die = cl.time + 1;
|
||||
dl->decay = 300;
|
||||
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.155;
|
||||
dl->color[2] = 0.05;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.775;
|
||||
dl->color[2] = 0.25;
|
||||
dl->channelfade[0] = 0.196;
|
||||
dl->channelfade[1] = 0.23;
|
||||
dl->channelfade[2] = 0.12;
|
||||
|
@ -1189,9 +1189,9 @@ void CL_ParseTEnt (void)
|
|||
dl->die = cl.time + 1;
|
||||
dl->decay = 500;
|
||||
|
||||
dl->color[0] = 0.4f;
|
||||
dl->color[1] = 0.3f;
|
||||
dl->color[2] = 0.15f;
|
||||
dl->color[0] = 2.0f;
|
||||
dl->color[1] = 1.5f;
|
||||
dl->color[2] = 0.75f;
|
||||
dl->channelfade[0] = 0;
|
||||
dl->channelfade[1] = 0;
|
||||
dl->channelfade[2] = 0;
|
||||
|
@ -1371,9 +1371,9 @@ void CL_ParseTEnt (void)
|
|||
dl->radius = 200;
|
||||
dl->decay = 1000;
|
||||
dl->die = cl.time + 0.2;
|
||||
dl->color[0] = 0.4;
|
||||
dl->color[1] = 0.4;
|
||||
dl->color[2] = 0.4;
|
||||
dl->color[0] = 2.0;
|
||||
dl->color[1] = 2.0;
|
||||
dl->color[2] = 2.0;
|
||||
break;
|
||||
|
||||
case TEDP_CUSTOMFLASH:
|
||||
|
@ -1389,10 +1389,9 @@ void CL_ParseTEnt (void)
|
|||
dl->die = cl.time + pos2[0];
|
||||
dl->decay = dl->radius / pos2[0];
|
||||
|
||||
// DP's range is 0-2 for lights, FTE is 0-0.4.. 255/637.5 = 0.4
|
||||
dl->color[0] = MSG_ReadByte()*(1.0f/637.5f);
|
||||
dl->color[1] = MSG_ReadByte()*(1.0f/637.5f);
|
||||
dl->color[2] = MSG_ReadByte()*(1.0f/637.5f);
|
||||
dl->color[0] = MSG_ReadByte()*(1.0f/127.0f);
|
||||
dl->color[1] = MSG_ReadByte()*(1.0f/127.5f);
|
||||
dl->color[2] = MSG_ReadByte()*(1.0f/127.0f);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1426,9 +1425,9 @@ void CL_ParseTEnt (void)
|
|||
dl->radius = 200;
|
||||
dl->decay = 1000;
|
||||
dl->die = cl.time + 0.2;
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.2;
|
||||
dl->color[2] = 0.2;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 1.0;
|
||||
dl->color[2] = 1.0;
|
||||
|
||||
// stain (Hopefully this is close to how DP does it)
|
||||
R_AddStain(pos, -10, -10, -10, 30);
|
||||
|
@ -2110,8 +2109,8 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 * r_explosionlight.value;
|
||||
dl->die = cl.time + 0.4;
|
||||
dl->decay = 400;
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.2;
|
||||
dl->color[0] = 1;
|
||||
dl->color[1] = 1;
|
||||
dl->color[2] = 0.0;
|
||||
dl->channelfade[0] = 0.5;
|
||||
dl->channelfade[1] = 0.51;
|
||||
|
@ -2147,9 +2146,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 + r_explosionlight.value*200;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.1;
|
||||
dl->color[2] = 0.1;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.5;
|
||||
dl->color[2] = 0.5;
|
||||
dl->channelfade[0] = 0.36;
|
||||
dl->channelfade[1] = 0.19;
|
||||
dl->channelfade[2] = 0.19;
|
||||
|
@ -2243,9 +2242,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 + r_explosionlight.value*200;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.1;
|
||||
dl->color[2] = 0.08;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.5;
|
||||
dl->color[2] = 0.4;
|
||||
dl->channelfade[0] = 0.36;
|
||||
dl->channelfade[1] = 0.19;
|
||||
dl->channelfade[2] = 0.19;
|
||||
|
@ -2440,9 +2439,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 * r_explosionlight.value;
|
||||
dl->die = cl.time + 0.4;
|
||||
dl->decay = 400;
|
||||
dl->color[0] = 0.01;
|
||||
dl->color[1] = 0.2;
|
||||
dl->color[2] = 0.01;
|
||||
dl->color[0] = 0.05;
|
||||
dl->color[1] = 1.0;
|
||||
dl->color[2] = 0.05;
|
||||
dl->channelfade[0] = 0.1;
|
||||
dl->channelfade[1] = 0.5;
|
||||
dl->channelfade[2] = 0.1;
|
||||
|
@ -2490,9 +2489,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 * r_explosionlight.value;
|
||||
dl->die = cl.time + 0.4;
|
||||
dl->decay = 400;
|
||||
dl->color[0] = 0.038;
|
||||
dl->color[1] = 0.082;
|
||||
dl->color[2] = 0.150;
|
||||
dl->color[0] = 0.19;
|
||||
dl->color[1] = 0.41;
|
||||
dl->color[2] = 0.75;
|
||||
dl->channelfade[0] = 0.085;
|
||||
dl->channelfade[1] = 0.180;
|
||||
dl->channelfade[2] = 0.300;
|
||||
|
@ -2535,9 +2534,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 + r_explosionlight.value*200;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
dl->color[0] = 0.2;
|
||||
dl->color[1] = 0.1;
|
||||
dl->color[2] = 0.08;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.5;
|
||||
dl->color[2] = 0.4;
|
||||
dl->channelfade[0] = 0.36;
|
||||
dl->channelfade[1] = 0.19;
|
||||
dl->channelfade[2] = 0.19;
|
||||
|
@ -2650,9 +2649,9 @@ void CLQ2_ParseTEnt (void)
|
|||
dl->radius = 150 * r_explosionlight.value;
|
||||
dl->die = cl.time + 0.1;
|
||||
dl->minlight = 250;
|
||||
dl->color[0] = -0.2;
|
||||
dl->color[1] = -0.2;
|
||||
dl->color[2] = -0.2;
|
||||
dl->color[0] = -1.0;
|
||||
dl->color[1] = -1.0;
|
||||
dl->color[2] = -1.0;
|
||||
}
|
||||
|
||||
// sound
|
||||
|
|
|
@ -579,7 +579,7 @@ void VQ3_RenderView(const q3refdef_t *ref)
|
|||
if (r_torch.ival)
|
||||
{
|
||||
dlight_t *dl;
|
||||
dl = CL_NewDlightRGB(0, ref->vieworg, 300, r_torch.ival, 0.05, 0.05, 0.02);
|
||||
dl = CL_NewDlight(0, ref->vieworg, 300, r_torch.ival, 0.5, 0.5, 0.2);
|
||||
dl->flags |= LFLAG_SHADOWMAP|LFLAG_FLASHBLEND;
|
||||
dl->fov = 60;
|
||||
VectorCopy(ref->viewaxis[0], dl->axis[0]);
|
||||
|
|
|
@ -1288,7 +1288,7 @@ int CLHL_ParseGamePacket(void)
|
|||
if (!(flags & 4))
|
||||
S_StartSound(0, 0, S_PrecacheSound("explosion"), startp, 1, 1);
|
||||
if (!(flags & 2))
|
||||
CL_NewDlightRGB(0, startp, 200, 1, 0.2,0.2,0.2);
|
||||
CL_NewDlight(0, startp, 200, 1, 2.0,2.0,2.0);
|
||||
|
||||
ef = CL_AllocExplosion();
|
||||
VectorCopy(startp, ef->origin);
|
||||
|
|
|
@ -770,7 +770,7 @@ void CL_InitDlights(void);
|
|||
void CL_FreeDlights(void);
|
||||
dlight_t *CL_AllocDlight (int key);
|
||||
dlight_t *CL_AllocSlight (void); //allocates a static light
|
||||
dlight_t *CL_NewDlight (int key, const vec3_t origin, float radius, float time, int type);
|
||||
dlight_t *CL_NewDlight (int key, const vec3_t origin, float radius, float time, float r, float g, float b);
|
||||
dlight_t *CL_NewDlightRGB (int key, const vec3_t origin, float radius, float time, float r, float g, float b);
|
||||
dlight_t *CL_NewDlightCube (int key, const vec3_t origin, vec3_t angles, float radius, float time, vec3_t colours);
|
||||
void CL_DecayLights (void);
|
||||
|
|
|
@ -1588,7 +1588,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
|
|||
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ent.keynum, ¢->trailstate))
|
||||
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xdc, 4, ¢->trailstate);
|
||||
|
||||
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0);
|
||||
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.1, 0.05);
|
||||
}
|
||||
// PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER.
|
||||
// EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese!
|
||||
|
|
|
@ -2342,7 +2342,6 @@ static struct
|
|||
};
|
||||
|
||||
int image_width, image_height;
|
||||
//fixme: should probably get rid of the 'Mod' prefix, and use something more suitable.
|
||||
texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
||||
{
|
||||
qboolean alphaed;
|
||||
|
@ -2368,19 +2367,71 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
}
|
||||
|
||||
snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); /*should be safe if its null*/
|
||||
if (subpath && *subpath)
|
||||
if (subpath && *subpath && !(flags & IF_REPLACE))
|
||||
{
|
||||
tex = R_FindTexture(fname);
|
||||
if (TEXVALID(tex)) //don't bother if it already exists.
|
||||
return tex;
|
||||
}
|
||||
if (!(flags & IF_SUBDIRONLY))
|
||||
if (!(flags & IF_SUBDIRONLY) && !(flags & IF_REPLACE))
|
||||
{
|
||||
tex = R_FindTexture(name);
|
||||
if (TEXVALID(tex)) //don't bother if it already exists.
|
||||
return tex;
|
||||
}
|
||||
|
||||
if ((flags & IF_TEXTYPE) == IF_CUBEMAP)
|
||||
{
|
||||
int j;
|
||||
char *suf[] =
|
||||
{
|
||||
// "rt", "lf", "ft", "bk", "up", "dn",
|
||||
"px", "nx", "py", "ny", "pz", "nz",
|
||||
"posx", "negx", "posy", "negy", "posz", "negz"
|
||||
};
|
||||
flags |= IF_REPLACE;
|
||||
|
||||
tex = r_nulltex;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
tex = r_nulltex;
|
||||
for (e = sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--)
|
||||
{
|
||||
if (!tex_extensions[e].enabled)
|
||||
continue;
|
||||
|
||||
buf = NULL;
|
||||
for (j = 0; j < sizeof(suf)/sizeof(suf[0])/6; j++)
|
||||
{
|
||||
snprintf(fname, sizeof(fname)-1, "%s%s%s", nicename, suf[i + 6*j], tex_extensions[e].name);
|
||||
buf = COM_LoadFile (fname, 5);
|
||||
if (buf)
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf)
|
||||
{
|
||||
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, fname)))
|
||||
{
|
||||
extern cvar_t vid_hardwaregamma;
|
||||
if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value)
|
||||
BoostGamma(data, image_width, image_height);
|
||||
|
||||
tex = R_LoadTexture32 (name, image_width, image_height, data, (flags | IF_REPLACE) + (i << IF_TEXTYPESHIFT));
|
||||
|
||||
BZ_Free(data);
|
||||
BZ_Free(buf);
|
||||
if (TEXVALID(tex))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TEXVALID(tex))
|
||||
return r_nulltex;
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
||||
if (subpath && *subpath)
|
||||
{
|
||||
|
|
|
@ -2416,7 +2416,7 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir, in
|
|||
}
|
||||
if (ptype->dl_radius)
|
||||
{
|
||||
dlight_t *dl = CL_NewDlightRGB(dlkey, org, ptype->dl_radius, ptype->dl_time, ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]);
|
||||
dlight_t *dl = CL_NewDlight(dlkey, org, ptype->dl_radius, ptype->dl_time, ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]);
|
||||
dl->channelfade[0] = ptype->dl_decay[0];
|
||||
dl->channelfade[1] = ptype->dl_decay[1];
|
||||
dl->channelfade[2] = ptype->dl_decay[2];
|
||||
|
|
|
@ -833,7 +833,7 @@ static void QCBUILTIN PF_R_DynamicLight_Add(progfuncs_t *prinst, struct globalva
|
|||
dlight_t *dl;
|
||||
|
||||
//if the org matches self, then attach it.
|
||||
dl = CL_NewDlightRGB (VectorCompare(self->v->origin, org)?-self->entnum:0, org, radius, -0.1, rgb[0], rgb[1], rgb[2]);
|
||||
dl = CL_NewDlight (VectorCompare(self->v->origin, org)?-self->entnum:0, org, radius, -0.1, rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
if (pflags & PFLAGS_NOSHADOW)
|
||||
dl->flags |= LFLAG_NOSHADOWS;
|
||||
|
@ -3266,43 +3266,6 @@ static void QCBUILTIN PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalv
|
|||
VectorCopy(srcorg, retorg);
|
||||
}
|
||||
|
||||
static void QCBUILTIN PF_rotatevectorsbyangles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *ang = G_VECTOR(OFS_PARM0);
|
||||
vec3_t src[3], trans[3], res[3];
|
||||
ang[0]*=-1;
|
||||
AngleVectors(ang, trans[0], trans[1], trans[2]);
|
||||
ang[0]*=-1;
|
||||
VectorInverse(trans[1]);
|
||||
|
||||
VectorCopy(csqcg.forward, src[0]);
|
||||
VectorNegate(csqcg.right, src[1]);
|
||||
VectorCopy(csqcg.up, src[2]);
|
||||
|
||||
R_ConcatRotations(trans, src, res);
|
||||
|
||||
VectorCopy(res[0], csqcg.forward);
|
||||
VectorNegate(res[1], csqcg.right);
|
||||
VectorCopy(res[2], csqcg.up);
|
||||
}
|
||||
static void QCBUILTIN PF_rotatevectorsbymatrix (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
vec3_t src[3], trans[3], res[3];
|
||||
|
||||
VectorCopy(G_VECTOR(OFS_PARM0), src[0]);
|
||||
VectorNegate(G_VECTOR(OFS_PARM1), src[1]);
|
||||
VectorCopy(G_VECTOR(OFS_PARM2), src[2]);
|
||||
|
||||
VectorCopy(csqcg.forward, src[0]);
|
||||
VectorNegate(csqcg.right, src[1]);
|
||||
VectorCopy(csqcg.up, src[2]);
|
||||
|
||||
R_ConcatRotations(trans, src, res);
|
||||
|
||||
VectorCopy(res[0], csqcg.forward);
|
||||
VectorNegate(res[1], csqcg.right);
|
||||
VectorCopy(res[2], csqcg.up);
|
||||
}
|
||||
static void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int modelindex = G_FLOAT(OFS_PARM0);
|
||||
|
|
|
@ -363,7 +363,7 @@ static void Surf_AddDynamicLights (msurface_t *surf)
|
|||
local[0] -= surf->texturemins[0];
|
||||
local[1] -= surf->texturemins[1];
|
||||
|
||||
a = 256*(cl_dlights[lnum].color[0]*1.5 + cl_dlights[lnum].color[1]*2.95 + cl_dlights[lnum].color[2]*0.55);
|
||||
a = 256*(cl_dlights[lnum].color[0]*NTSC_RED + cl_dlights[lnum].color[1]*NTSC_GREEN + cl_dlights[lnum].color[2]*NTSC_BLUE);
|
||||
|
||||
bl = blocklights;
|
||||
for (t = 0 ; t<tmax ; t++)
|
||||
|
@ -510,9 +510,9 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf)
|
|||
local[0] -= surf->texturemins[0];
|
||||
local[1] -= surf->texturemins[1];
|
||||
|
||||
r = cl_dlights[lnum].color[0]*256;
|
||||
g = cl_dlights[lnum].color[1]*256;
|
||||
b = cl_dlights[lnum].color[2]*256;
|
||||
r = cl_dlights[lnum].color[0]*128;
|
||||
g = cl_dlights[lnum].color[1]*128;
|
||||
b = cl_dlights[lnum].color[2]*128;
|
||||
|
||||
/* if (cl_dlights[lnum].type == 1) //a wierd effect.
|
||||
{
|
||||
|
|
|
@ -270,9 +270,13 @@ enum imageflags
|
|||
IF_NOALPHA = 1<<3,
|
||||
IF_NOGAMMA = 1<<4,
|
||||
IF_NEAREST = 1<<5,
|
||||
IF_CUBEMAP = 1<<6,
|
||||
IF_3DMAP = 1<<7,
|
||||
IF_3DMAP = 1<<6, /*waning - don't test directly*/
|
||||
IF_CUBEMAP = 1<<7, /*waning - don't test directly*/
|
||||
IF_CUBEMAPEXTRA = 1<<8,
|
||||
IF_TEXTYPE = (1<<6) | (1<<7) | (1<<8), /*0=2d, 1=3d, 2-7=cubeface*/
|
||||
IF_TEXTYPESHIFT = 6, /*0=2d, 1=3d, 2-7=cubeface*/
|
||||
|
||||
IF_REPLACE = 1<<30,
|
||||
IF_SUBDIRONLY = 1<<31
|
||||
};
|
||||
|
||||
|
|
|
@ -211,6 +211,7 @@ cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset"
|
|||
rendererstate_t currentrendererstate;
|
||||
|
||||
#if defined(GLQUAKE)
|
||||
cvar_t gl_workaround_ati_shadersource = CVARD ("gl_workaround_ati_shadersource", "1", "Work around ATI driver bugs in the glShaderSource function. Can safely be enabled with other drivers too.");
|
||||
cvar_t vid_gl_context_version = SCVAR ("vid_gl_context_version", "");
|
||||
cvar_t vid_gl_context_forwardcompatible = SCVAR ("vid_gl_context_forwardcompatible", "0");
|
||||
cvar_t vid_gl_context_compatibility = SCVAR ("vid_gl_context_compatibility", "1");
|
||||
|
@ -338,6 +339,7 @@ void GLRenderer_Init(void)
|
|||
extern cvar_t gl_contrast;
|
||||
|
||||
//gl-specific video vars
|
||||
Cvar_Register (&gl_workaround_ati_shadersource, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&vid_gl_context_version, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&vid_gl_context_debug, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&vid_gl_context_forwardcompatible, GLRENDEREROPTIONS);
|
||||
|
|
|
@ -62,22 +62,47 @@ static void VFSSTDIO_Close(vfsfile_t *file)
|
|||
Z_Free(file);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void VFSSTDIO_CloseTemp(vfsfile_t *file)
|
||||
{
|
||||
vfsstdiofile_t *intfile = (vfsstdiofile_t*)file;
|
||||
char *fname = (char*)(intfile+1);
|
||||
fclose(intfile->handle);
|
||||
_unlink(fname);
|
||||
Z_Free(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
vfsfile_t *FSSTDIO_OpenTemp(void)
|
||||
{
|
||||
FILE *f;
|
||||
vfsstdiofile_t *file;
|
||||
|
||||
#ifdef _WIN32
|
||||
/*warning: annother app might manage to open the file before we can. if the file is not opened exclusively then we can end up with issues
|
||||
on windows, fopen is typically exclusive anyway, but not on unix. but on unix, tmpfile is actually usable, so special-case the windows code*/
|
||||
char *fname = _tempnam(NULL, "ftemp");
|
||||
f = fopen(fname, "w+b");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
file = Z_Malloc(sizeof(vfsstdiofile_t) + strlen(fname)+1);
|
||||
file->funcs.Close = VFSSTDIO_CloseTemp;
|
||||
strcpy((char*)(file+1), fname);
|
||||
free(fname);
|
||||
#else
|
||||
f = tmpfile();
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
file = Z_Malloc(sizeof(vfsstdiofile_t));
|
||||
file->funcs.Close = VFSSTDIO_Close;
|
||||
#endif
|
||||
file->funcs.ReadBytes = VFSSTDIO_ReadBytes;
|
||||
file->funcs.WriteBytes = VFSSTDIO_WriteBytes;
|
||||
file->funcs.Seek = VFSSTDIO_Seek;
|
||||
file->funcs.Tell = VFSSTDIO_Tell;
|
||||
file->funcs.GetLen = VFSSTDIO_GetSize;
|
||||
file->funcs.Close = VFSSTDIO_Close;
|
||||
file->funcs.Flush = VFSSTDIO_Flush;
|
||||
file->handle = f;
|
||||
|
||||
|
|
|
@ -2660,6 +2660,48 @@ void QCBUILTIN PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_global
|
|||
VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
|
||||
}
|
||||
|
||||
void QCBUILTIN PF_rotatevectorsbyangles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
|
||||
float *ang = G_VECTOR(OFS_PARM0);
|
||||
vec3_t src[3], trans[3], res[3];
|
||||
ang[0]*=-1;
|
||||
AngleVectors(ang, trans[0], trans[1], trans[2]);
|
||||
ang[0]*=-1;
|
||||
VectorInverse(trans[1]);
|
||||
|
||||
VectorCopy(w->g.v_forward, src[0]);
|
||||
VectorNegate(w->g.v_right, src[1]);
|
||||
VectorCopy(w->g.v_up, src[2]);
|
||||
|
||||
R_ConcatRotations(trans, src, res);
|
||||
|
||||
VectorCopy(res[0], w->g.v_forward);
|
||||
VectorNegate(res[1], w->g.v_right);
|
||||
VectorCopy(res[2], w->g.v_up);
|
||||
}
|
||||
|
||||
void QCBUILTIN PF_rotatevectorsbymatrix (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
vec3_t src[3], trans[3], res[3];
|
||||
|
||||
VectorCopy(G_VECTOR(OFS_PARM0), src[0]);
|
||||
VectorNegate(G_VECTOR(OFS_PARM1), src[1]);
|
||||
VectorCopy(G_VECTOR(OFS_PARM2), src[2]);
|
||||
|
||||
VectorCopy(w->g.v_forward, src[0]);
|
||||
VectorNegate(w->g.v_right, src[1]);
|
||||
VectorCopy(w->g.v_up, src[2]);
|
||||
|
||||
R_ConcatRotations(trans, src, res);
|
||||
|
||||
VectorCopy(res[0], w->g.v_forward);
|
||||
VectorNegate(res[1], w->g.v_right);
|
||||
VectorCopy(res[2], w->g.v_up);
|
||||
}
|
||||
|
||||
//Vector functions
|
||||
////////////////////////////////////////////////////
|
||||
//Progs internals
|
||||
|
|
|
@ -146,6 +146,8 @@ void QCBUILTIN PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_global
|
|||
void QCBUILTIN PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_rotatevectorsbyangles (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_rotatevectorsbymatrix (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void PF_findchainfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
|
|
|
@ -20,230 +20,6 @@
|
|||
|
||||
extern cvar_t gl_overbright;
|
||||
|
||||
#if 0
|
||||
#define LIGHTPASS_GLSL_SHARED "\
|
||||
varying vec2 tcbase;\n\
|
||||
varying vec3 lightvector;\n\
|
||||
#if defined(SPECULAR) || defined(OFFSETMAPPING)\n\
|
||||
varying vec3 eyevector;\n\
|
||||
#endif\n\
|
||||
#ifdef PCF\n\
|
||||
varying vec4 vshadowcoord;\n\
|
||||
uniform mat4 entmatrix;\n\
|
||||
#endif\n\
|
||||
"
|
||||
|
||||
#define LIGHTPASS_GLSL_VERTEX "\
|
||||
#ifdef VERTEX_SHADER\n\
|
||||
#include \"sys/skeletal.h\"\n\
|
||||
\
|
||||
uniform vec3 l_lightposition;\n\
|
||||
attribute vec2 v_texcoord;\n\
|
||||
\
|
||||
#if defined(SPECULAR) || defined(OFFSETMAPPING)\n\
|
||||
uniform vec3 e_eyepos;\n\
|
||||
#endif\n\
|
||||
\
|
||||
void main ()\n\
|
||||
{\n\
|
||||
vec3 n, s, t, w;\n\
|
||||
gl_Position = skeletaltransform_wnst(w,n,s,t);\n\
|
||||
\
|
||||
tcbase = v_texcoord; //pass the texture coords straight through\n\
|
||||
\
|
||||
vec3 lightminusvertex = l_lightposition - w.xyz;\n\
|
||||
lightvector.x = dot(lightminusvertex, s.xyz);\n\
|
||||
lightvector.y = dot(lightminusvertex, t.xyz);\n\
|
||||
lightvector.z = dot(lightminusvertex, n.xyz);\n\
|
||||
\
|
||||
#if defined(SPECULAR)||defined(OFFSETMAPPING)\n\
|
||||
vec3 eyeminusvertex = e_eyepos - w.xyz;\n\
|
||||
eyevector.x = dot(eyeminusvertex, s.xyz);\n\
|
||||
eyevector.y = -dot(eyeminusvertex, t.xyz);\n\
|
||||
eyevector.z = dot(eyeminusvertex, n.xyz);\n\
|
||||
#endif\n\
|
||||
#if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\
|
||||
vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(w.xyz, 1.0));\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
"
|
||||
|
||||
/*this is full 4*4 PCF, with an added attempt at prenumbra*/
|
||||
/*the offset consts are 1/(imagesize*2) */
|
||||
#define PCF16P(f) "\
|
||||
float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\
|
||||
float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\
|
||||
float s = 0.0;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
colorscale *= s/5.0;\n\
|
||||
"
|
||||
|
||||
/*this is pcf 3*3*/
|
||||
/*the offset consts are 1/(imagesize*2) */
|
||||
#define PCF9(f) "\
|
||||
const float xPixelOffset = 1.0/texx;\
|
||||
const float yPixelOffset = 1.0/texy;\
|
||||
float s = 0.0;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
colorscale *= s/9.0;\n\
|
||||
"
|
||||
|
||||
/*this is a lazy form of pcf. take 5 samples in an x*/
|
||||
/*the offset consts are 1/(imagesize*2) */
|
||||
#define PCF5(f) "\
|
||||
float xPixelOffset = 1.0/texx;\
|
||||
float yPixelOffset = 1.0/texy;\
|
||||
float s = 0.0;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
|
||||
colorscale *= s/5.0;\n\
|
||||
"
|
||||
|
||||
/*this is unfiltered*/
|
||||
#define PCF1(f) "\
|
||||
colorscale *= "f"Proj(shadowmap, shadowcoord).r;\n"
|
||||
|
||||
#define LIGHTPASS_GLSL_FRAGMENT "\
|
||||
#ifdef FRAGMENT_SHADER\n\
|
||||
#include \"sys/fog.h\"\n\
|
||||
uniform sampler2D s_t0;\n"/*base texture*/"\
|
||||
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\
|
||||
uniform sampler2D s_t1;\n"/*normalmap/height texture*/"\
|
||||
#endif\n\
|
||||
#ifdef SPECULAR\n\
|
||||
uniform sampler2D s_t2;\n"/*specularmap texture*/"\
|
||||
#endif\n\
|
||||
#ifdef PROJECTION\n\
|
||||
uniform sampler2D s_t3;\n"/*projected texture*/"\
|
||||
#endif\n\
|
||||
#ifdef PCF\n\
|
||||
#ifdef CUBE\n\
|
||||
uniform samplerCubeShadow s_t7;\n\
|
||||
#else\n\
|
||||
uniform sampler2DShadow s_t7;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\
|
||||
\
|
||||
uniform float l_lightradius;\n\
|
||||
uniform vec3 l_lightcolour;\n\
|
||||
\
|
||||
#ifdef OFFSETMAPPING\n\
|
||||
uniform float offsetmapping_scale;\n\
|
||||
#endif\n\
|
||||
\
|
||||
\
|
||||
void main ()\n\
|
||||
{\n\
|
||||
#ifdef OFFSETMAPPING\n\
|
||||
vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\
|
||||
vec2 foo = tcbase;\n\
|
||||
#define tcbase foo\n\
|
||||
tcbase += OffsetVector;\n\
|
||||
OffsetVector *= 0.333;\n\
|
||||
tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
|
||||
tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
|
||||
tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
|
||||
#endif\n\
|
||||
\
|
||||
\
|
||||
#ifdef BUMP\n\
|
||||
vec3 bases = vec3(texture2D(s_t0, tcbase));\n\
|
||||
#else\n\
|
||||
vec3 diff = vec3(texture2D(s_t0, tcbase));\n\
|
||||
#endif\n\
|
||||
#if defined(BUMP) || defined(SPECULAR)\n\
|
||||
vec3 bumps = vec3(texture2D(s_t1, tcbase)) * 2.0 - 1.0;\n\
|
||||
#endif\n\
|
||||
#ifdef SPECULAR\n\
|
||||
vec3 specs = vec3(texture2D(s_t2, tcbase));\n\
|
||||
#endif\n\
|
||||
\
|
||||
vec3 nl = normalize(lightvector);\n\
|
||||
float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n\
|
||||
\
|
||||
#ifdef BUMP\n\
|
||||
vec3 diff;\n\
|
||||
diff = bases * max(dot(bumps, nl), 0.0);\n\
|
||||
#endif\n\
|
||||
#ifdef SPECULAR\n\
|
||||
vec3 halfdir = (normalize(eyevector) + normalize(lightvector))/2.0;\n\
|
||||
float dv = dot(halfdir, bumps);\n\
|
||||
diff += pow(dv, 8.0) * specs;\n\
|
||||
#endif\n\
|
||||
""\n\
|
||||
#ifdef PCF\n\
|
||||
#if defined(SPOT)\n\
|
||||
const float texx = 512.0;\n\
|
||||
const float texy = 512.0;\n\
|
||||
vec4 shadowcoord = vshadowcoord;\n\
|
||||
#else\n\
|
||||
const float texx = 512.0;\n\
|
||||
const float texy = 512.0;\n\
|
||||
vec4 shadowcoord;\n\
|
||||
shadowcoord.zw = vshadowcoord.zw;\n\
|
||||
shadowcoord.xy = vshadowcoord.xy;\n\
|
||||
#endif\n\
|
||||
#ifdef CUBE\n\
|
||||
"PCF9("shadowCube") /*valid are 1,5,9*/"\n\
|
||||
#else\n\
|
||||
"PCF9("shadow2D") /*valid are 1,5,9*/"\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
#if defined(SPOT)\n\
|
||||
/*Actually, this isn't correct*/\n\
|
||||
if (shadowcoord.w < 0.0) discard;\n\
|
||||
vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n\
|
||||
#endif\n\
|
||||
#if defined(PROJECTION)\n\
|
||||
l_lightcolour *= texture2d(s_t3, shadowcoord);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n\
|
||||
}\n\
|
||||
\
|
||||
#endif\n\
|
||||
"
|
||||
|
||||
char *defaultglsl2program =
|
||||
LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT
|
||||
;
|
||||
|
||||
#endif
|
||||
|
||||
static const char LIGHTPASS_SHADER[] = "\
|
||||
{\n\
|
||||
program rtlight%s\n\
|
||||
|
@ -258,6 +34,23 @@ static const char LIGHTPASS_SHADER[] = "\
|
|||
map $specular\n\
|
||||
}\n\
|
||||
}";
|
||||
static const char RTLIGHTCUBE_SHADER[] = "\
|
||||
{\n\
|
||||
program rtlight%s\n\
|
||||
{\n\
|
||||
map $diffuse\n\
|
||||
blendfunc add\n\
|
||||
}\n\
|
||||
{\n\
|
||||
map $normalmap\n\
|
||||
}\n\
|
||||
{\n\
|
||||
map $specular\n\
|
||||
}\n\
|
||||
{\n\
|
||||
map $lightcubemap\n\
|
||||
}\n\
|
||||
}";
|
||||
static const char PCFPASS_SHADER[] = "\
|
||||
{\n\
|
||||
program rtlight#PCF%s\n"/*\
|
||||
|
@ -268,9 +61,6 @@ static const char PCFPASS_SHADER[] = "\
|
|||
#define PCF\n\
|
||||
%s%s\n\
|
||||
}\n*/"\
|
||||
\
|
||||
/*eye pos*/\n\
|
||||
param opt entmatrix entmatrix\n\
|
||||
\
|
||||
{\n\
|
||||
map $diffuse\n\
|
||||
|
@ -302,12 +92,14 @@ struct {
|
|||
int vbo_texcoords[SHADER_PASS_MAX];
|
||||
int vbo_deforms; //holds verticies... in case you didn't realise.
|
||||
|
||||
qboolean initedlightpasses;
|
||||
const shader_t *lightpassshader;
|
||||
qboolean initedpcfpasses;
|
||||
const shader_t *pcfpassshader;
|
||||
qboolean initedspotpasses;
|
||||
const shader_t *spotpassshader;
|
||||
qboolean inited_shader_rtlight;
|
||||
const shader_t *shader_rtlight;
|
||||
qboolean inited_shader_cube;
|
||||
const shader_t *shader_cube;
|
||||
qboolean inited_shader_smap;
|
||||
const shader_t *shader_smap;
|
||||
qboolean inited_shader_spot;
|
||||
const shader_t *shader_spot;
|
||||
|
||||
const shader_t *crepskyshader;
|
||||
const shader_t *crepopaqueshader;
|
||||
|
@ -377,6 +169,8 @@ struct {
|
|||
vec3_t lightcolours;
|
||||
float lightradius;
|
||||
texid_t lighttexture;
|
||||
texid_t lightcubemap;
|
||||
float lightprojmatrix[16]; /*world space*/
|
||||
};
|
||||
|
||||
int wbatch;
|
||||
|
@ -936,6 +730,9 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea
|
|||
t = shaderstate.curshadowmap;
|
||||
break;
|
||||
|
||||
case T_GEN_LIGHTCUBEMAP:
|
||||
GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, shaderstate.lightcubemap, useclientarray);
|
||||
return;
|
||||
case T_GEN_CUBEMAP:
|
||||
t = pass->anim_frames[0];
|
||||
GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray);
|
||||
|
@ -1047,7 +844,12 @@ void Shader_LightPass_Std(char *shortname, shader_t *s, const void *args)
|
|||
{
|
||||
char shadertext[8192*2];
|
||||
sprintf(shadertext, LIGHTPASS_SHADER, "");
|
||||
// FS_WriteFile("shader/lightpass.shader.builtin", shadertext, strlen(shadertext), FS_GAMEONLY);
|
||||
Shader_DefaultScript(shortname, s, shadertext);
|
||||
}
|
||||
void Shader_LightPass_Cube(char *shortname, shader_t *s, const void *args)
|
||||
{
|
||||
char shadertext[8192*2];
|
||||
sprintf(shadertext, RTLIGHTCUBE_SHADER, "#CUBE");
|
||||
Shader_DefaultScript(shortname, s, shadertext);
|
||||
}
|
||||
void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args)
|
||||
|
@ -1131,10 +933,15 @@ void GLBE_Init(void)
|
|||
shaderstate.identitylighting = 1;
|
||||
|
||||
/*normally we load these lazily, but if they're probably going to be used anyway, load them now to avoid stalls.*/
|
||||
if (r_shadow_realtime_dlight.ival && !shaderstate.initedlightpasses && gl_config.arb_shader_objects)
|
||||
if (r_shadow_realtime_dlight.ival && !shaderstate.inited_shader_rtlight && gl_config.arb_shader_objects)
|
||||
{
|
||||
shaderstate.initedlightpasses = true;
|
||||
shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL);
|
||||
shaderstate.inited_shader_rtlight = true;
|
||||
shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL);
|
||||
}
|
||||
if (r_shadow_realtime_dlight.ival && !shaderstate.inited_shader_cube && gl_config.arb_shader_objects)
|
||||
{
|
||||
shaderstate.inited_shader_cube = true;
|
||||
shaderstate.shader_cube = R_RegisterCustom("rtlight_sube", Shader_LightPass_Cube, NULL);
|
||||
}
|
||||
|
||||
shaderstate.shaderbits = ~0;
|
||||
|
@ -2613,6 +2420,16 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned
|
|||
qglUniform3fvARB(p->handle[perm], 1, t2);
|
||||
}
|
||||
break;
|
||||
case SP_LIGHTPROJMATRIX:
|
||||
/*light's texture projection matrix*/
|
||||
{
|
||||
float t[16];
|
||||
Matrix4_Multiply(shaderstate.lightprojmatrix, shaderstate.modelmatrix, t);
|
||||
qglUniformMatrix4fvARB(p->handle[perm], 1, false, t);
|
||||
}
|
||||
break;
|
||||
|
||||
/*static lighting info*/
|
||||
case SP_E_L_DIR:
|
||||
qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_dir);
|
||||
break;
|
||||
|
@ -2833,26 +2650,31 @@ void GLBE_SelectMode(backendmode_t mode)
|
|||
break;
|
||||
|
||||
case BEM_SMAPLIGHT:
|
||||
if (!shaderstate.initedpcfpasses)
|
||||
if (!shaderstate.inited_shader_smap)
|
||||
{
|
||||
shaderstate.initedpcfpasses = true;
|
||||
shaderstate.pcfpassshader = R_RegisterCustom("lightpass_pcf", Shader_LightPass_PCF, NULL);
|
||||
shaderstate.inited_shader_smap = true;
|
||||
shaderstate.shader_smap = R_RegisterCustom("rtlight_shadowmap", Shader_LightPass_PCF, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case BEM_SMAPLIGHTSPOT:
|
||||
if (!shaderstate.initedspotpasses)
|
||||
if (!shaderstate.inited_shader_spot)
|
||||
{
|
||||
shaderstate.initedspotpasses = true;
|
||||
shaderstate.spotpassshader = R_RegisterCustom("lightpass_spot", Shader_LightPass_Spot, NULL);
|
||||
shaderstate.inited_shader_spot = true;
|
||||
shaderstate.shader_spot = R_RegisterCustom("rtlight_spot", Shader_LightPass_Spot, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case BEM_LIGHT:
|
||||
if (!shaderstate.initedlightpasses)
|
||||
if (!shaderstate.inited_shader_rtlight)
|
||||
{
|
||||
shaderstate.initedlightpasses = true;
|
||||
shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL);
|
||||
shaderstate.inited_shader_rtlight = true;
|
||||
shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL);
|
||||
}
|
||||
if (!shaderstate.inited_shader_cube)
|
||||
{
|
||||
shaderstate.inited_shader_cube = true;
|
||||
shaderstate.shader_cube = R_RegisterCustom("rtlight_sube", Shader_LightPass_Cube, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2927,12 +2749,36 @@ void BE_SelectFog(vec3_t colour, float alpha, float density)
|
|||
|
||||
void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
|
||||
{
|
||||
static float shadowprojectionbias[16] =
|
||||
{
|
||||
0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.4993f, 1.0f
|
||||
};
|
||||
float view[16], proj[16], t[16];
|
||||
|
||||
/*generate light projection information*/
|
||||
float nearplane = 4;
|
||||
if (dl->fov)
|
||||
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, nearplane, dl->radius);
|
||||
else
|
||||
Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, dl->radius);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(view, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
|
||||
Matrix4_Multiply(shadowprojectionbias, proj, t);
|
||||
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
|
||||
|
||||
|
||||
/*simple info*/
|
||||
shaderstate.lightradius = dl->radius;
|
||||
VectorCopy(dl->origin, shaderstate.lightorg);
|
||||
VectorCopy(colour, shaderstate.lightcolours);
|
||||
#ifdef RTLIGHTS
|
||||
shaderstate.curshadowmap = dl->stexture;
|
||||
#endif
|
||||
#ifdef RTLIGHTS
|
||||
shaderstate.lightcubemap = dl->cubetexture;
|
||||
#endif
|
||||
}
|
||||
|
||||
void BE_PushOffsetShadow(qboolean pushdepth)
|
||||
|
@ -3035,13 +2881,16 @@ static void DrawMeshes(void)
|
|||
break;
|
||||
#ifdef RTLIGHTS
|
||||
case BEM_SMAPLIGHTSPOT:
|
||||
BE_RenderMeshProgram(shaderstate.spotpassshader, shaderstate.spotpassshader->passes);
|
||||
BE_RenderMeshProgram(shaderstate.shader_spot, shaderstate.shader_spot->passes);
|
||||
break;
|
||||
case BEM_SMAPLIGHT:
|
||||
BE_RenderMeshProgram(shaderstate.pcfpassshader, shaderstate.pcfpassshader->passes);
|
||||
BE_RenderMeshProgram(shaderstate.shader_smap, shaderstate.shader_smap->passes);
|
||||
break;
|
||||
case BEM_LIGHT:
|
||||
BE_RenderMeshProgram(shaderstate.lightpassshader, shaderstate.lightpassshader->passes);
|
||||
if (TEXVALID(shaderstate.lightcubemap))
|
||||
BE_RenderMeshProgram(shaderstate.shader_cube, shaderstate.shader_cube->passes);
|
||||
else
|
||||
BE_RenderMeshProgram(shaderstate.shader_rtlight, shaderstate.shader_rtlight->passes);
|
||||
break;
|
||||
case BEM_DEPTHNORM:
|
||||
BE_RenderMeshProgram(shaderstate.depthnormshader, shaderstate.depthnormshader->passes);
|
||||
|
|
|
@ -1052,7 +1052,7 @@ void GL_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
|
|||
*scaled_height = 1;
|
||||
}
|
||||
|
||||
void GL_8888to565(unsigned char *in, unsigned short *out, unsigned int mip, unsigned int w, unsigned int h)
|
||||
void GL_8888to565(int targ, unsigned char *in, unsigned short *out, unsigned int mip, unsigned int w, unsigned int h)
|
||||
{
|
||||
unsigned int p = w*h;
|
||||
unsigned short tmp;
|
||||
|
@ -1066,10 +1066,10 @@ void GL_8888to565(unsigned char *in, unsigned short *out, unsigned int mip, unsi
|
|||
in++;
|
||||
*out++ = tmp;
|
||||
}
|
||||
qglTexImage2D (GL_TEXTURE_2D, mip, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, iout);
|
||||
qglTexImage2D (targ, mip, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, iout);
|
||||
}
|
||||
|
||||
void GL_8888to4444(unsigned char *in, unsigned short *out, unsigned int mip, unsigned int w, unsigned int h)
|
||||
void GL_8888to4444(int targ, unsigned char *in, unsigned short *out, unsigned int mip, unsigned int w, unsigned int h)
|
||||
{
|
||||
unsigned int p = w*h;
|
||||
unsigned short tmp;
|
||||
|
@ -1083,7 +1083,7 @@ void GL_8888to4444(unsigned char *in, unsigned short *out, unsigned int mip, uns
|
|||
tmp |= ((*in++>>4) << 0);
|
||||
*out++ = tmp;
|
||||
}
|
||||
qglTexImage2D (GL_TEXTURE_2D, mip, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, iout);
|
||||
qglTexImage2D (targ, mip, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, iout);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1098,6 +1098,7 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
unsigned *scaled = (unsigned *)uploadmemorybuffer;
|
||||
int scaled_width, scaled_height;
|
||||
int type;
|
||||
int targ;
|
||||
|
||||
TRACE(("dbg: GL_Upload32: %s %i %i\n", name, width, height));
|
||||
|
||||
|
@ -1118,6 +1119,19 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
}
|
||||
}
|
||||
}
|
||||
switch((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT)
|
||||
{
|
||||
case 0:
|
||||
targ = GL_TEXTURE_2D;
|
||||
break;
|
||||
case 1:
|
||||
targ = GL_TEXTURE_3D;
|
||||
break;
|
||||
default:
|
||||
targ = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + (((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT) - 2);
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("dbg: GL_Upload32: %i %i\n", scaled_width, scaled_height));
|
||||
|
||||
if (scaled_width * scaled_height > sizeofuploadmemorybuffer/4)
|
||||
|
@ -1153,7 +1167,22 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
if (gl_config.arb_texture_compression && gl_compress.value && name && !(flags&IF_NOMIPMAP))
|
||||
samples = (flags&IF_NOALPHA) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB;
|
||||
|
||||
if (flags & IF_3DMAP)
|
||||
if (flags&IF_CLAMP)
|
||||
{
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
if (targ != GL_TEXTURE_2D)
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
if (targ != GL_TEXTURE_2D)
|
||||
qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (targ == GL_TEXTURE_3D)
|
||||
{
|
||||
int r,d;
|
||||
if (scaled_height * scaled_height != scaled_width)
|
||||
|
@ -1165,19 +1194,6 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
else
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
if (flags&IF_CLAMP)
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
}
|
||||
|
||||
for (d = 0; d < scaled_height; d++)
|
||||
{
|
||||
/*each 'layer' is sequential, which means we need to de-interlace the layers*/
|
||||
|
@ -1193,35 +1209,24 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
if (gl_config.sgis_generate_mipmap && !(flags&IF_NOMIPMAP))
|
||||
{
|
||||
TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n"));
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
qglTexParameteri(targ, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
}
|
||||
|
||||
if (!(flags&IF_NOMIPMAP))
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
if (flags & IF_NEAREST)
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
else
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
|
||||
if (flags & IF_NEAREST)
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
else
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
|
||||
}
|
||||
|
||||
if (flags&IF_CLAMP)
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
|
||||
}
|
||||
|
||||
if (scaled_width == width && scaled_height == height)
|
||||
|
@ -1230,11 +1235,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
{
|
||||
TRACE(("dbg: GL_Upload32: non-mipmapped/unscaled\n"));
|
||||
if (type == GL_UNSIGNED_SHORT_5_6_5)
|
||||
GL_8888to565((unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
|
||||
GL_8888to565(targ, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
|
||||
else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
|
||||
GL_8888to4444((unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
|
||||
GL_8888to4444(targ, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
|
||||
else
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data);
|
||||
qglTexImage2D (targ, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data);
|
||||
goto done;
|
||||
}
|
||||
memcpy (scaled, data, width*height*4);
|
||||
|
@ -1244,11 +1249,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
|
||||
TRACE(("dbg: GL_Upload32: recaled\n"));
|
||||
if (type == GL_UNSIGNED_SHORT_5_6_5)
|
||||
GL_8888to565((unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
|
||||
GL_8888to565(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
|
||||
else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
|
||||
GL_8888to4444((unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
|
||||
GL_8888to4444(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
|
||||
else
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
|
||||
qglTexImage2D (targ, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
|
||||
if (!(flags&IF_NOMIPMAP) && !gl_config.sgis_generate_mipmap)
|
||||
{
|
||||
miplevel = 0;
|
||||
|
@ -1264,15 +1269,15 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
scaled_height = 1;
|
||||
miplevel++;
|
||||
if (type == GL_UNSIGNED_SHORT_5_6_5)
|
||||
GL_8888to565((unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
|
||||
GL_8888to565(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
|
||||
else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
|
||||
GL_8888to4444((unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
|
||||
GL_8888to4444(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
|
||||
else
|
||||
qglTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
|
||||
qglTexImage2D (targ, miplevel, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
|
||||
}
|
||||
}
|
||||
|
||||
if (gl_config.arb_texture_compression && gl_compress.value && gl_savecompressedtex.value && name && !(flags&IF_NOMIPMAP))
|
||||
if (targ == GL_TEXTURE_2D && gl_config.arb_texture_compression && gl_compress.value && gl_savecompressedtex.value && name && !(flags&IF_NOMIPMAP))
|
||||
{
|
||||
vfsfile_t *out;
|
||||
int miplevels;
|
||||
|
@ -1330,7 +1335,7 @@ done:
|
|||
qglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy_factor); // without this, you could loose anisotropy on mapchange
|
||||
|
||||
if (gl_config.sgis_generate_mipmap && !(flags&IF_NOMIPMAP))
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
||||
qglTexParameteri(targ, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
||||
}
|
||||
|
||||
void GL_Upload32 (char *name, unsigned *data, int width, int height, unsigned int flags)
|
||||
|
@ -2214,24 +2219,32 @@ texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, u
|
|||
{
|
||||
// qboolean noalpha;
|
||||
// int p, s;
|
||||
gltexture_t *glt;
|
||||
gltexture_t *glt = NULL;
|
||||
|
||||
// see if the texture is already present
|
||||
if (identifier[0])
|
||||
{
|
||||
glt = GL_MatchTexture(identifier, 32, width, height);
|
||||
if (glt)
|
||||
if (glt && !(flags & IF_REPLACE))
|
||||
return glt->texnum;
|
||||
}
|
||||
|
||||
glt = GL_AllocNewGLTexture(identifier, width, height);
|
||||
if (!glt)
|
||||
glt = GL_AllocNewGLTexture(identifier, width, height);
|
||||
glt->bpp = 32;
|
||||
glt->flags = flags;
|
||||
|
||||
if (flags & IF_3DMAP)
|
||||
GL_MTBind(0, GL_TEXTURE_3D, glt->texnum);
|
||||
else
|
||||
switch((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT)
|
||||
{
|
||||
case 0:
|
||||
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
|
||||
break;
|
||||
case 1:
|
||||
GL_MTBind(0, GL_TEXTURE_3D, glt->texnum);
|
||||
break;
|
||||
default:
|
||||
GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, glt->texnum);
|
||||
break;
|
||||
}
|
||||
|
||||
GL_Upload32 (identifier, data, width, height, flags);
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ void R_InitFlashblends(void)
|
|||
lpplight_shader = NULL;
|
||||
}
|
||||
|
||||
static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand)
|
||||
static qboolean R_BuildDlightMesh(dlight_t *light, float colscale, float radscale, qboolean expand)
|
||||
{
|
||||
int i, j;
|
||||
// float a;
|
||||
|
@ -225,6 +225,10 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa
|
|||
rad *= a;
|
||||
rad *= 0.33;
|
||||
}
|
||||
if (light->style)
|
||||
{
|
||||
colscale *= d_lightstylevalue[light->style-1]/255.0f;
|
||||
}
|
||||
|
||||
VectorSubtract (light->origin, r_origin, v);
|
||||
if (Length (v) < rad + gl_mindist.value*2)
|
||||
|
@ -232,9 +236,9 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa
|
|||
return false;
|
||||
}
|
||||
|
||||
flashblend_colours[0][0] = colour[0]*2;
|
||||
flashblend_colours[0][1] = colour[1]*2;
|
||||
flashblend_colours[0][2] = colour[2]*2;
|
||||
flashblend_colours[0][0] = colour[0]*colscale;
|
||||
flashblend_colours[0][1] = colour[1]*colscale;
|
||||
flashblend_colours[0][2] = colour[2]*colscale;
|
||||
flashblend_colours[0][3] = 1;
|
||||
|
||||
VectorCopy(light->origin, flashblend_vcoords[0]);
|
||||
|
@ -289,21 +293,27 @@ void R_RenderDlights (void)
|
|||
l = cl_dlights+rtlights_first;
|
||||
for (i=rtlights_first; i<rtlights_max; i++, l++)
|
||||
{
|
||||
if (!l->radius || !(l->flags & LFLAG_FLASHBLEND))
|
||||
if (!l->radius)
|
||||
continue;
|
||||
|
||||
//dlights emitting from the local player are not visible as flashblends
|
||||
if (l->key == cl.playernum[r_refdef.currentplayernum]+1)
|
||||
continue; //was a glow
|
||||
if (l->key == -(cl.playernum[r_refdef.currentplayernum]+1))
|
||||
continue; //was a muzzleflash
|
||||
if (l->corona <= 0)
|
||||
continue;
|
||||
|
||||
if (l->flags & LFLAG_FLASHBLEND)
|
||||
{
|
||||
//dlights emitting from the local player are not visible as flashblends
|
||||
if (l->key == cl.playernum[r_refdef.currentplayernum]+1)
|
||||
continue; //was a glow
|
||||
if (l->key == -(cl.playernum[r_refdef.currentplayernum]+1))
|
||||
continue; //was a muzzleflash
|
||||
}
|
||||
|
||||
if (r_flashblend.ival == 2)
|
||||
{
|
||||
if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2))
|
||||
continue;
|
||||
}
|
||||
if (!R_BuildDlightMesh (l, r_flashblendscale.value, false))
|
||||
if (!R_BuildDlightMesh (l, l->corona, l->coronascale, false))
|
||||
AddLightBlend (l->color[0]*5, l->color[1]*5, l->color[2]*5, l->radius * 0.0003);
|
||||
else
|
||||
BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, beflags);
|
||||
|
@ -318,7 +328,7 @@ void R_GenDlightMesh(struct batch_s *batch)
|
|||
|
||||
BE_SelectDLight(l, l->color);
|
||||
|
||||
if (!R_BuildDlightMesh (l, 1, true))
|
||||
if (!R_BuildDlightMesh (l, 2, 1, true))
|
||||
{
|
||||
int i;
|
||||
static vec2_t s[4] = {{1, -1}, {-1, -1}, {-1, 1}, {1, 1}};
|
||||
|
|
|
@ -907,7 +907,7 @@ static void R_SaveRTLights_f(void)
|
|||
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
|
||||
light->radius, light->color[0], light->color[1], light->color[2],
|
||||
light->style-1,
|
||||
"", light->corona,
|
||||
light->cubemapname, light->corona,
|
||||
ang[0], ang[1], ang[2],
|
||||
light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE|LFLAG_CREPUSCULAR)
|
||||
));
|
||||
|
|
|
@ -804,8 +804,9 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
|
|||
"#define FOG\n",
|
||||
NULL
|
||||
};
|
||||
char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0])];
|
||||
char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0]) + 64];
|
||||
unsigned int nopermutation = ~0u;
|
||||
int nummodifiers;
|
||||
int p, n, pn;
|
||||
char *end;
|
||||
|
||||
|
@ -882,6 +883,24 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
|
|||
};
|
||||
|
||||
memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS);
|
||||
|
||||
nummodifiers = 0;
|
||||
for (end = strchr(name, '#'); end && *end; )
|
||||
{
|
||||
char *start = end+1;
|
||||
end = strchr(start, '#');
|
||||
if (!end)
|
||||
end = start + strlen(start);
|
||||
permutationdefines[nummodifiers] = malloc(10 + end - start);
|
||||
memcpy(permutationdefines[nummodifiers], "#define ", 8);
|
||||
memcpy(permutationdefines[nummodifiers]+8, start, end - start);
|
||||
memcpy(permutationdefines[nummodifiers]+8+(end-start), "\n", 2);
|
||||
|
||||
for (start = permutationdefines[nummodifiers]+8; *start; start++)
|
||||
*start = toupper(*start);
|
||||
|
||||
nummodifiers++;
|
||||
}
|
||||
for (p = 0; p < PERMUTATIONS; p++)
|
||||
{
|
||||
if (qrenderer != qrtype)
|
||||
|
@ -894,7 +913,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
|
|||
{
|
||||
continue;
|
||||
}
|
||||
pn = 0;
|
||||
pn = nummodifiers;
|
||||
for (n = 0; permutationname[n]; n++)
|
||||
{
|
||||
if (p & (1u<<n))
|
||||
|
@ -911,7 +930,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
|
|||
{
|
||||
continue;
|
||||
}
|
||||
pn = 0;
|
||||
pn = nummodifiers;
|
||||
for (n = 0; permutationname[n]; n++)
|
||||
{
|
||||
if (p & (1u<<n))
|
||||
|
@ -922,6 +941,8 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
|
|||
}
|
||||
#endif
|
||||
}
|
||||
while(nummodifiers)
|
||||
free(permutationdefines[--nummodifiers]);
|
||||
|
||||
Shader_ProgAutoFields(prog, cvarnames, cvartypes);
|
||||
}
|
||||
|
@ -1864,6 +1885,7 @@ struct sbuiltin_s
|
|||
s0=diffuse, s1=normal, s2=specular, s3=shadowmap
|
||||
custom modifiers:
|
||||
PCF(shadowmap)
|
||||
CUBE(projected cubemap)
|
||||
*/
|
||||
"!!permu BUMP\n"
|
||||
"!!permu SPECULAR\n"
|
||||
|
@ -1877,9 +1899,9 @@ struct sbuiltin_s
|
|||
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
|
||||
"varying vec3 eyevector;\n"
|
||||
"#endif\n"
|
||||
"#ifdef PCF\n"
|
||||
"#if defined(PCF) || defined(CUBE)\n"
|
||||
"varying vec4 vshadowcoord;\n"
|
||||
"uniform mat4 entmatrix;\n"
|
||||
"uniform mat4 l_projmatrix;\n"
|
||||
"#endif\n"
|
||||
|
||||
"#ifdef VERTEX_SHADER\n"
|
||||
|
@ -1910,8 +1932,8 @@ struct sbuiltin_s
|
|||
"eyevector.y = -dot(eyeminusvertex, t.xyz);\n"
|
||||
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
|
||||
"#endif\n"
|
||||
"#if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n"
|
||||
"vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(w.xyz, 1.0));\n"
|
||||
"#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE)\n"
|
||||
"vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0);\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
|
@ -1992,8 +2014,8 @@ struct sbuiltin_s
|
|||
"#ifdef SPECULAR\n"
|
||||
"uniform sampler2D s_t2;\n"/*specularmap texture*/
|
||||
"#endif\n"
|
||||
"#ifdef PROJECTION\n"
|
||||
"uniform sampler2D s_t3;\n"/*projected texture*/
|
||||
"#ifdef CUBE\n"
|
||||
"uniform samplerCube s_t3;\n"/*projected texture*/
|
||||
"#endif\n"
|
||||
"#ifdef PCF\n"
|
||||
"#ifdef CUBE\n"
|
||||
|
@ -2050,6 +2072,10 @@ struct sbuiltin_s
|
|||
"diff += pow(dv, 8.0) * specs;\n"
|
||||
"#endif\n"
|
||||
|
||||
"#ifdef CUBE\n"
|
||||
"diff *= textureCube(s_t3, vshadowcoord.xyz).rgb;\n"
|
||||
"#endif\n"
|
||||
|
||||
"#ifdef PCF\n"
|
||||
"#if defined(SPOT)\n"
|
||||
"const float texx = 512.0;\n"
|
||||
|
@ -2395,6 +2421,7 @@ struct shader_field_names_s shader_field_names[] =
|
|||
{"l_lightradius", SP_LIGHTRADIUS},
|
||||
{"l_lightcolour", SP_LIGHTCOLOUR},
|
||||
{"l_lightposition", SP_LIGHTPOSITION},
|
||||
{"l_projmatrix", SP_LIGHTPROJMATRIX},
|
||||
|
||||
{"e_rendertexturescale", SP_RENDERTEXTURESCALE},
|
||||
{NULL}
|
||||
|
@ -2898,6 +2925,11 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
|
|||
pass->texgen = T_GEN_SHADOWMAP;
|
||||
pass->tcgen = TC_GEN_BASE; //FIXME: moo!
|
||||
}
|
||||
else if (!Q_stricmp (tname, "$lightcubemap"))
|
||||
{
|
||||
pass->texgen = T_GEN_LIGHTCUBEMAP;
|
||||
pass->tcgen = TC_GEN_BASE; //FIXME: moo!
|
||||
}
|
||||
else if (!Q_stricmp (tname, "$currentrender"))
|
||||
{
|
||||
pass->texgen = T_GEN_CURRENTRENDER;
|
||||
|
|
|
@ -294,6 +294,8 @@ static const char *gl_extensions;
|
|||
|
||||
static unsigned int gl_num_extensions;
|
||||
|
||||
extern cvar_t gl_workaround_ati_shadersource;
|
||||
|
||||
|
||||
qboolean GL_CheckExtension(char *extname)
|
||||
{
|
||||
|
@ -963,8 +965,13 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan
|
|||
|
||||
shader = qglCreateShaderObjectARB(shadertype);
|
||||
|
||||
if (1)//gl_workaround_ati_shadersource.ival)
|
||||
if (gl_workaround_ati_shadersource.ival)
|
||||
{
|
||||
/*ATI Driver Bug: ATI drivers ignore the 'length' array.
|
||||
this code does what the drivers fail to do.
|
||||
this patch makes the submission more mainstream
|
||||
if ati can feck it up so much on a system with no real system memory issues, I wouldn't be surprised if embedded systems also mess it up.
|
||||
*/
|
||||
char *combined;
|
||||
int totallen = 1;
|
||||
for (i = 0; i < strings; i++)
|
||||
|
|
|
@ -210,6 +210,7 @@ typedef struct shaderpass_s {
|
|||
T_GEN_LIGHTMAP, //world light samples
|
||||
T_GEN_DELUXMAP, //world light directions
|
||||
T_GEN_SHADOWMAP, //light's depth values.
|
||||
T_GEN_LIGHTCUBEMAP, //light's projected cubemap
|
||||
|
||||
T_GEN_DIFFUSE, //texture's default diffuse texture
|
||||
T_GEN_NORMALMAP, //texture's default normalmap
|
||||
|
@ -311,6 +312,7 @@ typedef struct {
|
|||
SP_LIGHTCOLOUR,
|
||||
SP_LIGHTPOSITION,
|
||||
SP_LIGHTSCREEN,
|
||||
SP_LIGHTPROJMATRIX,
|
||||
|
||||
//things that are set immediatly
|
||||
SP_FIRSTIMMEDIATE, //never set
|
||||
|
|
|
@ -8781,8 +8781,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"globalstat", PF_globalstat, 0, 0, 0, 233, "void(float num, float type, string name)"}, //EXT_CSQC_1 actually
|
||||
//END EXT_CSQC
|
||||
{"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234, "void(entity player)"},
|
||||
{"rotatevectorsbyangle", PF_Fixme, 0, 0, 0, 235, "void(vector angle)"}, // #235
|
||||
{"rotatevectorsbyvectors", PF_Fixme, 0, 0, 0, 236, "void(vector fwd, vector right, vector up)"}, // #236
|
||||
{"rotatevectorsbyangle",PF_rotatevectorsbyangles,0,0, 0, 235, "void(vector angle)"}, // #235
|
||||
{"rotatevectorsbyvectors",PF_rotatevectorsbymatrix,0,0, 0, 236, "void(vector fwd, vector right, vector up)"}, // #236
|
||||
{"skinforname", PF_skinforname, 0, 0, 0, 237, "float(float mdlindex, string skinname)"}, // #237
|
||||
{"shaderforname", PF_Fixme, 0, 0, 0, 238, "float(string shadername, optional string defaultshader, ...)"},
|
||||
{"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239, "void(vector org, optional float count)"},
|
||||
|
@ -9864,6 +9864,9 @@ void PR_DumpPlatform_f(void)
|
|||
{"LFIELD_STYLE", "const float", CS, lfield_style},
|
||||
{"LFIELD_ANGLES", "const float", CS, lfield_angles},
|
||||
{"LFIELD_FOV", "const float", CS, lfield_fov},
|
||||
{"LFIELD_CORONA", "const float", CS, lfield_corona},
|
||||
{"LFIELD_CORONASCALE", "const float", CS, lfield_coronascale},
|
||||
{"LFIELD_CUBEMAPNAME", "const float", CS, lfield_cubemapname},
|
||||
|
||||
{"LFLAG_NORMALMODE", "const float", CS, LFLAG_NORMALMODE},
|
||||
{"LFLAG_REALTIMEMODE", "const float", CS, LFLAG_REALTIMEMODE},
|
||||
|
|
Loading…
Reference in a new issue