From f32a88f684e5a73f1ce73883c07f827c64a2ac42 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 27 Dec 2011 08:35:19 +0000 Subject: [PATCH] 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 --- engine/client/cl_cg.c | 2 +- engine/client/cl_ents.c | 79 ++++----- engine/client/cl_tent.c | 77 +++++---- engine/client/cl_ui.c | 2 +- engine/client/clhl_game.c | 2 +- engine/client/client.h | 2 +- engine/client/clq2_ents.c | 2 +- engine/client/image.c | 57 ++++++- engine/client/p_script.c | 2 +- engine/client/pr_csqc.c | 39 +---- engine/client/r_surf.c | 8 +- engine/client/render.h | 8 +- engine/client/renderer.c | 2 + engine/common/fs_stdio.c | 27 ++- engine/common/pr_bgcmd.c | 42 +++++ engine/common/pr_common.h | 2 + engine/gl/gl_backend.c | 347 +++++++++++--------------------------- engine/gl/gl_draw.c | 121 +++++++------ engine/gl/gl_rlight.c | 34 ++-- engine/gl/gl_rmisc.c | 2 +- engine/gl/gl_shader.c | 50 +++++- engine/gl/gl_vidcommon.c | 9 +- engine/gl/shader.h | 2 + engine/server/pr_cmds.c | 7 +- 24 files changed, 458 insertions(+), 467 deletions(-) diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 78199549a..db9fcb044 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -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 diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 0631c3201..a522d78f8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -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; diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 4ec9c1fa8..f4b65158e 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -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 diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 1807bd771..236871728 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -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]); diff --git a/engine/client/clhl_game.c b/engine/client/clhl_game.c index bfdc7525f..aed20444e 100644 --- a/engine/client/clhl_game.c +++ b/engine/client/clhl_game.c @@ -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); diff --git a/engine/client/client.h b/engine/client/client.h index b75aaad53..0a23ecdc4 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -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); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index b51beee6c..f664f12ac 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -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! diff --git a/engine/client/image.c b/engine/client/image.c index fad9a3c9d..46078cf5a 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -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) { diff --git a/engine/client/p_script.c b/engine/client/p_script.c index ae6bd5d49..78ee7f2c2 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -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]; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 7781b2e79..570b13d04 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -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); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 9c3102282..e78c607d3 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -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 ; ttexturemins[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. { diff --git a/engine/client/render.h b/engine/client/render.h index 60f1edce5..77f7582ba 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -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 }; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index fb6440473..b177b2ea5 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -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); diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index 22a4ee7b7..141baeecb 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -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; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index f010aa3bb..292d5d223 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -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 diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 997d92d4f..04b4bd7c4 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -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); diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 84c0eea54..4a5ea9d0a 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -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); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 1b529037f..a46322092 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -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); diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index a2798bfd4..7d3a1685e 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -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; iradius || !(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}}; diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index bb6c240dc..61790585b 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -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) )); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 1bcd8ac0d..cbf5fdc5b 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -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<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; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index b6f165b07..9320f2494 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -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++) diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 63df29030..e1664e94a 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -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 diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index dd1a2370f..28b9e4459 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -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},