First attempt at hl2 lightcube stuff.

This commit is contained in:
Shpoike 2021-05-19 04:40:38 +01:00
parent 483b25be2c
commit 86e427126c
23 changed files with 337 additions and 91 deletions

View File

@ -3439,14 +3439,14 @@ void CL_LinkStaticEntities(void *pvs, int *areas)
Mod_LoadModel(src->model, MLV_WARN); //we use threads, so these'll load in time.
continue;
}
if (!src->light_known)
/*if (!src->light_known)
{
vec3_t tmp;
VectorCopy(src->origin, tmp);
VectorCopy(sent->lightorg, src->origin);
R_CalcModelLighting(src, src->model); //bake and cache, now everything else is working.
VectorCopy(tmp, src->origin);
}
}*/
if (src->pvscache.num_leafs==-2)
{
vec3_t absmin, absmax;
@ -4072,7 +4072,7 @@ void CL_LinkPacketEntities (void)
#ifdef HEXEN2
ent->h2playerclass = 0;
#endif
ent->light_known = 0;
ent->light_type = ELT_UNKNOWN;
ent->forcedshader = NULL;
ent->shaderTime = 0;

View File

@ -2062,7 +2062,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
ent.shaderRGBAf[1] = 0;
ent.shaderRGBAf[2] = 0;
//bypasses world lighting
ent.light_known = true;
ent.light_type = ELT_LAMBERT;
VectorSet(ent.light_avg, 1, 1, 1);
VectorSet(ent.light_range, 0, 0, 0);
//(yes, its a bit shit. not even a post-process thing)
@ -2070,7 +2070,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
// add to refresh list
V_AddEntity (&ent);
ent.light_known = false;
ent.light_type = ELT_UNKNOWN;
ent.customskin = 0;

View File

@ -2808,7 +2808,7 @@ static void Con_DrawModelPreview(model_t *model, float x, float y, float w, floa
ent.light_dir[1] = DotProduct(lightpos, ent.axis[1]);
ent.light_dir[2] = DotProduct(lightpos, ent.axis[2]);
ent.light_known = 2;
ent.light_type = ELT_FLAT;
V_AddEntity(&ent);

View File

@ -3535,7 +3535,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
ent.light_dir[1] = DotProduct(lightpos, ent.axis[1]);
ent.light_dir[2] = DotProduct(lightpos, ent.axis[2]);
ent.light_known = 2;
ent.light_type = ELT_FLAT;
if (ent.model->type == mod_dummy)
{

View File

@ -5437,13 +5437,13 @@ static void QCBUILTIN PF_cs_droptofloor (pubprogfuncs_t *prinst, struct globalva
static void QCBUILTIN PF_cl_getlight (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
vec3_t ambient, diffuse, dir;
vec3_t ambient, diffuse, dir, cube[6];
if (csqc_world.worldmodel->lightmaps.maxstyle >= cl_max_lightstyles || !csqc_world.worldmodel || csqc_world.worldmodel->loadstate != MLS_LOADED || !csqc_world.worldmodel->funcs.LightPointValues)
VectorSet(G_VECTOR(OFS_RETURN), 0, 0, 0);
else
{
csqc_world.worldmodel->funcs.LightPointValues(csqc_world.worldmodel, G_VECTOR(OFS_PARM0), ambient, diffuse, dir);
csqc_world.worldmodel->funcs.LightPointValues(csqc_world.worldmodel, G_VECTOR(OFS_PARM0), ambient, diffuse, dir, cube);
VectorMA(ambient, 0.5, diffuse, G_VECTOR(OFS_RETURN));
}
}

View File

@ -93,7 +93,7 @@ float R_Clutter_FRandom(clutter_build_ctx_t *ctx)
static void R_Clutter_Insert_Soup(clutter_build_ctx_t *ctx, shader_t *shader, vecV_t *fte_restrict coord, vec2_t *fte_restrict texcoord, vec3_t *fte_restrict normal, vec3_t *fte_restrict sdir, vec3_t *fte_restrict tdir, vec4_t *fte_restrict colours, size_t numverts, index_t *fte_restrict index, size_t numidx, float scale, vec3_t origin, vec3_t axis[])
{
vec3_t diffuse, ambient, ldir;
vec3_t diffuse, ambient, ldir, cube[6];
float dot;
struct clutter_build_ctx_soup_s *soup = NULL;
size_t i;
@ -141,7 +141,7 @@ static void R_Clutter_Insert_Soup(clutter_build_ctx_t *ctx, shader_t *shader, ve
soup->idx[soup->numidx++] = soup->numverts+*index++;
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, origin, diffuse, ambient, ldir);
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, origin, diffuse, ambient, ldir, cube);
VectorScale(ambient, 1/255.0, ambient);
VectorScale(diffuse, 1/255.0, diffuse);

View File

@ -87,6 +87,13 @@ typedef enum {
RT_MAX_REF_ENTITY_TYPE
} refEntityType_t;
enum entlighttype_e
{
ELT_UNKNOWN, //not computed yet.
ELT_LAMBERT,
ELT_FLAT,
ELT_CUBE,
};
typedef unsigned int skinid_t; //skin 0 is 'unused'
@ -105,7 +112,8 @@ typedef struct entity_s
float shaderTime; /*timestamp, for syncing shader times to spawns*/
vec3_t glowmod; /*meant to be a multiplier for the fullbrights*/
int light_known; /*bsp lighting has been calced*/
enum entlighttype_e light_type; /*bsp lighting has been calced*/
vec3_t light_cube[6]; /*hl2-style lighting*/
vec3_t light_avg; /*midpoint level*/
vec3_t light_range; /*avg + this = max, avg - this = min*/
vec3_t light_dir;

View File

@ -107,7 +107,7 @@ typedef enum uploadfmt
PTI_L8_SRGB, //8bit format. luminance gets flooded to all RGB channels. might be supported using swizzles.
PTI_L8A8_SRGB, //16bit format. L=luminance. note: this cannot be implemented as a swizzle as there's no way to get srgb on red without it on green.
//small formats.
PTI_P8, //used for paletted data. Loaded as R8, but separate purely due to mipmap generation. should probably make a mipgen enum.
PTI_P8, //used for paletted data (with common/engine palette). Loaded as R8, but separate purely due to mipmap generation. should probably make a mipgen enum.
PTI_R8, //used for greyscale data (that doesn't need to get expanded to rgb).
PTI_RG8, //might be useful for normalmaps
PTI_R8_SNORM,

View File

@ -2736,11 +2736,12 @@ qboolean Mod_Mesh_EdictInFatPVS(struct model_s *model, const struct pvscache_s *
void Mod_Mesh_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, const vec3_t cullmins, const vec3_t cullmaxs)
{
}
static void Mod_Mesh_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
static enum entlighttype_e Mod_Mesh_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6])
{ //trisoup doesn't have any actual pvs, thus we can't report anything...
VectorSet(res_diffuse, 255,255,255);
VectorSet(res_ambient, 128,128,128);
VectorSet(res_dir, 0,0,1);
return ELT_LAMBERT;
}
static void Mod_SetMeshModelFuncs(model_t *mod, qboolean isstatic)
{

View File

@ -44,6 +44,7 @@ cvar_t q3bsp_bihtraces = CVARFD("_q3bsp_bihtraces", /*FIXME: generate BIH leafs
#ifdef HL2BSPS
static cvar_t hl2_displacement_scale = CVARFD("hl2_displacement_scale", "1", CVAR_RENDERERLATCH|CVAR_CHEAT, "Multiplier for how far displacements can move.");
static cvar_t hl2_favour_ldr = CVARFD("hl2_favour_ldr", "0", CVAR_RENDERERLATCH|CVAR_CHEAT, "Favour LDR data instead of HDR (when both are present).");
#endif
#if Q3SURF_NODRAW != TI_NODRAW
@ -324,6 +325,16 @@ typedef struct cminfo_s
qbyte portalquerying[MAX_Q2MAP_AREAPORTALS];
mesh_t *portalpoly; //[numq2areaportals]
int *occlusionqueries; //[numq2areaportals]
struct mleaflight_s
{
struct leaflightpoint_s
{
vec3_t rgb[6];
qbyte x, y, z;
} *point;
int count;
} *leaflight;
#endif
@ -4498,8 +4509,8 @@ enum hllumps_e
VLUMP_VISIBILITY = LUMP_VISIBILITY,
VLUMP_NODES = LUMP_NODES,
VLUMP_TEXINFO = LUMP_TEXINFO,
VLUMP_FACES = LUMP_FACES,
VLUMP_LIGHTING = LUMP_LIGHTING,
VLUMP_FACES_LDR = LUMP_FACES,
VLUMP_LIGHTING_LDR = LUMP_LIGHTING,
// VLUMP_FOO = 9,//LUMP_CLIPNODES
VLUMP_LEAFS = LUMP_LEAFS,
// VLUMP_FOO = 11,//LUMP_MARKSURFACES
@ -4543,14 +4554,14 @@ enum hllumps_e
VLUMP_DISP_TRIFLAGS = 48,
// VLUMP_FOO = 49,
// VLUMP_FOO = 50,
// VLUMP_FOO = 51,
// VLUMP_FOO = 52,
VLUMP_LEAFLIGHTI_HDR= 51, //indexes into VLUMP_LEAFLIGHTV_HDR, two shorts per leaf.
VLUMP_LEAFLIGHTI_LDR= 52,
VLUMP_LIGHTING_HDR = 53,
// VLUMP_FOO = 54,
// VLUMP_FOO = 55,
// VLUMP_FOO = 56,
VLUMP_LEAFLIGHTV_HDR= 55,
VLUMP_LEAFLIGHTV_LDR= 56,
// VLUMP_FOO = 57,
// VLUMP_FOO = 58,
VLUMP_FACES_HDR = 58,
// VLUMP_FOO = 59,
// VLUMP_FOO = 60,
// VLUMP_FOO = 61,
@ -4821,6 +4832,11 @@ typedef struct
//new for hl2
short leafwaterid;
struct //present in v19. gone in v20.
{
qbyte rgb[3];
signed char e;
} light[6];
short pad;
} hl2dleaf_t;
static qboolean CModHL2_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l, int ver)
@ -4831,7 +4847,8 @@ static qboolean CModHL2_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l, int
hl2dleaf_t *in;
int count;
size_t insize = sizeof(*in);
if (ver == 19)
struct leaflightpoint_s *lightpoint = NULL;
if (ver < 20)
insize = 56; //older maps have some lighting info here.
else
insize = 32;
@ -4862,6 +4879,12 @@ static qboolean CModHL2_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l, int
mod->leafs = out;
mod->numleafs = count;
if (ver < 20)
{
prv->leaflight = ZG_Malloc(&mod->memgroup, sizeof(*out) * count);
lightpoint = ZG_Malloc(&mod->memgroup, sizeof(*lightpoint) * count);
}
for ( i=0 ; i<count ; i++, in = (hl2dleaf_t*)((qbyte*)in+insize), out++)
{
memset(out, 0, sizeof(*out));
@ -4892,13 +4915,178 @@ static qboolean CModHL2_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l, int
if (out->cluster >= mod->numclusters)
mod->numclusters = out->cluster + 1;
if (lightpoint)
{
for (j = 0; j < 6; j++)
{
float e = pow(2, in->light[j].e);
lightpoint->rgb[j][0] = e * in->light[j].rgb[0];
lightpoint->rgb[j][1] = e * in->light[j].rgb[1];
lightpoint->rgb[j][2] = e * in->light[j].rgb[2];
}
prv->leaflight[i].count = 1;
prv->leaflight[i].point = lightpoint++;
}
}
out = mod->leafs;
mod->pvsbytes = ((mod->numclusters + 31)>>3)&~3;
return true;
}
#ifdef HAVE_CLIENT
static void CModHL2_LoadLeafLight (model_t *mod, qbyte *mod_base, lump_t *hdridx, lump_t *ldridx, lump_t *hdrvals, lump_t *ldrvals, int version)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
lump_t *lump_idx, *lump_vals;
struct leaflightpoint_s *point;
size_t i, j;
unsigned short *in;
qbyte *inpoint;
if (version < 20)
return; //nope. this info is in the leafs.
if (hdridx && hdrvals)
lump_idx = hdridx, lump_vals = hdrvals;
else if (ldridx && ldrvals)
lump_idx = ldridx, lump_vals = ldrvals;
else
return; //unsupported.
if (lump_vals->filelen%(7*4))
return;
if (lump_idx->filelen != mod->numleafs*sizeof(short)*2)
return; //erk?
//easy enough to load some of the data...
point = ZG_Malloc(&mod->memgroup, sizeof(*point)*(lump_vals->filelen/(7*4)));
inpoint = mod_base + lump_vals->fileofs;
for (i = 0; i < lump_vals->filelen/(7*4); i++)
{
for (j = 0; j < 6; j++, inpoint+=4)
{
float e = pow(2, (signed char)inpoint[3]);
point[i].rgb[j][0] = e * inpoint[0];
point[i].rgb[j][1] = e * inpoint[1];
point[i].rgb[j][2] = e * inpoint[2];
}
point[i].x = *inpoint++;
point[i].y = *inpoint++;
point[i].z = *inpoint++;
inpoint++;
}
prv->leaflight = ZG_Malloc(&mod->memgroup, sizeof(*prv->leaflight)*mod->numleafs);
in = (unsigned short*)(mod_base + lump_idx->fileofs);
for (i = 0; i < mod->numleafs; i++)
{
prv->leaflight[i].count = LittleShort(*in++);
prv->leaflight[i].point = point + (unsigned short)LittleShort(*in++);
}
}
enum entlighttype_e HL2BSP_LightPointValues (struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6])
{
cvar_t *srgbmag = Cvar_Get("lt_srgb_mag", "1", 0, "TEST");
cvar_t *scale = Cvar_Get("lt_scale", "256", 0, "TEST");
cvar_t *forceface = Cvar_Get("lt_face", "-1", 0, "TEST");
cminfo_t *prv = (cminfo_t*)model->meshinfo;
int leafnum = CM_PointLeafnum(model,point);
mleaf_t *leaf = model->leafs+leafnum;
struct mleaflight_s *leaflight = prv->leaflight+leafnum;
struct leaflightpoint_s *best, *lp;
size_t i, j, d, bd=~0;
int xyz[3];
vec3_t diff[6];
float sig[6];
if (prv->leaflight && leaflight->count)
{
for (i = 0; i < 3; i++)
xyz[i] = 255*(point[i] - leaf->minmaxs[i]) / (leaf->minmaxs[3+i]-leaf->minmaxs[i]);
for (i = 0, best=lp = leaflight->point; i < leaflight->count; i++, lp++)
{
int m[3];
m[0] = xyz[0] - lp->x;
m[1] = xyz[1] - lp->y;
m[2] = xyz[2] - lp->z;
d = DotProduct(m,m);
if (bd > d)
{
bd = d;
best = lp;
}
}
VectorClear(res_ambient);
for (j = 0; j < 6; j++)
VectorAdd(res_ambient, best->rgb[j], res_ambient);
VectorScale(res_ambient, 1.0/6, res_ambient);
//try and figure out an average dir for the brightest direction
for (j = 0; j < 6; j++)
{
VectorSubtract(best->rgb[j], res_ambient, diff[j]);
sig[j] = VectorLength(diff[j]);
}
for (j = 0; j < 3; j++)
res_dir[j] = sig[j*2+1] - sig[j*2];
VectorNormalize(res_dir);
//figure out how much light there should be in that direction.
VectorCopy(res_ambient, res_diffuse);
for (j = 0; j < 3; j++)
{
if (res_dir[0]>=0)
VectorMA(res_diffuse, res_dir[0], diff[j*2+1], res_diffuse);
else
VectorMA(res_diffuse, -res_dir[0], diff[j*2+0], res_diffuse);
}
if (forceface->ival >= 0)
{
VectorCopy(best->rgb[forceface->ival], res_diffuse);
VectorCopy(best->rgb[forceface->ival], res_ambient);
VectorClear(res_dir);
res_dir[forceface->ival/3] = (forceface->ival&1)?-1:1;
}
if (srgbmag->value)
{
for (j = 0; j < 3; j++)
{
res_diffuse[j] = M_LinearToSRGB(res_diffuse[j], srgbmag->value)*scale->value;
res_ambient[j] = M_LinearToSRGB(res_ambient[j], srgbmag->value)*scale->value;
}
for (j = 0; j < 6; j++)
{
res_cube[j][0] = M_LinearToSRGB(best->rgb[j][0], srgbmag->value)*scale->value;
res_cube[j][1] = M_LinearToSRGB(best->rgb[j][1], srgbmag->value)*scale->value;
res_cube[j][2] = M_LinearToSRGB(best->rgb[j][2], srgbmag->value)*scale->value;
}
}
else
{
VectorScale(res_diffuse, scale->value, res_diffuse);
VectorScale(res_ambient, scale->value, res_ambient);
for (j = 0; j < 6; j++)
VectorScale(best->rgb[j], scale->value, res_cube[j]);
}
return ELT_CUBE;
}
VectorSet(res_dir, 0,0.707,0.707);
VectorSet(res_diffuse, 64,64,64);
VectorSet(res_ambient, 192,192,192);
return ELT_FLAT;
}
#endif
#if defined(HAVE_CLIENT) && defined(GLQUAKE)
//for each area that we recurse, follow the neighbouring areas and check their area portals too.
//if a portal is closed, we switch to using a solid opaque shader, to avoid any HOM glitches.
@ -5308,8 +5496,8 @@ typedef struct
} hl2dface_t;
static qboolean CModHL2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *lumps, int version)
{
lump_t *l = &lumps[VLUMP_FACES];
lump_t *l2 = &lumps[58];
lump_t *l = &lumps[VLUMP_FACES_LDR];
lump_t *l2 = &lumps[VLUMP_FACES_HDR];
hl2dface_t *in;
msurface_t *out;
int i, count, surfnum;
@ -5317,7 +5505,7 @@ static qboolean CModHL2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *lumps,
int ti, st;
int lumpsize = sizeof(*in);
if (l2->filelen)
if (l2->filelen && !(hl2_favour_ldr.ival && lumps[VLUMP_LIGHTING_LDR].filelen))
l = l2;
if (version == 18)
@ -5405,21 +5593,21 @@ static qboolean CModHL2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *lumps,
return true;
}
#ifdef HAVE_CLIENT
static void CModHL2_LoadLighting (model_t *mod, qbyte *mod_base, lump_t *oldl, lump_t *newl)
static void CModHL2_LoadLighting (model_t *mod, qbyte *mod_base, lump_t *ldr, lump_t *hdr)
{
if (newl->filelen)
{ //this data is screwy. it LOOKS like e8bgr8, but we still get weird results.
mod->lightmaps.fmt = LM_E8BGR8;
mod->lightdatasize = newl->filelen;
mod->lightdata = ZG_Malloc(&mod->memgroup, mod->lightdatasize);
memcpy(mod->lightdata, (void *)(mod_base + newl->fileofs), mod->lightdatasize);
}
else if (oldl->filelen)
if (hdr->filelen && !(hl2_favour_ldr.ival && ldr->filelen))
{
mod->lightmaps.fmt = LM_E8BGR8;
mod->lightdatasize = oldl->filelen;
mod->lightdatasize = hdr->filelen;
mod->lightdata = ZG_Malloc(&mod->memgroup, mod->lightdatasize);
memcpy(mod->lightdata, (void *)(mod_base + oldl->fileofs), mod->lightdatasize);
memcpy(mod->lightdata, (void *)(mod_base + hdr->fileofs), mod->lightdatasize);
}
else if (ldr->filelen)
{
mod->lightmaps.fmt = LM_E8BGR8;
mod->lightdatasize = ldr->filelen;
mod->lightdata = ZG_Malloc(&mod->memgroup, mod->lightdatasize);
memcpy(mod->lightdata, (void *)(mod_base + ldr->fileofs), mod->lightdatasize);
}
}
#endif
@ -5658,7 +5846,7 @@ static qboolean CModHL2_LoadStaticProps(model_t *mod, qbyte *offset, size_t size
}
}
//Hack: lighting is wrong.
ent->light_known = 1;
ent->light_type = ELT_UNKNOWN;
VectorSet(ent->light_dir, 0, 0.707, 0.707);
VectorSet(ent->light_avg, 0.75, 0.75, 0.75);
VectorSet(ent->light_range, 0.5, 0.5, 0.5);
@ -5761,7 +5949,7 @@ static qboolean VBSP_LoadModel(model_t *mod, qbyte *mod_base, size_t filelen, ch
noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[VLUMP_SURFEDGES]);
#ifdef HAVE_CLIENT
if (noerrors && haverenderer)
CModHL2_LoadLighting (mod, mod_base, &header.lumps[VLUMP_LIGHTING], &header.lumps[VLUMP_LIGHTING_HDR]);
CModHL2_LoadLighting (mod, mod_base, &header.lumps[VLUMP_LIGHTING_LDR], &header.lumps[VLUMP_LIGHTING_HDR]);
#endif
noerrors = noerrors && CModHL2_LoadSurfaces (mod, mod_base, &header.lumps[VLUMP_TEXINFO]);
noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[VLUMP_PLANES]);
@ -5780,6 +5968,11 @@ static qboolean VBSP_LoadModel(model_t *mod, qbyte *mod_base, size_t filelen, ch
noerrors = noerrors && CModQ2_LoadSubmodels (mod, mod_base, &header.lumps[VLUMP_MODELS]);
noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[VLUMP_AREAS]);
noerrors = noerrors && CModHL2_LoadAreaPortals (mod, mod_base, &header.lumps[VLUMP_AREAPORTALS], &header.lumps[VLUMP_AREAPORTALVERTS]);
#ifdef HAVE_CLIENT
if (noerrors && haverenderer)
CModHL2_LoadLeafLight (mod, mod_base, &header.lumps[VLUMP_LEAFLIGHTI_HDR], &header.lumps[VLUMP_LEAFLIGHTI_LDR],
&header.lumps[VLUMP_LEAFLIGHTV_HDR], &header.lumps[VLUMP_LEAFLIGHTV_LDR], header.version);
#endif
noerrors = noerrors && CModHL2_LoadGameLump (mod, mod_base, &header.lumps[VLUMP_GAMELUMP]);
if (!noerrors)
@ -5790,7 +5983,7 @@ static qboolean VBSP_LoadModel(model_t *mod, qbyte *mod_base, size_t filelen, ch
mod->funcs.FindTouchedLeafs = Q23BSP_FindTouchedLeafs;
#endif
#ifdef HAVE_CLIENT
mod->funcs.LightPointValues = GLQ2BSP_LightPointValues;
mod->funcs.LightPointValues = HL2BSP_LightPointValues;
mod->funcs.StainNode = GLR_Q2BSP_StainNode;
mod->funcs.MarkLights = Q2BSP_MarkLights;
#endif
@ -8728,6 +8921,7 @@ void CM_Init(void) //register cvars.
#ifdef HL2BSPS
Cvar_Register(&hl2_displacement_scale, MAPOPTIONS);
Cvar_Register(&hl2_favour_ldr, MAPOPTIONS);
#endif
CM_InitBoxHull ();

View File

@ -1350,7 +1350,7 @@ static void R_DrawShadowVolume(mesh_t *mesh)
#endif
//true if no shading is to be used.
qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
void R_CalcModelLighting(entity_t *e, model_t *clmodel)
{
vec3_t lightdir;
int i;
@ -1358,16 +1358,16 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
float add, m;
vec3_t shadelight, ambientlight;
if (e->light_known)
return e->light_known-1;
if (e->light_type != ELT_UNKNOWN) //don't bother recalculating if its already been calced.
return;
e->light_dir[0] = 0; e->light_dir[1] = 1; e->light_dir[2] = 0;
if ((clmodel->engineflags & MDLF_FLAME) || r_fullbright.ival)
{
e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1;
e->light_range[0] = e->light_range[1] = e->light_range[2] = 0;
e->light_known = 2;
return e->light_known-1;
e->light_type = ELT_FLAT;
return;
}
if (
#ifdef HEXEN2
@ -1377,22 +1377,22 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
{
e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1;
e->light_range[0] = e->light_range[1] = e->light_range[2] = 0;
e->light_known = 2;
return e->light_known-1;
e->light_type = ELT_FLAT;
return;
}
if (r_fb_models.ival == 1 && ruleset_allow_fbmodels.ival && (clmodel->engineflags & MDLF_EZQUAKEFBCHEAT) && cls.protocol == CP_QUAKEWORLD && cl.deathmatch)
{
e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1;
e->light_range[0] = e->light_range[1] = e->light_range[2] = 0;
e->light_known = 2;
return e->light_known-1;
e->light_type = ELT_FLAT;
return;
}
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (e->flags & RF_WEAPONMODEL)
{
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, r_refdef.vieworg, shadelight, ambientlight, lightdir);
e->light_type = cl.worldmodel->funcs.LightPointValues(cl.worldmodel, r_refdef.vieworg, shadelight, ambientlight, lightdir, e->light_cube);
for (i = 0; i < 3; i++)
{ /*viewmodels may not be pure black*/
if (ambientlight[i] < 24)
@ -1407,9 +1407,9 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
VectorAdd(e->origin, center, center);
#else
VectorCopy(e->origin, center);
center[2] += 24;
// center[2] += 24;
#endif
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, center, shadelight, ambientlight, lightdir);
e->light_type = cl.worldmodel->funcs.LightPointValues(cl.worldmodel, center, shadelight, ambientlight, lightdir, e->light_cube);
}
}
else
@ -1579,8 +1579,8 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
VectorClear(e->light_range);
VectorScale(shadelight, fb, e->light_avg);
e->light_known = 2;
return e->light_known-1;
e->light_type = ELT_FLAT;
return;
}
else
{
@ -1658,9 +1658,6 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
VectorMA(ambientlight, 0.5, shadelight, e->light_avg);
VectorSubtract(shadelight, ambientlight, e->light_range);
}
e->light_known = 1;
return e->light_known-1;
}
void R_GAlias_DrawBatch(batch_t *batch)
@ -2871,7 +2868,7 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo
VectorSet(r_worldentity.light_avg, 1.0, 1.0, 1.0);
VectorSet(r_worldentity.light_range, 0.5, 0.5, 0.5);
VectorSet(r_worldentity.light_dir, 0.0, 0.196, 0.98);
r_worldentity.light_known = 1;
r_worldentity.light_type = ELT_LAMBERT;
R_GAlias_GenerateBatches(&r_worldentity, batches);
}

View File

@ -3412,7 +3412,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
for (i = perm->numparms; i > 0; i--, p++)
{
ph = p->handle;
switch(p->type)
safeswitch(p->type)
{
/*
case SP_UBO_ENTITYINFO:
@ -3666,23 +3666,23 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
break;
case SP_E_GLOWMOD:
qglUniform3fvARB(ph, 1, (GLfloat*)shaderstate.curentity->glowmod);
qglUniform3fvARB(ph, 1, (const GLfloat*)shaderstate.curentity->glowmod);
break;
case SP_E_ORIGIN:
qglUniform3fvARB(ph, 1, (GLfloat*)shaderstate.curentity->origin);
qglUniform3fvARB(ph, 1, (const GLfloat*)shaderstate.curentity->origin);
break;
case SP_E_COLOURS:
qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.curentity->shaderRGBAf);
qglUniform4fvARB(ph, 1, (const GLfloat*)shaderstate.curentity->shaderRGBAf);
break;
case SP_S_COLOUR:
if (shaderstate.colourarraytype)
qglUniform4fARB(ph, 1, 1, 1, 1); //invalid use
else
qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.pendingcolourflat);
qglUniform4fvARB(ph, 1, (const GLfloat*)shaderstate.pendingcolourflat);
break;
case SP_E_COLOURSIDENT:
if (shaderstate.flags & BEF_FORCECOLOURMOD)
qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.curentity->shaderRGBAf);
qglUniform4fvARB(ph, 1, (const GLfloat*)shaderstate.curentity->shaderRGBAf);
else
qglUniform4fARB(ph, 1, 1, 1, shaderstate.curentity->shaderRGBAf[3]);
break;
@ -3814,19 +3814,28 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
/*static lighting info*/
case SP_E_L_DIR:
qglUniform3fvARB(ph, 1, (float*)shaderstate.curentity->light_dir);
qglUniform3fvARB(ph, 1, (const float*)shaderstate.curentity->light_dir);
break;
case SP_E_L_MUL:
if (shaderstate.mode == BEM_DEPTHDARK)
qglUniform3fvARB(ph, 1, vec3_origin);
else
qglUniform3fvARB(ph, 1, (float*)shaderstate.curentity->light_range);
qglUniform3fvARB(ph, 1, (const float*)shaderstate.curentity->light_range);
break;
case SP_E_L_AMBIENT:
if (shaderstate.mode == BEM_DEPTHDARK)
qglUniform3fvARB(ph, 1, vec3_origin);
else
qglUniform3fvARB(ph, 1, (float*)shaderstate.curentity->light_avg);
qglUniform3fvARB(ph, 1, (const float*)shaderstate.curentity->light_avg);
break;
case SP_E_L_AMBIENTCUBE:
if (shaderstate.mode == BEM_DEPTHDARK)
{
static vec3_t nulllightcube[6];
qglUniform3fvARB(ph, 6, (const float*)nulllightcube);
}
else
qglUniform3fvARB(ph, 6, (const float*)shaderstate.curentity->light_cube);
break;
case SP_E_TIME:
@ -3861,7 +3870,19 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
qglUniform3fvARB(ph, 1, ((cvar_t*)p->pval)->vec4);
break;
default:
case SP_CONST2I:
//qglUniform2iARB(ph, p->ival[0], p->ival[1], 0);
//break;
case SP_CONST3I:
//qglUniform3iARB(ph, p->ival[0], p->ival[1], p->ival[2]);
//break;
case SP_CONST4I:
//qglUniform4iARB(ph, p->ival[0], p->ival[1], p->ival[2], p->ival[3]);
//break;
case SP_BAD:
case SP_FIRSTIMMEDIATE:
case SP_M_ENTBONES_MAT4:
safedefault:
Host_EndGame("Bad shader program parameter type (%i)", p->type);
break;
}
@ -3891,6 +3912,8 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density)
perm |= PERMUTATION_FOG;
if (shaderstate.curentity->light_type==ELT_CUBE)
perm |= PERMUTATION_AMBIENTCUBE;
// if (TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// perm |= PERMUTATION_DELUXE;
if ((TEXLOADED(shaderstate.curtexnums->reflectcube) || TEXLOADED(shaderstate.curtexnums->reflectmask)))
@ -3904,6 +3927,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
permu = p->permu[perm];
if (!permu)
{
Con_DLPrintf(2, "%s: Lazy permutation load - %x\n", p->name, perm);
p->permu[perm] = permu = Shader_LoadPermutation(p, perm);
if (!permu)
{ //failed? copy from 0 so we don't keep re-failing

View File

@ -4444,7 +4444,7 @@ void Heightmap_FindTouchedLeafs (model_t *mod, pvscache_t *ent, const float *min
}
#endif
void Heightmap_LightPointValues (model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
enum entlighttype_e Heightmap_LightPointValues (model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6])
{
res_diffuse[0] = 128;
res_diffuse[1] = 128;
@ -4456,6 +4456,7 @@ void Heightmap_LightPointValues (model_t *mod, const vec3_t point, vec3_t res_di
res_dir[1] = 0;//cos(time);
res_dir[2] = 0;//sin(time);
VectorNormalize(res_dir);
return ELT_LAMBERT;
}
void Heightmap_StainNode (mnode_t *node, float *parms)
{

View File

@ -283,7 +283,7 @@ typedef struct {
qboolean (*EdictInFatPVS) (struct model_s *model, const struct pvscache_s *edict, const qbyte *pvs, const int *areas); //areas[0] is the count of accepted areas, if valid.
void (*FindTouchedLeafs) (struct model_s *model, struct pvscache_s *ent, const vec3_t cullmins, const vec3_t cullmaxs); //edict system as opposed to q2 game dll system.
void (*LightPointValues) (struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
enum entlighttype_e (*LightPointValues) (struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6]);
void (*StainNode) (struct mnode_s *node, float *parms);
void (*MarkLights) (struct dlight_s *light, dlightbitmask_t bit, struct mnode_s *node);
@ -636,7 +636,7 @@ size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes,
void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, unsigned int surfflagmask, unsigned int surflagmatch, void (*callback)(void *ctx, vec3_t *fte_restrict points, size_t numpoints, shader_t *shader), void *ctx);
void Q1BSP_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node);
void GLQ1BSP_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
enum entlighttype_e GLQ1BSP_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6]);
qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, const vec3_t p1, const vec3_t p2, unsigned int hitcontents, struct trace_s *trace);
/*

View File

@ -68,7 +68,7 @@ void R_UpdateHDR(vec3_t org)
if (r_hdr_irisadaptation.ival && cl.worldmodel && !(r_refdef.flags & RDF_NOWORLDMODEL))
{
//fake and lame, but whatever.
vec3_t ambient, diffuse, dir;
vec3_t ambient, diffuse, dir, cube[6];
float lev = 0;
#ifdef RTLIGHTS
@ -79,7 +79,7 @@ void R_UpdateHDR(vec3_t org)
if (!r_shadow_realtime_world.ival || r_shadow_realtime_world_lightmaps.value)
#endif
{
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, org, ambient, diffuse, dir);
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, org, ambient, diffuse, dir, cube);
lev += (VectorLength(ambient) + VectorLength(diffuse))/256;
}
@ -2346,7 +2346,7 @@ static void GLQ3_AddLatLong(const qbyte latlong[2], vec3_t dir, float mag)
dir[2] += mag * cos ( lat );
}
void GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
enum entlighttype_e GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6])
{
q3lightgridinfo_t *lg = (q3lightgridinfo_t *)mod->lightgrid;
int index[8];
@ -2378,7 +2378,7 @@ void GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t
res_dir[1] = 1;
res_dir[2] = 0.1;
}
return;
return ELT_LAMBERT;
}
//If in doubt, steal someone else's code...
@ -2458,6 +2458,8 @@ void GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t
VectorAdd(diffuse, ambient, res_diffuse);
if (res_dir)
VectorCopy(direction, res_dir);
return ELT_LAMBERT;
}
static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
@ -2616,7 +2618,7 @@ int R_LightPoint (vec3_t p)
if (cl.worldmodel->fromgame == fg_quake3)
{
GLQ3_LightGrid(cl.worldmodel, p, NULL, end, NULL);
GLQ3_LightGrid(cl.worldmodel, p, NULL, end, NULL, NULL);
return (end[0] + end[1] + end[2])/3;
}
@ -2925,7 +2927,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
#endif
void GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
enum entlighttype_e GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6])
{
vec3_t end;
float *r;
@ -2949,7 +2951,7 @@ void GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_dif
res_dir[1] = 1;
res_dir[2] = 0.1;
VectorNormalize(res_dir);
return;
return ELT_LAMBERT;
}
end[0] = point[0];
@ -3000,6 +3002,7 @@ void GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_dif
VectorScale(res_ambient, lm, res_ambient);
}
#endif
return ELT_LAMBERT;
}
#endif

View File

@ -1361,7 +1361,8 @@ static struct
{"SKELETAL", PERMUTATION_SKELETAL},
{"FOG", PERMUTATION_FOG},
{"FRAMEBLEND", PERMUTATION_FRAMEBLEND},
{"LIGHTSTYLED", PERMUTATION_LIGHTSTYLES}
{"LIGHTSTYLED", PERMUTATION_LIGHTSTYLES},
{"AMBIENTCUBE", PERMUTATION_AMBIENTCUBE},
};
#define MAXMODIFIERS 64
@ -2340,6 +2341,7 @@ struct shader_field_names_s shader_unif_names[] =
/**/{"e_light_dir", SP_E_L_DIR}, //lightgrid light dir. dotproducts should be clamped to 0-1.
/**/{"e_light_mul", SP_E_L_MUL}, //lightgrid light scaler.
/**/{"e_light_ambient", SP_E_L_AMBIENT}, //lightgrid light value for the unlit side.
/**/{"e_light_ambientcube", SP_E_L_AMBIENTCUBE},//6 lightgrid light values.
{"s_colour", SP_S_COLOUR}, //the rgbgen/alphagen stuff. obviously doesn't work with per-vertex ones.

View File

@ -1547,10 +1547,14 @@ static const char *glsl_hdrs[] =
"uniform vec4 e_colourident;"
"uniform vec3 e_glowmod;"
"uniform vec3 e_uppercolour;"
"uniform vec3 e_lowercolour;"
"uniform vec3 e_lowercolour;\n"
"#ifdef AMBIENTCUBE\n"
"uniform vec3 e_light_ambientcube[6];\n"
"#else\n"
"uniform vec3 e_light_dir;"
"uniform vec3 e_light_mul;"
"uniform vec3 e_light_ambient;"
"uniform vec3 e_light_ambient;\n"
"#endif\n"
/*rtlight properties, use with caution*/
"uniform vec2 l_lightscreen;"

View File

@ -390,7 +390,7 @@ void R_InitFlashblends(void);
#ifdef GLQUAKE
void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node);
#endif
void GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
enum entlighttype_e GLQ3_LightGrid(model_t *mod, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir, vec3_t res_cube[6]);
qboolean R_LoadRTLights(void);
qboolean R_ImportRTLights(const char *entlump);

View File

@ -373,6 +373,9 @@ enum{
#define PERMUTATION_LIGHTSTYLES 0u
#endif
#define PERMUTATION_AMBIENTCUBE (1u<<PERMUTATION_BIT_AMBIENTCUBE)
PERMUTATION_BIT_AMBIENTCUBE, //light info is 6 axial light values.
PERMUTATION_BIT_MAX
};
#define PERMUTATIONS (1u<<PERMUTATION_BIT_MAX)
@ -436,6 +439,7 @@ typedef struct {
SP_E_L_DIR, /*these light values are non-dynamic light as in classic quake*/
SP_E_L_MUL,
SP_E_L_AMBIENT,
SP_E_L_AMBIENTCUBE,
SP_E_EYEPOS, /*viewer's eyepos, in model space*/
SP_V_EYEPOS, /*viewer's eyepos, in world space*/
SP_W_FOG,

View File

@ -4205,12 +4205,12 @@ static void QCBUILTIN PF_sv_getlight (pubprogfuncs_t *prinst, struct globalvars_
#ifdef HAVE_CLIENT
/*not shared with client - clients get more lights*/
float *point = G_VECTOR(OFS_PARM0);
vec3_t diffuse, ambient, dir;
vec3_t diffuse, ambient, dir, cube[6];
model_t *wm = sv.world.worldmodel;
if (wm && wm->loadstate == MLS_LOADED && wm->funcs.LightPointValues && wm->lightmaps.maxstyle<cl_max_lightstyles)
{
wm->funcs.LightPointValues(wm, point, diffuse, ambient, dir);
wm->funcs.LightPointValues(wm, point, diffuse, ambient, dir, cube);
VectorMA(ambient, 0.5, diffuse, G_VECTOR(OFS_RETURN));
return;
}

View File

@ -7283,7 +7283,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
//fixme: should probably support rtlights, but this is a server, so urgh.
if (sv.world.worldmodel && sv.world.worldmodel->funcs.LightPointValues)
{
vec3_t diffuse, ambient, dir;
vec3_t diffuse, ambient, dir, cube[6];
float lev = 0;
#if defined(RTLIGHTS) && !defined(SERVERONLY)
Sh_CalcPointLight(sv_player->v->origin, ambient);
@ -7292,7 +7292,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
if (!r_shadow_realtime_world.ival || r_shadow_realtime_world_lightmaps.value)
#endif
{
sv.world.worldmodel->funcs.LightPointValues(sv.world.worldmodel, sv_player->v->origin, ambient, diffuse, dir);
sv.world.worldmodel->funcs.LightPointValues(sv.world.worldmodel, sv_player->v->origin, ambient, diffuse, dir, cube);
lev += (VectorLength(ambient) + VectorLength(diffuse)/2.0)/256;
}
sv_player->xv->light_level = lev * 255;

View File

@ -33,7 +33,7 @@ varying vec3 eyeminusvertex;
vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 );
norm_f = ( texture2D( s_normalmap, tex_c).xyz);
norm_f.g *= -1.0f;
norm_f.g *= -1.0;
norm_f = normalize( norm_f );
// Reflection/View coordinates

View File

@ -3,8 +3,8 @@
!!permu BUMP
!!permu FOG
!!permu SKELETAL
!!permu AMBIENTCUBE
!!samps diffuse fullbright normalmap
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
@ -104,11 +104,18 @@ varying vec3 norm;
diffuse_f.rgb += (textureCube(s_reflectcube, cube_c).rgb * vec3(refl,refl,refl));
#endif
#ifdef HALFLAMBERT
light = e_light_ambient + (e_light_mul * halflambert(norm, e_light_dir));
#ifdef AMBIENTCUBE
//no specular effect here. use rtlights for that.
vec3 nn = norm*norm; //FIXME: should be worldspace normal.
light = nn.x * e_light_ambientcube[(norm.x<0.0)?1:0] +
nn.y * e_light_ambientcube[(norm.y<0.0)?3:2] +
nn.z * e_light_ambientcube[(norm.z<0.0)?5:4];
#else
#ifdef HALFLAMBERT
light = e_light_ambient + (e_light_mul * halflambert(norm, e_light_dir));
#else
light = e_light_ambient + (e_light_mul * lambert(norm, e_light_dir));
#endif
#endif
/* the light we're getting is always too bright */
light *= 0.75;
@ -120,6 +127,7 @@ varying vec3 norm;
light.g = 1.5;
if (light.b > 1.5)
light.b = 1.5;
#endif
diffuse_f.rgb *= light;