Compare commits

...

33 Commits
master ... hl2

Author SHA1 Message Date
Shpoike 42d18bc5f1 resize the modelviewer's texture display if it would have gone offscreen. 2021-08-19 07:21:19 +01:00
Shpoike fa5538f696 Accept portal2's models too. 2021-08-19 07:21:19 +01:00
Shpoike 86e427126c First attempt at hl2 lightcube stuff. 2021-08-19 07:21:19 +01:00
Shpoike 483b25be2c Use more of the static prop properties - alphafading, lightorg, and leafrefs. 2021-08-19 07:21:19 +01:00
Shpoike f0fc7bfa0f Dedicated hl2bsp servers should now compile and work. 2021-08-19 07:21:19 +01:00
Shpoike 26d7371c95 Fix up some -Werror errors. 2021-08-19 07:21:19 +01:00
M.C. a65e717d21 vmt loader: handle rendertarget surfaces 2021-08-19 07:21:19 +01:00
M.C. 60ba88c33b change vmt_unlit to the default fallback for unknown vmt shaders 2021-08-19 07:21:19 +01:00
Shpoike 45ffcb91f4 Fix up r_showfields 3 a little, to make it easier to see which props are which. 2021-08-19 07:21:19 +01:00
Shpoike 93ee065acf This is Eukara's attempt to parse vmt files better. 2021-08-19 07:21:19 +01:00
Shpoike 804ff3f5b2 Load hl2 model textures and multiple bodies+meshes. lods are still broken. 2021-08-19 07:21:19 +01:00
Shpoike f4d9df2b24 Make sure iso8859-1 displays with accentless ascii fallbacks, for people who insist on using quake's glyphs. 2021-08-19 07:21:19 +01:00
Shpoike aabf9b316d Fix confusion between the outside and explicit pvs (read: recursive portal rendering). 2021-08-19 07:21:19 +01:00
Shpoike c1e320116d nullarea stuff was inconsistent. This was breaking areaportals. 2021-08-19 07:21:19 +01:00
Shpoike ff9495fcf7 Try to improve hl2bsp light intensities to better match hl2. favour ldr lightmap textures, as we overbright too much otherwise. 2021-08-19 07:21:19 +01:00
Shpoike 5392900887 Fix hl2bsp static props with r_ignoreentpvs 0. 2021-08-19 07:21:19 +01:00
Shpoike 42148878aa Fix alpha stuff in vmt materials. 2021-08-19 07:21:19 +01:00
Shpoike 5ab71f6b01 Enable more bloatware. 2021-08-19 07:21:19 +01:00
Shpoike e3b37db8bc fix typo in comment. 2021-08-19 07:21:19 +01:00
Shpoike f918b3c9c8 make sure lightmap textures have the right image format shown. 2021-08-19 07:21:19 +01:00
Shpoike e09f707067 Defective/buggy/limited support for hl2 models. 2021-08-19 07:21:19 +01:00
Shpoike bac71b8d58 Avoid mutex deadlock in an error path. 2021-08-19 07:21:19 +01:00
Shpoike 84313ce213 Basic parsing of hl2bsp static props. 2021-08-19 07:21:19 +01:00
Shpoike 76d232b007 Fix possible crash due to hl2bsp support. 2021-08-19 07:21:19 +01:00
Shpoike 7612446a59 Fix up blackslashes in zips on load, so FSZIP_FLocate won't fail because of it. 2021-08-19 07:21:19 +01:00
Shpoike 7ca893c3e1 Fix up our VFS pipe logic to handle larger initial blobs properly. 2021-08-19 07:21:19 +01:00
Shpoike 6f82d0fd8b Add support for hl2bsps's zip-inside-bsp lump... 2021-08-19 07:21:19 +01:00
Shpoike 586a92ec47 Try to make sense of hl2 materials. 2021-08-19 07:21:19 +01:00
Shpoike 6658565956 Try to handle hl2bsp's area portals. 2021-08-19 07:21:19 +01:00
Shpoike e470cc5033 Added displacement support for HL2BSPs. 2021-08-19 07:21:19 +01:00
Shpoike 955e9d3fb6 Basic hl2bsp support. 2021-08-19 07:21:18 +01:00
Shpoike 3e81fdef8a Update and enable our VTF loader. 2021-08-19 07:21:18 +01:00
Shpoike e1a0f5fa4e Fix vpk support. 2021-08-19 07:21:18 +01:00
51 changed files with 4440 additions and 211 deletions

View File

@ -907,6 +907,7 @@ COMMON_OBJS = \
fs_stdio.o \
fs_pak.o \
fs_zip.o \
fs_vpk.o \
fs_dzip.o \
fs_xz.o \
m_download.o \

View File

@ -3297,6 +3297,7 @@ void CL_ClearLerpEntsParticleState(void)
}
}
qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel);
void CL_LinkStaticEntities(void *pvs, int *areas)
{
int i;
@ -3401,6 +3402,73 @@ void CL_LinkStaticEntities(void *pvs, int *areas)
// FIXME: no effects on static ents
// CLQ1_AddPowerupShell(ent, false, stat->effects);
}
if (cl.worldmodel->numstaticents)
{
struct modelstaticent_s *sent;
entity_t *src;
float d;
vec3_t disp;
for (i = 0; i < cl.worldmodel->numstaticents; i++)
{
if (cl_numvisedicts == cl_maxvisedicts)
{
cl_expandvisents=true;
break;
}
sent = &cl.worldmodel->staticents[i];
src = &sent->ent;
if (sent->fademaxdist)
{
VectorSubtract(r_refdef.vieworg, src->origin, disp);
d = VectorLength(disp);
if (d > sent->fademaxdist)
continue; //skip it.
d -= sent->fademindist;
d /= sent->fademaxdist-sent->fademindist;
if (d < 0)
d = 0;
}
else
d = 0;
if (!src->model || src->model->loadstate != MLS_LOADED)
{
if (src->model && src->model->loadstate == MLS_NOTLOADED)
Mod_LoadModel(src->model, MLV_WARN); //we use threads, so these'll load in time.
continue;
}
/*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;
float r = src->model->radius;
VectorSet(absmin, -r,-r,-r);
VectorSet(absmax, r,r,r);
VectorAdd(absmin, src->origin, absmin);
VectorAdd(absmax, src->origin, absmax);
cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &src->pvscache, absmin, absmax);
}
ent = &cl_visedicts[cl_numvisedicts++];
*ent = *src;
ent->framestate.g[FS_REG].frametime[0] = cl.time;
ent->framestate.g[FS_REG].frametime[1] = cl.time;
if (d)
{
ent->shaderRGBAf[3] *= 1-d;
ent->flags |= RF_TRANSLUCENT;
}
}
}
}
//returns cos(angle)
@ -4004,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

@ -7240,10 +7240,10 @@ static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const ch
unsigned int numresources;
} *vtf;
fmtfmt_t vmffmt, lrfmt;
unsigned int bw, bh, bb;
unsigned int bw, bh, bd, bb;
qbyte *end = filedata + filesize;
unsigned int face, faces, frame, frames, miplevel, miplevels, img;
unsigned int w, h;
unsigned int faces, frame, frames, miplevel, miplevels, img;
unsigned int w, h, d = 1;
size_t datasize;
unsigned int version;
@ -7294,10 +7294,10 @@ static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const ch
filedata += vtf->headersize;
//and skip the low-res image too.
if (vtf->lowreswidth && vtf->lowresheight)
Image_BlockSizeForEncoding(ImageVTF_VtfToFTE(lrfmt), &bb, &bw, &bh);
Image_BlockSizeForEncoding(ImageVTF_VtfToFTE(lrfmt), &bb, &bw, &bh, &bd);
else
bb=bw=bh=1;
datasize = ((vtf->lowreswidth+bw-1)/bw) * ((vtf->lowresheight+bh-1)/bh) * bb;
bb=bw=bh=bd=1;
datasize = ((vtf->lowreswidth+bw-1)/bw) * ((vtf->lowresheight+bh-1)/bh) * ((1/*vtf->lowresdepth*/+bd-1)/bd) * bb;
filedata += datasize;
}
@ -7307,7 +7307,7 @@ static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const ch
mips->type = (vtf->flags & 0x4000)?PTI_CUBE:PTI_2D;
mips->encoding = ImageVTF_VtfToFTE(vmffmt);
Image_BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh);
Image_BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh, &bd);
miplevels = vtf->mipmapcount;
frames = 1;//vtf->numframes;
@ -7335,7 +7335,7 @@ static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const ch
w = 1;
if (!h)
h = 1;
datasize = ((w+bw-1)/bw) * ((h+bh-1)/bh) * bb;
datasize = ((w+bw-1)/bw) * ((h+bh-1)/bh) * ((d+bd-1)/bd) * bb;
for (frame = 0; frame < vtf->numframes; frame++)
{
if (miplevel < miplevels)

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)
{
@ -3984,7 +3984,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
w = (float)vid.width / shader->defaulttextures->base->width;
h = (float)(vid.height-y) / shader->defaulttextures->base->height;
h = min(w,h);
h = min(min(w,h), 1);
w = h*shader->defaulttextures->base->width;
h = h*shader->defaulttextures->base->height;
R2D_Image(0, y, w, h, 0, 0, 1, 1, shader);

View File

@ -168,6 +168,7 @@ enum mod_purge_e
};
enum mlverbosity_e
{
MLV_NOLOAD, //leave it notloaded.
MLV_SILENT,
MLV_WARN,
MLV_WARNSYNC,

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

@ -643,6 +643,25 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest,
{
switch(wmodel->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
for (i=0 ; i<size ; i++)
{
unsigned lm = ((unsigned int*)lightmap)[i];
intensity = max3(((lm>>0)&0xff),((lm>>8)&0xff),((lm>>16)&0xff)) * scale * pow(2, (signed char)(lm>>24));
blocknormals[i][0] += intensity*(deluxmap[i*3+0]-127);
blocknormals[i][1] += intensity*(deluxmap[i*3+1]-127);
blocknormals[i][2] += intensity*(deluxmap[i*3+2]-127);
}
lightmap += size*4; // skip to next lightmap
deluxmap += size*3;
}
break;
#endif
case LM_E5BGR9:
deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -1484,6 +1503,28 @@ static void Surf_BuildLightMap (model_t *model, msurface_t *surf, int map, int s
Sys_Error("Surf_BuildLightMap: q3bsp");
switch(model->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
if (scale)
{
VectorScale(cl_lightstyle[surf->styles[maps]].colours, scale, scalergb);
for (i=0 ; i<size ; i++)
{
unsigned int l = ((unsigned int*)src)[i];
float e = pow(2, (signed char)(l>>24));
blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0xff);
blocklights[i*3+1] += scalergb[1] * e * ((l>> 8)&0xff);
blocklights[i*3+2] += scalergb[2] * e * ((l>>16)&0xff);
}
}
src += size*4; // skip to next lightmap
}
break;
#endif
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
@ -1555,6 +1596,17 @@ static void Surf_BuildLightMap (model_t *model, msurface_t *surf, int map, int s
if (surf->dlightframe == r_dlightframecount)
Surf_AddDynamicLights_RGB (surf);
#ifdef HL2BSPS
if (model->fromgame == fg_halflife2)
for (i=0 ; i<size*3 ; i++)
{
int t = M_LinearToSRGB(blocklights[i], (256<<7)-1);
if (t < 0)
t = 0;
blocklights[i] = t;
}
#endif
Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm);
}
else
@ -1615,6 +1667,23 @@ static void Surf_BuildLightMap (model_t *model, msurface_t *surf, int map, int s
{
switch(model->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
for (i=0 ; i<size ; i++)
{
unsigned int lm = ((unsigned int *)src)[i];
blocklights[i] += max3(((lm>>0)&0xff),((lm>>8)&0xff),((lm>>16)&0xff)) * scale *
pow(2, (signed char)(lm>>24));
}
src += size*4; // skip to next lightmap
}
break;
#endif
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
@ -1658,6 +1727,16 @@ static void Surf_BuildLightMap (model_t *model, msurface_t *surf, int map, int s
Surf_AddDynamicLights_Lum (surf);
}
#ifdef HL2BSPS
if (model->fromgame == fg_halflife2)
for (i=0 ; i<size ; i++)
{
int t = M_LinearToSRGB(blocklights[i], (256<<7)-1);
if (t < 0)
t = 0;
blocklights[i] = t;
}
#endif
Surf_StoreLightmap_Lum(dest, blocklights, smax, tmax, shift, stainsrc, lm->width);
}
}
@ -1781,6 +1860,28 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
}
else switch(wmodel->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
if (scale)
{
VectorScale(cl_lightstyle[surf->styles[maps]].colours, scale, scalergb);
for (i=0 ; i<size ; i++)
{
unsigned int l = ((unsigned int*)src)[i];
float e = pow(2, (signed char)(l>>24));
blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0xff);
blocklights[i*3+1] += scalergb[1] * e * ((l>> 8)&0xff);
blocklights[i*3+2] += scalergb[2] * e * ((l>>16)&0xff);
}
}
src += size*4; // skip to next lightmap
}
break;
#endif
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
@ -1851,6 +1952,17 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
if (!r_stains.value || !surf->stained)
stainsrc = NULL;
#ifdef HL2BSPS
if (wmodel->fromgame == fg_halflife2)
for (i=0 ; i<size*3 ; i++)
{
int t = M_LinearToSRGB(blocklights[i], (256<<7)-1);
if (t < 0)
t = 0;
blocklights[i] = t;
}
#endif
Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm);
}
else
@ -1881,6 +1993,23 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
{
switch(wmodel->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
for (i=0 ; i<size ; i++)
{
unsigned int lm = ((unsigned int *)lightmap)[i];
blocklights[i] += max3(((lm>>0)&0x1ff),((lm>>9)&0x1ff),((lm>>18)&0x1ff)) * scale *
pow(2, (signed char)(lm>>24));
}
lightmap += size*4; // skip to next lightmap
}
break;
#endif
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
@ -1924,6 +2053,16 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
}
}
#ifdef HL2BSPS
if (wmodel->fromgame == fg_halflife2)
for (i=0 ; i<size ; i++)
{
int t = M_LinearToSRGB(blocklights[i], (256<<7)-1);
if (t < 0)
t = 0;
blocklights[i] = t;
}
#endif
Surf_StoreLightmap_Lum(dest, blocklights, smax, tmax, shift, stainsrc, lm->width);
}
@ -2441,6 +2580,117 @@ static void Surf_RecursiveQ2WorldNode (mnode_t *node)
}
#endif
#ifdef HL2BSPS
static void Surf_RecursiveHL2WorldNode (mnode_t *node)
{
int c, side;
mplane_t *plane;
msurface_t *surf, **mark;
mleaf_t *pleaf;
double dot;
int sidebit;
if (node->contents == Q2CONTENTS_SOLID)
return; // solid
if (node->visframe != r_visframecount)
return;
if (R_CullBox (node->minmaxs, node->minmaxs+3))
return;
// if a leaf node, draw stuff
if (node->contents != -1)
{
pleaf = (mleaf_t *)node;
// check for door connected areas
if (! (r_refdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
c = pleaf->cluster;
if (c >= 0)
frustumvis[c>>3] |= 1<<(c&7);
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if (c)
{
do
{
surf = *mark;
if (surf->flags & SURF_ONNODE)
surf->visframe = r_framecount;
else if (surf->visframe != r_framecount)
{
surf->visframe = r_framecount;
Surf_RenderDynamicLightmaps (surf);
surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh;
}
mark++;
} while (--c);
}
return;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node->plane;
switch (plane->type)
{
case PLANE_X:
dot = modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (modelorg, plane->normal) - plane->dist;
break;
}
if (dot >= 0)
{
side = 0;
sidebit = 0;
}
else
{
side = 1;
sidebit = SURF_PLANEBACK;
}
// recurse down the children, front side first
Surf_RecursiveHL2WorldNode (node->children[side]);
// draw stuff
for ( c = node->numsurfaces, surf = currentmodel->surfaces + node->firstsurface; c ; c--, surf++)
{
if (surf->visframe != r_framecount)
continue;
if ( (surf->flags & SURF_PLANEBACK) != sidebit )
continue; // wrong side
surf->visframe = 0;//r_framecount+1;//-1;
Surf_RenderDynamicLightmaps (surf);
surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh;
}
// recurse down the back side
Surf_RecursiveHL2WorldNode (node->children[!side]);
}
#endif
#ifdef Q3BSPS
#if 0
static void Surf_LeafWorldNode (void)
@ -2726,7 +2976,11 @@ void Surf_SetupFrame(void)
r_viewcluster2 = -1;
}
#if defined(Q2BSPS) || defined(Q3BSPS)
else if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
else if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3
#ifdef HL2BSPS
|| cl.worldmodel->fromgame == fg_halflife2
#endif
)
{
leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
r_viewarea = leaf->area;
@ -3513,7 +3767,11 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_REPLACE);
#if defined(Q2BSPS) || defined(Q3BSPS)
if (es->wmodel->fromgame == fg_quake2 || es->wmodel->fromgame == fg_quake3)
if (es->wmodel->fromgame == fg_quake2 || es->wmodel->fromgame == fg_quake3
#ifdef HL2BSPS
|| es->wmodel->fromgame == fg_halflife2
#endif
)
Surf_SimpleWorld_Q3BSP(es, pvs);
else
#endif
@ -3784,7 +4042,11 @@ void Surf_DrawWorld (void)
entvis = surfvis = NULL;
}
#if defined(Q2BSPS) || defined(Q3BSPS)
else if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3)
else if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3
#ifdef HL2BSPS
|| currentmodel->fromgame == fg_halflife2
#endif
)
{
pvsbuffer_t *vis = &surf_frustumvis[r_refdef.recurse];
if (vis->buffersize < currentmodel->pvsbytes)
@ -3808,6 +4070,43 @@ void Surf_DrawWorld (void)
}
else
#endif
#ifdef HL2BSPS
if (currentmodel->fromgame == fg_halflife2)
{
entvis = surfvis = R_MarkLeaves_Q2 ();
VectorCopy (r_refdef.vieworg, modelorg);
if (!surfvis)
{
size_t i;
msurface_t *surf;
for (i = 0; i < currentmodel->nummodelsurfaces; i++)
{
surf = &currentmodel->surfaces[i];
Surf_RenderDynamicLightmaps (surf);
surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh;
}
}
else
{
size_t i;
dispinfo_t *disp;
msurface_t *surf;
areas[0] = 1;
areas[1] = r_viewarea;
Surf_RecursiveHL2WorldNode (currentmodel->nodes);
for (i = 0; i < currentmodel->numdisplacements; i++)
{
disp = &currentmodel->displacements[i];
if (currentmodel->funcs.EdictInFatPVS(currentmodel, &disp->pvs, surfvis, areas))
{
surf = disp->surf;
Surf_RenderDynamicLightmaps (surf);
surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh;
}
}
}
}
#endif
#ifdef Q2BSPS
if (currentmodel->fromgame == fg_quake2)
{
@ -4055,6 +4354,12 @@ uploadfmt_t Surf_LightmapMode(model_t *model)
{
switch (model->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8:
//hdr SHOULD be true, but that doesn't match hl2, and there's a few areas with lightmaps that are set FAR too bright.
rgb = true;
break;
#endif
case LM_E5BGR9:
hdr = rgb = true;
break;

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

@ -2759,14 +2759,14 @@ qbyte *R_MarkLeaves_Q2 (void)
vis = cvis[portal] = r_refdef.forcedvis;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
r_oldviewcluster2 = -2;
}
else
{
vis = cvis[portal];
if (!portal)
{
if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2)
if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2 && vis)
return vis;
r_oldviewcluster = r_viewcluster;
@ -2775,7 +2775,7 @@ qbyte *R_MarkLeaves_Q2 (void)
else
{
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
r_oldviewcluster2 = -2;
}
if (r_novis.ival == 2)
@ -2784,6 +2784,7 @@ qbyte *R_MarkLeaves_Q2 (void)
if (r_novis.ival || r_viewcluster == -1 || !cl.worldmodel->vis)
{
// mark everything
r_visframecount++;
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
cl.worldmodel->leafs[i].visframe = r_visframecount;
for (i=0 ; i<cl.worldmodel->numnodes ; i++)

View File

@ -240,8 +240,13 @@ void Draw_FunStringWidthFont(struct font_s *font, float x, float y, const void *
w = Font_Decode(w, &codeflags, &codepoint);
fw += Font_CharWidth(codeflags, codepoint);
}
if (rightalign == 2)
{
if (rightalign == 3)
{ //center the text (ignoring width info)
px -= fw/2;
width = fw;
}
else if (rightalign == 2)
{ //center the text (left align when too long)
if (fw < width)
{
px += (width-fw)/2;
@ -249,7 +254,7 @@ void Draw_FunStringWidthFont(struct font_s *font, float x, float y, const void *
}
}
else
{
{ //right align the text if shorter than specified width..
px += width;
if (fw > width)
fw = width;

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

@ -2051,7 +2051,7 @@ void R_DrawNameTags(void)
if (body)
{
// Q_snprintfz(fname, sizeof(fname), "<default shader>");
str = va("^2%s^7\n%s%s\n{%s\n", fname, ruleset_allow_shaders.ival?"":CON_ERROR"WARNING: ruleset_allow_shaders disables external shaders"CON_DEFAULT"\n", surf->texinfo->texture->name, body);
str = va("^2%s^7\n%s%s\n{\n%s\n", fname, ruleset_allow_shaders.ival?"":CON_ERROR"WARNING: ruleset_allow_shaders disables external shaders"CON_DEFAULT"\n", surf->texinfo->texture->name, ((*body=='\n')?body+1:body));
Z_Free(body);
}
else
@ -2127,6 +2127,54 @@ void R_DrawNameTags(void)
}
}
}
for (i=0 ; i<cl.num_statics ; i++)
{
entity_t *state = &cl_static_entities[i].ent;
mod = state->model;
if (mod && mod->loadstate == MLS_LOADED)
VectorInterpolate(mod->mins, 0.5, mod->maxs, org);
else
VectorClear(org);
VectorAdd(org, state->origin, org);
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
{
char *entstr;
int x, y;
entstr = state->model->name;
if (entstr)
{
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
Draw_FunStringWidth(x, y, entstr, 0, 3, false);
}
}
}
for (i=0 ; i<cl.worldmodel->numstaticents; i++)
{
struct modelstaticent_s *state = &cl.worldmodel->staticents[i];
mod = state->ent.model;
if (mod && mod->loadstate == MLS_LOADED)
VectorInterpolate(mod->mins, 0.5, mod->maxs, org);
else
VectorClear(org);
VectorAdd(org, state->ent.origin, org);
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
{
char *entstr;
int x, y;
entstr = mod->name;
if (entstr)
{
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
Draw_FunStringWidth(x, y, entstr, 0, 3, false);
}
}
}
}
#ifdef Q2SERVER //not enough fields for it to really be worth it.
if (w == &sv.world && svs.gametype == GT_QUAKE2 && ge)

View File

@ -458,7 +458,7 @@ typedef struct
{
int ident;
int version;
lump_t lumps[50];
lump_t lumps[64];
} q2dheader_t;
typedef struct
@ -604,6 +604,42 @@ typedef struct
#define Q3CONTENTS_TRIGGER 0x40000000
#define Q3CONTENTS_NODROP FTECONTENTS_SKY //0x80000000
#ifdef HL2BSPS
//this is more for documentation, hence why the q2 values where the match
#define HL2CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001
#define HL2CONTENTS_WINDOW Q2CONTENTS_WINDOW //0x00000002
#define HL2CONTENTS_AUX Q2CONTENTS_AUX //0x00000004
#define HL2CONTENTS_GRATE /*FTECONTENTS_LAVA*/ 0x00000008 //Surprise...
#define HL2CONTENTS_SLIME FTECONTENTS_SLIME //0x00000010
#define HL2CONTENTS_WATER FTECONTENTS_WATER //0x00000020
#define HL2CONTENTS_MIST Q2CONTENTS_MIST //0x00000040
#define HL2CONTENTS_OPAQUE 0x00000080
#define HL2CONTENTS_TESTFOGVOLUME 0x00000100
//0x00000200
//0x00000400
#define HL2CONTENTS_TEAM1 0x00000800
#define HL2CONTENTS_TEAM2 0x00001000
#define HL2CONTENTS_IGNORE_NODRAW_OPAQUE 0x00002000
#define HL2CONTENTS_MOVEABLE /*FTECONTENTS_LADDER*/ 0x00004000
#define HL2CONTENTS_AREAPORTAL Q2CONTENTS_AREAPORTAL //0x00008000
#define HL2CONTENTS_PLAYERCLIP FTECONTENTS_PLAYERCLIP //0x00010000
#define HL2CONTENTS_MONSTERCLIP FTECONTENTS_MONSTERCLIP //0x00020000
#define HL2CONTENTS_CURRENT_0 Q2CONTENTS_CURRENT_0 //0x00040000
#define HL2CONTENTS_CURRENT_90 Q2CONTENTS_CURRENT_90 //0x00080000
#define HL2CONTENTS_CURRENT_180 Q2CONTENTS_CURRENT_180 //0x00100000
#define HL2CONTENTS_CURRENT_270 Q2CONTENTS_CURRENT_270 //0x00200000
#define HL2CONTENTS_CURRENT_UP Q2CONTENTS_CURRENT_UP //0x00400000
#define HL2CONTENTS_CURRENT_DWN Q2CONTENTS_CURRENT_DOWN //0x00800000
#define HL2CONTENTS_ORIGIN Q2CONTENTS_ORIGIN //0x01000000 // removed before bsping an entity
#define HL2CONTENTS_MONSTER FTECONTENTS_BODY //0x02000000 // should never be on a brush, only in game
#define HL2CONTENTS_DEADMONSTER FTECONTENTS_CORPSE //0x04000000
#define HL2CONTENTS_DETAIL Q2CONTENTS_DETAIL //0x08000000 // brushes to be added after vis leafs
#define HL2CONTENTS_TRANSLUCENT Q2CONTENTS_TRANSLUCENT //0x10000000 // auto set if any surface has trans
#define HL2CONTENTS_LADDER Q2CONTENTS_LADDER //0x20000000
#define HL2CONTENTS_HITBOX 0x40000000
/*FTECONTENTS_SKY*/ //0x80000000
#endif
//qc compat only. not used internally.
#define DPCONTENTS_SOLID 1 // hit a bmodel, not a bounding box
#define DPCONTENTS_WATER 2

View File

@ -13,6 +13,7 @@ typedef struct
{
mplane_t *plane;
q2mapsurface_t *surface;
struct dispinfo_s *dispinfo;
} q2cbrushside_t;
typedef struct q2cbrush_s
{

View File

@ -1739,7 +1739,11 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
mesh->snormals_array = meshcache.anorms;
mesh->tnormals_array = meshcache.anormt;
if (vbop)
{
*vbop = meshcache.vbop;
meshcache.vbo.indicies = inf->vboindicies;
meshcache.vbo.indexcount = inf->numindexes;
}
#ifndef SKELETALMODELS
return false;
@ -2732,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

@ -54,7 +54,7 @@
#define PACKAGE_PK3 //aka zips. we support utf8,zip64,spans,weakcrypto,(deflate),(bzip2),symlinks. we do not support strongcrypto nor any of the other compression schemes.
#define PACKAGE_Q1PAK //also q2
//#define PACKAGE_DOOMWAD //doom wad support (generates various file names, and adds support for doom's audio, sprites, etc)
//#define PACKAGE_VPK //hl2 packages
#define PACKAGE_VPK //HalfLife2's packages
#define AVAIL_XZDEC //.xz decompression
#define AVAIL_GZDEC //.gz decompression
#define AVAIL_ZLIB //whether pk3s can be compressed or not.
@ -65,6 +65,7 @@
#define Q1BSPS //Quake1
#define Q2BSPS //Quake2
#define Q3BSPS //Quake3, as well as a load of other games too...
#define HL2BSPS //HalfLife2 map compat.
#define RFBSPS //qfusion's bsp format / jk2o etc.
#define TERRAIN //FTE's terrain, as well as .map support
//#define DOOMWADS //map support, filesystem support is separate.
@ -86,6 +87,7 @@
#define MODELFMT_MDX //kingpin's format (for hitboxes+geomsets).
#define MODELFMT_OBJ //lame mesh-only format that needs far too much processing and even lacks a proper magic identifier too
#define MODELFMT_GLTF //khronos 'transmission format'. .gltf or .glb extension. PBR. Version 2 only, for now.
#define MODELFMT_HL2 //HalfLife2 / Source models, or something.
#define RAGDOLL //ragdoll support. requires RBE support (via a plugin...).
//Image formats
@ -106,7 +108,7 @@
#define IMAGEFMT_BMP //windows bmp. yuck. also includes .ico for the luls
#define IMAGEFMT_PCX //paletted junk. required for qw player skins, q2 and a few old skyboxes.
#define IMAGEFMT_EXR //openexr, via Industrial Light & Magic's rgba api, giving half-float data.
//#define IMAGEFMT_VTF //hl2 image format
#define IMAGEFMT_VTF //HalfLife2's image format (you'll probably want the material format too)
#define AVAIL_PNGLIB //.png image format support (read+screenshots)
#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots)
//#define AVAIL_STBI //make use of Sean T. Barrett's lightweight public domain stb_image[_write] single-file-library, to avoid libpng/libjpeg dependancies.
@ -117,6 +119,7 @@
#define DECOMPRESS_RGTC //bc4+bc5
#define DECOMPRESS_BPTC //bc6+bc7
#define DECOMPRESS_ASTC //ASTC, for drivers that don't support it properly.
#define MATERIAL_VMT //attempt to parse halflife2's vmt files.
// Game/Gamecode Support
#define CSQC_DAT

View File

@ -90,7 +90,7 @@ static void QDECL FSVPK_ClosePath(searchpathfuncs_t *handle)
for (i = 0; i < pak->numfragments; i++)
{
if (pak->fragments[i])
pak->fragments[i]->Close(pak->fragments[i]);
pak->fragments[i]->pub.ClosePath(&pak->fragments[i]->pub);
pak->fragments[i] = NULL;
}
Z_Free(pak->fragments);
@ -188,27 +188,34 @@ typedef struct {
static int QDECL VFSVPK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread)
{
vfsvpk_t *vfsp = (void*)vfs;
int read;
int read, preread;
if (bytestoread <= 0)
return 0;
if (vfsp->currentpos < vfsp->preloadsize)
{
read = bytestoread;
if (read > vfsp->preloadsize-vfsp->currentpos)
read = vfsp->preloadsize-vfsp->currentpos;
memcpy(buffer, vfsp->preloaddata, read);
vfsp->currentpos += read;
if (read == bytestoread)
return read; //we're done, no need to seek etc
bytestoread -= read;
preread = bytestoread;
if (preread > vfsp->preloadsize-vfsp->currentpos)
preread = vfsp->preloadsize-vfsp->currentpos;
if (preread < 0)
return -1; //erk...
memcpy(buffer, vfsp->preloaddata+vfsp->currentpos, preread);
vfsp->currentpos += preread;
if (preread == bytestoread)
return preread; //we're done, no need to seek etc
bytestoread -= preread;
buffer = (char*)buffer+preread;
}
else
preread = 0;
if (vfsp->currentpos-vfsp->preloadsize + bytestoread > vfsp->length)
bytestoread = vfsp->length - (vfsp->currentpos-vfsp->preloadsize);
if (vfsp->currentpos + bytestoread > vfsp->length)
bytestoread = vfsp->length - vfsp->currentpos;
if (bytestoread <= 0)
{
if (preread)
return preread;
return -1;
}
@ -218,12 +225,17 @@ static int QDECL VFSVPK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int byte
VFS_SEEK(vfsp->parentpak->handle, vfsp->startpos+vfsp->currentpos-vfsp->preloadsize);
read = VFS_READ(vfsp->parentpak->handle, buffer, bytestoread);
if (read > 0)
{
vfsp->currentpos += read;
read += preread;
}
else if (preread)
read = preread;
vfsp->parentpak->filepos = vfsp->startpos+vfsp->currentpos-vfsp->preloadsize;
Sys_UnlockMutex(vfsp->parentpak->mutex);
}
else
read = 0;
read = preread;
return read;
}
@ -237,14 +249,14 @@ static qboolean QDECL VFSVPK_Seek (struct vfsfile_s *vfs, qofs_t pos)
vfsvpk_t *vfsp = (void*)vfs;
if (pos > vfsp->length)
return false;
vfsp->currentpos = pos + vfsp->startpos;
vfsp->currentpos = pos;// + vfsp->startpos;
return true;
}
static qofs_t QDECL VFSVPK_Tell (struct vfsfile_s *vfs)
{
vfsvpk_t *vfsp = (void*)vfs;
return vfsp->currentpos - vfsp->startpos;
return vfsp->currentpos;// - vfsp->startpos;
}
static qofs_t QDECL VFSVPK_GetLen (struct vfsfile_s *vfs)
{
@ -293,7 +305,7 @@ static vfsfile_t *QDECL FSVPK_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
#ifdef _DEBUG
{
mpackfile_t *pf = loc->fhandle;
mvpkfile_t *pf = loc->fhandle;
Q_strncpyz(vfs->funcs.dbgname, pf->name, sizeof(vfs->funcs.dbgname));
}
#endif
@ -430,8 +442,8 @@ searchpathfuncs_t *QDECL FSVPK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
i = LittleLong(header.version);
if (i == 2)
;//VFS_SEEK(packhandle, 7*sizeof(int));
// else if (i == 1)
// VFS_SEEK(packhandle, 3*sizeof(int));
else if (i == 1)
VFS_SEEK(packhandle, 3*sizeof(int));
else
{
Con_Printf("vpk %s is version %x (unspported)\n", desc, i);

View File

@ -1830,7 +1830,7 @@ unsigned short ibmtounicode[256] =
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, //0x20(ascii)
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, //0x30(ascii)
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, //0x40(ascii)
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, //0x50(ascii)
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B, '/',0x005D,0x005E,0x005F, //0x50(ascii)
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, //0x60(ascii)
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x2302, //0x70(mostly ascii, one display-only)
0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7,0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5, //0x80(non-ascii, printable)
@ -1871,9 +1871,11 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
//copy out the filename and lowercase it
if (entry.gflags & (1u<<11))
{ //already utf-8 encoding
unsigned short i;
if (entry.fnane_len > sizeof(f->name)-1)
entry.fnane_len = sizeof(f->name)-1;
memcpy(f->name, entry.fname, entry.fnane_len);
for (i = 0; i < entry.fnane_len; i++)
f->name[i] = (entry.fname[i]=='\\')?'/':entry.fname[i];
f->name[entry.fnane_len] = 0;
}
else
@ -1889,7 +1891,6 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
nlen += cl;
}
f->name[nlen] = 0;
}
if (prefix && *prefix)

File diff suppressed because it is too large Load Diff

View File

@ -165,7 +165,7 @@ void *Sys_CreateMutexNamed(char *file, int line);
#endif
#else
#ifdef __GNUC__ //gcc complains about if (true) when these are maros. msvc complains about static not being called in headers. gah.
#ifdef __GNUC__ //gcc complains about if (true) when these are macros. msvc complains about static not being called in headers. gah.
static inline qboolean Sys_MutexStub(void) {return qtrue;}
static inline void *Sys_CreateMutex(void) {return NULL;}
#define Sys_IsMainThread() Sys_MutexStub()

View File

@ -27,13 +27,6 @@ typedef struct plane_s
float dist;
} plane_t;
typedef struct csurface_s
{
char name[16];
int flags;
int value;
} q2csurface_t;
typedef struct cplane_s
{
vec3_t normal;

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
@ -5597,6 +5621,7 @@ void GLBE_UpdateLightmaps(void)
else
{
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
lm->lightmap_texture->format = lm->fmt;
if (lm->pbo_handle)
{
qglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, lm->pbo_handle);

View File

@ -1484,54 +1484,57 @@ static struct charcache_s *Font_GetChar(font_t *f, unsigned int codepoint)
//not cached, can't get.
c = Font_TryLoadGlyph(f, charidx);
if (!c && charidx >= 0x400 && charidx <= 0x45f)
{ //apparently there's a lot of russian players out there.
//if we just replace all their chars with a '?', they're gonna get pissed.
//so lets at least attempt to provide some default mapping that makes sense even if they don't have a full font.
//koi8-u is a mapping useful with 7-bit email because the message is still vaugely readable in latin if the high bits get truncated.
//not being a language specialist, I'm just going to use that mapping, with the high bit truncated to ascii (which mostly exists in the quake charset).
//this exact table is from ezquake. because I'm too lazy to figure out the proper mapping. (beware of triglyphs)
static char *wc2koi_table =
"?3??4?67??" "??" "??" ">?" //400
"abwgdevzijklmnop" //410
"rstufhc~{}/yx|`q" //420
"ABWGDEVZIJKLMNOP" //430
"RSTUFHC^[]_YX\\@Q" //440
"?#??$?&'??" "??" "??.?"; //450
charidx = wc2koi_table[charidx - 0x400];
if (charidx != '?')
{
c = Font_GetCharIfLoaded(f, charidx);
if (!c)
c = Font_TryLoadGlyph(f, charidx);
if (!c)
{
CHARIDXTYPE nc;
if (charidx >= 0xA0 && charidx <= 0x17F)
{ //latin-1 glyphs can mostly just drop their accents.
//should give a better fallback when people don't have these glyphs defined.
static char *latinfallback_table =
" !c###|S@c?<@-R@" //A0
"@@@@'u@.,@@>@@@?" //B0
"AAAAAAECEEEEIIII" //C0
"DNOOOOO*OUUUUYYs" //D0
"aaaaaaeceeeeiiii" //E0
"onooooo/ouuuuyyy" //F0
"AaAaAaCcCcCcCcDd" //100
"DdEeEeEeEeEeGgGg" //110
"GgGgHhHhIiIiIiIi" //120
"IiIiJjKkkLlLlLlL" //130
"lllNnNnNnnNnOoOo" //140
"OoEeRrRrRrSsSsSs" //150
"SsTtTtTtUuUuUuUu" //160
"UuUuWwYyYZzZzZzf"; //170
nc = latinfallback_table[charidx - 0xA0];
if (nc != '@')
{
c = Font_GetCharIfLoaded(f, nc);
if (!c)
c = Font_TryLoadGlyph(f, nc);
}
}
}
if (!c && charidx >= 0xA0 && charidx <= 0x17F)
{ //try to make sense of iso8859-1
//(mostly for zerstorer's o-umlout...)
static char *latin_table =
" ?c###|S?c?<??R?" //A0
"??""??""'u?.,??"">??""??" //B0
"AAAAAAECEEEEIIII" //C0
"DNOOOOO*OUUUUYYs" //D0
"aaaaaaeceeeeiiii" //E0
"onooooo/ouuuuyyy" //F0
"AaAaAaCcCcCcCcDd" //100
"DdEeEeEeEeEeGgGg" //110
"GgGgHhHhIiIiIiIi" //120
"IiIiJjKkkLlLlLlL" //130
"lllNnNnNnnNnOoOo" //140
"OoEeRrRrRrSsSsSs" //150
"SsTtTtTtUuUuUuUu" //160
"UuUuWwYyYZzZzZzf"; //170
charidx = latin_table[charidx - 0xA0];
if (charidx != '?')
{
c = Font_GetCharIfLoaded(f, charidx);
if (!c)
c = Font_TryLoadGlyph(f, charidx);
else if (charidx >= 0x400 && charidx <= 0x45f)
{ //apparently there's a lot of russian players out there.
//if we just replace all their chars with a '?', they're gonna get pissed.
//so lets at least attempt to provide some default mapping that makes sense even if they don't have a full font.
//koi8-u is a mapping useful with 7-bit email because the message is still vaugely readable in latin if the high bits get truncated.
//not being a language specialist, I'm just going to use that mapping, with the high bit truncated to ascii (which mostly exists in the quake charset).
//this exact table is from ezquake. because I'm too lazy to figure out the proper mapping. (beware of triglyphs)
static qbyte *wc2koi_table =
"?3??4?67??" "??" "??" ">?"
"abwgdevzijklmnop"
"rstufhc~{}/yx|`q"
"ABWGDEVZIJKLMNOP"
"RSTUFHC^[]_YX\\@Q"
"?#??$?&'??" "??" "??.?";
nc = wc2koi_table[charidx - 0x400];
if (nc != '?')
{
c = Font_GetCharIfLoaded(f, nc);
if (!c)
c = Font_TryLoadGlyph(f, nc);
}
}
}

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

@ -4,6 +4,578 @@
#include "shader.h"
#include "com_mesh.h"
#ifdef MODELFMT_HL2
/*
Half-Life 2 / Source models store much of their data in other files.
I'm only going to try loading simple static models, so we don't need much data from the .mdl itself.
FIXME: multiple meshes are still buggy.
FIXME: materials are not loaded properly.
FIXME: no lod stuff.
*/
typedef struct
{
unsigned int magic;
unsigned int version;
unsigned int revisionid;
char name[64];
unsigned int filesize;
vec3_t _80;
vec3_t _92;
vec3_t mins;
vec3_t maxs;
vec3_t _128;
vec3_t _140;
unsigned int _152;
unsigned int _156;
unsigned int _160;
unsigned int _164;
unsigned int _168;
unsigned int _172;
unsigned int _176;
unsigned int _180;
unsigned int _184;
unsigned int _188;
unsigned int _192;
unsigned int _196;
unsigned int _200;
unsigned int tex_count;
unsigned int tex_ofs;
unsigned int texpath_count;
unsigned int texpath_ofs;
unsigned int texbind_count; //N slots per skin
unsigned int skin_count;
unsigned int texbind_offset;//provides skin|slot->texture mappings
unsigned int body_count;
unsigned int body_ofs;
//other stuff?
} hl2mdlheader_t;
typedef struct
{
unsigned int name_ofs;
unsigned int surf_count;
unsigned int base;
unsigned int surf_ofs;
} hl2mdlbody_t;
typedef struct
{
char name[64];
unsigned int type;
unsigned int radius;
unsigned int mesh_count;
unsigned int mesh_ofs;
unsigned int vertex_count;
unsigned int _84;
unsigned int _88;
unsigned int _92;
unsigned int _96;
unsigned int _100;
unsigned int _104;
unsigned int _108;
unsigned int _112;
unsigned int _116;
unsigned int _120;
unsigned int _124;
unsigned int _128;
unsigned int _132;
unsigned int _136;
unsigned int _140;
unsigned int _144;
} hl2mdlsurf_t;
typedef struct
{
unsigned int mat_idx;
unsigned int model_ofs;
unsigned int vert_count;
unsigned int vert_first;
unsigned int _16;
unsigned int _20;
unsigned int _24;
unsigned int _28;
unsigned int _32;
unsigned int _36;
unsigned int _40;
unsigned int _44;
unsigned int _48;
unsigned int _52;
unsigned int _56;
unsigned int _60;
unsigned int _64;
unsigned int _68;
unsigned int _72;
unsigned int _76;
unsigned int _80;
unsigned int _84;
unsigned int _88;
unsigned int _92;
unsigned int _96;
unsigned int _100;
unsigned int _104;
unsigned int _108;
unsigned int _112;
} hl2mdlmesh_t;
typedef struct
{
unsigned int nameofs;
unsigned int _4;
unsigned int _8;
unsigned int _12;
unsigned int _16;
unsigned int _20;
unsigned int _24;
unsigned int _28;
unsigned int _32;
unsigned int _36;
unsigned int _40;
unsigned int _44;
unsigned int _48;
unsigned int _52;
unsigned int _56;
unsigned int _60;
} hl2mdltexture_t;
typedef struct
{
unsigned int nameofs;
} hl2mdltexturepath_t;
#pragma pack(push,1) //urgh wtf is this bullshit
typedef struct
{
unsigned int numskins;
unsigned int offsetskin;
} hl2vtxskins_t;
typedef struct
{
unsigned short foo;
//no padding
unsigned int offsetskinname;
} hl2vtxskin_t;
typedef struct
{
unsigned int version;
unsigned int vertcachesize;
unsigned short bonesperstrip;
unsigned short bonespertri;
unsigned int bonespervert;
unsigned int revisionid;
unsigned int lod_count;
unsigned int texreplacements_offset;
unsigned int body_count;
unsigned int body_ofs;
} hl2vtxheader_t;
typedef struct
{
unsigned int surf_count;
unsigned int surf_ofs;
} hl2vtxbody_t;
typedef struct
{
unsigned int lod_count;
unsigned int lod_ofs;
} hl2vtxsurf_t;
typedef struct
{
unsigned int mesh_count;
unsigned int mesh_ofs;
float dist;
} hl2vtxlod_t;
typedef struct
{
unsigned int stripg_count;
unsigned int stripg_ofs;
unsigned char flags;
//no padding (3 bytes)
} hl2vtxmesh_t;
typedef struct
{
unsigned int vert_count;
unsigned int vert_ofs;
unsigned int idx_count;
unsigned int idx_ofs;
unsigned int strip_count;
unsigned int strip_ofs;
unsigned char flags;
//no padding (3 bytes)
} hl2vtxstripg_t;
typedef struct
{
unsigned int idx_num;
unsigned int idx_ofs;
unsigned int vert_count;
unsigned int vert_ofs;
unsigned short bone_count;
unsigned char flags;
//no padding (1 byte)
unsigned int bonestate_count;
unsigned int bonestate_ofs;
} hl2vtxstrip_t;
typedef struct
{
qbyte bone[3];
qbyte bone_count;
unsigned short vert;
qbyte boneID[3];
//no padding
} hl2vtxvert_t;
typedef struct
{
unsigned int magic;
unsigned int version;
unsigned int revisionid;
unsigned int lod_count;
unsigned int lodverts_count[8];
unsigned int fixups_count;
unsigned int fixups_offset;
unsigned int verts_offset;
unsigned int tangents_offset;
} hl2vvdheader_t;
typedef struct
{
unsigned int lod;
unsigned int sourcevert;
unsigned int numverts;
} hl2vvdfixup_t;
typedef struct
{
float weight[3];
qbyte bone[3];
qbyte numbones;
vec3_t xyz;
vec3_t norm;
vec2_t st;
} hl2vvdvert_t;
#pragma pack(pop)
/*seriously, how many structs do you need?*/
typedef struct
{
model_t *mod;
unsigned numverts;
vec2_t *ofs_st_array;
vecV_t *ofs_skel_xyz;
vec3_t *ofs_skel_norm;
vec3_t *ofs_skel_svect;
vec3_t *ofs_skel_tvect;
// byte_vec4_t *ofs_skel_idx;
// vec4_t *ofs_skel_weight;
struct
{
unsigned int numfixups;
index_t *fixup;
} lod[1]; //must remain at 1 (instead of 8) until fixups are handled.
} hl2parsecontext_t;
static index_t *Mod_HL2_LoadIndexes(hl2parsecontext_t *ctx, unsigned int *idxcount, const hl2vtxmesh_t *vmesh, unsigned int lod, index_t firstindex)
{
size_t numidx = 0, g;
const hl2vtxstripg_t *vg;
index_t *idx, *ret = NULL;
vg = (const void*)((const qbyte*)vmesh+vmesh->stripg_ofs);
for (g = 0; g < vmesh->stripg_count; g++, vg++)
{
if (vg->idx_count%3)
{
*idxcount = 0;
return NULL;
}
numidx += vg->idx_count;
}
ret = idx = ZG_Malloc(&ctx->mod->memgroup, sizeof(*idx)*numidx);
vg = (const void*)((const qbyte*)vmesh+vmesh->stripg_ofs);
for (g = 0; g < vmesh->stripg_count; g++, vg++)
{
const unsigned short *in = (const void*)((const qbyte*)vg+vg->idx_ofs);
const unsigned short *e = in+vg->idx_count;
const hl2vtxvert_t *v = (const void*)((const qbyte*)vg+vg->vert_ofs);
if (ctx->lod[lod].numfixups)
{
index_t *fixup = ctx->lod[lod].fixup;
for(;;)
{
if (in == e)
break;
*idx++ = fixup[v[*in++].vert+firstindex];
}
}
else
{
for(;;)
{
if (in == e)
break;
*idx++ = v[*in++].vert+firstindex;
}
}
}
*idxcount = idx-ret;
return ret;
}
static qboolean Mod_HL2_LoadVTX(hl2parsecontext_t *ctx, const void *buffer, size_t fsize, unsigned int rev, const hl2mdlheader_t *mdl)
{ //horribly overcomplicated way to express this stuff.
size_t totalsurfs = 0, b, s, l, m;
const hl2vtxheader_t *header = buffer;
const hl2vtxbody_t *vbody;
const hl2vtxsurf_t *vsurf;
const hl2vtxlod_t *vlod;
const hl2vtxmesh_t *vmesh;
// const hl2vtxskins_t *vskins;
// const hl2vtxskin_t *vskin;
const hl2mdlbody_t *mbody = (const hl2mdlbody_t*)((const qbyte*)mdl + mdl->body_ofs);
galiasinfo_t *surf=NULL;
#ifdef HAVE_CLIENT
size_t t;
const hl2mdltexture_t *mtex = (const hl2mdltexture_t*)((const qbyte*)mdl + mdl->tex_ofs);
const unsigned short *skinbind;
galiasskin_t *skin;
skinframe_t *skinframe;
#endif
size_t firstvert = 0;
if (fsize < sizeof(*header) || header->version != 7 || header->revisionid != rev || header->body_count == 0)
return false;
vbody = (const void*)((const qbyte*)header + header->body_ofs);
for (b = 0; b < header->body_count; b++, vbody++)
{
vsurf = (const void*)((const qbyte*)vbody + vbody->surf_ofs);
for (s = 0; s < vbody->surf_count; s++, vsurf++)
{
vlod = (const void*)((const qbyte*)vsurf + vsurf->lod_ofs);
for (l = 0; l < min(vsurf->lod_count, countof(ctx->lod)); l++, vlod++)
totalsurfs += vlod->mesh_count;
}
}
if (!totalsurfs)
return false;
ctx->mod->meshinfo = surf = ZG_Malloc(&ctx->mod->memgroup, sizeof(*surf)*totalsurfs);
#ifdef HAVE_CLIENT
t = mdl->skin_count*mdl->texbind_count;
skinbind = (const unsigned short*)((const qbyte*)mdl+mdl->texbind_offset);
skin = ZG_Malloc(&ctx->mod->memgroup, sizeof(*skin)*t + sizeof(*skinframe)*t);
skinframe = (skinframe_t*)(skin+t);
for (s = 0; s < mdl->skin_count; s++)
for (t = 0; t < mdl->texbind_count; t++)
{
galiasskin_t *ns = &skin[s + t*mdl->skin_count];
Q_snprintfz(ns->name, sizeof(ns->name), "skin%u %u", (unsigned)s, (unsigned)t);
m = *skinbind++;
if (mdl->texpath_count)
{
const hl2mdltexturepath_t *mpath = (const hl2mdltexturepath_t*)((const qbyte*)mdl + mdl->texpath_ofs);
Q_strncpyz(skinframe->shadername, (const char*)mdl+mpath->nameofs, sizeof(skinframe->shadername));
}
else
{
COM_StripExtension((const char*)ctx->mod->name, skinframe->shadername, sizeof(skinframe->shadername));
Q_strncatz(skinframe->shadername, "/", sizeof(skinframe->shadername));
}
Q_strncatz(skinframe->shadername, (const char*)&mtex[m]+mtex[m].nameofs, sizeof(skinframe->shadername));
Q_strncatz(skinframe->shadername, ".vmt", sizeof(skinframe->shadername));
ns->numframes = 1; //no skingroups... not that kind anyway.
ns->skinspeed = 10;
ns->frame = skinframe;
skinframe++;
}
#endif
vbody = (const void*)((const qbyte*)header + header->body_ofs);
for (b = 0; b < header->body_count; b++, vbody++, mbody++)
{
const hl2mdlsurf_t *msurf = (const hl2mdlsurf_t*)((const qbyte*)mbody + mbody->surf_ofs);
vsurf = (const void*)((const qbyte*)vbody + vbody->surf_ofs);
for (s = 0; s < vbody->surf_count; s++, vsurf++, msurf++)
{
vlod = (const void*)((const qbyte*)vsurf + vsurf->lod_ofs);
// vskins = (const hl2vtxskins_t*)((const qbyte*)header + header->texreplacements_offset);
for (l = 0; l < min(vsurf->lod_count, countof(ctx->lod)); l++, vlod++/*, vskins++*/)
{
const hl2mdlmesh_t *mmesh = (const hl2mdlmesh_t*)((const qbyte*)msurf + msurf->mesh_ofs);
vmesh = (const void*)((const qbyte*)vlod + vlod->mesh_ofs);
for (m = 0; m < vlod->mesh_count; m++, vmesh++, mmesh++)
{
Q_snprintfz(surf->surfacename, sizeof(surf->surfacename), "%s:%s:l%u:m%u", (const char*)mbody+mbody->name_ofs, msurf->name, (unsigned)l, (unsigned)m);
/*animation info*/
surf->shares_bones = 0;
surf->numbones = 0;
surf->ofsbones = NULL; //no support for animations...
surf->numanimations = 0;
surf->ofsanimations = NULL; //we have no animation data
#ifndef SERVERONLY
/*skin data*/
surf->numskins = mdl->skin_count;
surf->ofsskins = skin+mmesh->mat_idx*mdl->skin_count;
/*vertdata*/
surf->ofs_rgbaf = NULL;
surf->ofs_rgbaub = NULL;
surf->ofs_st_array = ctx->ofs_st_array;
#endif
surf->shares_verts = 0;
surf->numverts = ctx->numverts;
surf->ofs_skel_xyz = ctx->ofs_skel_xyz;
surf->ofs_skel_norm = ctx->ofs_skel_norm;
surf->ofs_skel_svect = ctx->ofs_skel_svect;
surf->ofs_skel_tvect = ctx->ofs_skel_tvect;
//surf->ofs_skel_idx = ctx->ofs_skel_idx;
//surf->ofs_skel_weight = ctx->ofs_skel_weight;
/*index data*/
if (mmesh->vert_first+mmesh->vert_count > surf->numverts)
surf->ofs_indexes = NULL, surf->numindexes = 0; //erk?
else
surf->ofs_indexes = Mod_HL2_LoadIndexes(ctx, &surf->numindexes, vmesh, l, firstvert+mmesh->vert_first);
/*misc data*/
surf->geomset = 0;
surf->geomid = 0;
surf->contents = FTECONTENTS_BODY;
surf->csurface.flags = 0;
surf->surfaceid = 0;
surf->mindist = 0;
surf->maxdist = 0;
if (surf != ctx->mod->meshinfo)
surf[-1].nextsurf = surf;
surf->nextsurf = NULL;
surf++;
}
}
firstvert += msurf->vertex_count;
}
}
if (surf == ctx->mod->meshinfo)
return false;
return true;
}
static qboolean Mod_HL2_LoadVVD(hl2parsecontext_t *ctx, const void *buffer, size_t fsize, unsigned int rev)
{
const hl2vvdheader_t *header = buffer;
size_t lod;
const hl2vvdvert_t *in;
const vec4_t *it;
if (fsize < sizeof(*header) || header->magic != (('I'<<0)|('D'<<8)|('S'<<16)|('V'<<24)) || header->version != 4 || header->revisionid != rev || header->lodverts_count[0] == 0)
return false;
{
size_t v, numverts = ctx->numverts = header->lodverts_count[0];
vec2_t *st = ctx->ofs_st_array = ZG_Malloc(&ctx->mod->memgroup, sizeof(*st)*numverts);
vecV_t *xyz = ctx->ofs_skel_xyz = ZG_Malloc(&ctx->mod->memgroup, sizeof(*xyz)*numverts);
vec3_t *norm = ctx->ofs_skel_norm = ZG_Malloc(&ctx->mod->memgroup, sizeof(*norm)*numverts);
vec3_t *sdir = ctx->ofs_skel_svect = ZG_Malloc(&ctx->mod->memgroup, sizeof(*sdir)*numverts);
vec3_t *tdir = ctx->ofs_skel_tvect = ZG_Malloc(&ctx->mod->memgroup, sizeof(*tdir)*numverts);
// byte_vec4_t *bone = ctx->lod[lod].ofs_skel_idx = ZG_Malloc(&ctx->mod->memgroup, sizeof(*bone)*numverts);
// vec4_t *weight = ctx->lod[lod].ofs_skel_weight = ZG_Malloc(&ctx->mod->memgroup, sizeof(*weight)*numverts);
in = (const void*)((const char*)buffer+header->verts_offset);
it = (const void*)((const char*)buffer+header->tangents_offset);
for(v = 0; v < numverts; v++, in++, it++)
{
Vector2Copy(in->st, st[v]);
VectorCopy(in->xyz, xyz[v]);
VectorCopy(in->norm, norm[v]);
// VectorCopy(in->bone, bone[v]);
// bone[v][3] = bone[v][2]; //make sure its valid, and in cache.
// VectorCopy(in->weight, weight[v]);
// weight[v][3] = 0; //missing influences cannot influence.
//tangents are compacted, and for some reason in a different part of the file.
VectorCopy((*it), sdir[v]);
CrossProduct(in->norm, (*it), tdir[v]);
VectorScale(tdir[v], (*it)[3], tdir[v]);
}
}
if (header->fixups_count)
{
size_t fixups = header->fixups_count, f, v;
const hl2vvdfixup_t *fixup = (const hl2vvdfixup_t*)((const qbyte*)header+header->fixups_offset);
for (lod = 0; lod < countof(ctx->lod) && lod < header->lod_count; lod++)
{
size_t numverts;
for (numverts=0, f = 0; f < fixups; f++)
{
if (fixup[f].lod >= lod)
numverts += fixup[f].numverts;
}
if (numverts != header->lodverts_count[lod])
continue;
ctx->lod[lod].numfixups = numverts;
ctx->lod[lod].fixup = ZG_Malloc(&ctx->mod->memgroup, sizeof(index_t)*numverts);
for (numverts=0, f = 0; f < fixups; f++)
{
if (fixup[f].lod >= lod)
for (v = 0; v < fixup[f].numverts; v++)
ctx->lod[lod].fixup[numverts++] = fixup[f].sourcevert+v;
}
}
}
return true;
}
qboolean QDECL Mod_LoadHL2Model (model_t *mod, const void *buffer, size_t fsize)
{
hl2parsecontext_t ctx = {mod};
const hl2mdlheader_t *header = buffer;
void *vtx = NULL, *vvd = NULL;
size_t vtxsize = 0, vvdsize = 0;
char base[MAX_QPATH];
qboolean result;
size_t i;
const char *vtxpostfixes[] = {
".dx90.vtx",
".dx80.vtx",
".vtx",
".sw.vtx"
};
const char *vvdpostfixes[] = {
".vvd"
};
for (i = 0; !vtx && i < countof(vtxpostfixes); i++)
{
COM_StripExtension(mod->name, base, sizeof(base));
Q_strncatz(base, vtxpostfixes[i], sizeof(base));
vtx = FS_LoadMallocFile(base, &vtxsize);
}
for (i = 0; !vvd && i < countof(vvdpostfixes); i++)
{
COM_StripExtension(mod->name, base, sizeof(base));
Q_strncatz(base, vvdpostfixes[i], sizeof(base));
vvd = FS_LoadMallocFile(base, &vvdsize);
}
result = Mod_HL2_LoadVVD(&ctx, vvd, vvdsize, header->revisionid);
result &= Mod_HL2_LoadVTX(&ctx, vtx, vtxsize, header->revisionid, header);
FS_FreeFile(vvd);
FS_FreeFile(vtx);
VectorCopy(header->mins, mod->mins);
VectorCopy(header->maxs, mod->maxs);
mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
mod->type = mod_alias;
return result;
}
#endif
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Half-Life Model Renderer (Experimental) Copyright (C) 2001 James 'Ender' Brown [ender@quakesrc.org] This program is
@ -308,6 +880,17 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
hlmdl_bonecontroller_t *bonectls;
void *texmem = NULL;
header = buffer;
if (fsize < 8)
{
Con_Printf(CON_ERROR "%s - file is truncated\n", mod->name);
return false;
}
#ifdef MODELFMT_HL2
if (header->version >= 44 && header->version <= 49)
return Mod_LoadHL2Model(mod, buffer, fsize);
#endif
//load the model into hunk
model = ZG_Malloc(&mod->memgroup, sizeof(hlmodel_t));

View File

@ -683,6 +683,9 @@ void Mod_Init (qboolean initial)
Mod_RegisterModelFormatMagic(NULL, "Raven Map (bsp)", ('R'<<0)+('B'<<8)+('S'<<16)+('P'<<24), Mod_LoadQ2BrushModel);
Mod_RegisterModelFormatMagic(NULL, "QFusion Map (bsp)", ('F'<<0)+('B'<<8)+('S'<<16)+('P'<<24), Mod_LoadQ2BrushModel);
#endif
#ifdef HL2BSPS
Mod_RegisterModelFormatMagic(NULL, "HL2/'Source' Map (bsp)", ('V'<<0)+('B'<<8)+('S'<<16)+('P'<<24), Mod_LoadQ2BrushModel);
#endif
//doom maps
#ifdef MAP_DOOM
@ -774,7 +777,11 @@ mleaf_t *Mod_PointInLeaf (model_t *model, vec3_t p)
if (!model->nodes)
return NULL;
#if defined(Q2BSPS) || defined(Q3BSPS)
if (model->fromgame == fg_quake2 || model->fromgame == fg_quake3)
if (model->fromgame == fg_quake2 || model->fromgame == fg_quake3
#ifdef HL2BSPS
|| model->fromgame == fg_halflife2
#endif
)
{
return model->leafs + CM_PointLeafnum(model, p);
}
@ -859,9 +866,17 @@ model_t *Mod_FindName (const char *name)
{
#endif
if (mod_numknown == MAX_MOD_KNOWN)
{
Sys_UnlockMutex(com_resourcemutex);
Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
return NULL;
}
if (strlen(name) >= sizeof(mod->publicname))
{
Sys_UnlockMutex(com_resourcemutex);
Sys_Error ("model name is too long: %s", name);
return NULL;
}
memset(mod, 0, sizeof(model_t)); //clear the old model as the renderers use the same globals
Q_strncpyz (mod->publicname, name, sizeof(mod->publicname));
Q_strncpyz (mod->name, name, sizeof(mod->name));
@ -1052,6 +1067,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
}
#endif
if (a != MLS_LOADED)
switch(verbose)
{
default:
@ -1063,6 +1079,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
if (*mod->name != '*' && strcmp(mod->name, "null") && mod_warnmodels.ival && !previouslyfailed)
Con_Printf(CON_ERROR "Unable to load %s\n", mod->name);
break;
case MLV_NOLOAD: //shouldn't happen.
case MLV_SILENT:
break;
}
@ -1331,7 +1348,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
BZ_Free(buf);
COM_AddWork(WG_MAIN, Mod_ModelLoaded, mod, NULL, MLS_LOADED, 0);
COM_AddWork(WG_MAIN, Mod_ModelLoaded, mod, NULL, MLS_LOADED, verbose);
return;
}
@ -1349,7 +1366,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
{
if (mod->loadstate == MLS_NOTLOADED && *mod->name != '*')
if (mod->loadstate == MLS_NOTLOADED && *mod->name != '*' && verbose != MLV_NOLOAD)
{
mod->loadstate = MLS_LOADING;
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
@ -2401,8 +2418,57 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
mesh->colors4f_array[0] = (vec4_t*)(mesh->tnormals_array+mesh->numvertexes);
mesh->indexes = (index_t*)(mesh->colors4f_array[0]+mesh->numvertexes);
}
mesh->istrifan = true;
#ifdef HL2BSPS
if (surf->dispinfo)
{
dispinfo_t *d = surf->dispinfo;
struct dispvert_s *dv = d->verts;
memcpy(mesh->indexes, d->idx, sizeof(index_t)*d->numindexes);
//output the renderable verticies
for (i=0 ; i<mesh->numvertexes ; i++, dv++)
{
//xyz
VectorCopy (d->xyz[i], mesh->xyz_array[i]);
//st
mesh->st_array[i][0] = dv->st[0];
mesh->st_array[i][1] = dv->st[1];
if (surf->texinfo->texture->vwidth)
mesh->st_array[i][0] /= surf->texinfo->texture->vwidth;
if (surf->texinfo->texture->vheight)
mesh->st_array[i][1] /= surf->texinfo->texture->vheight;
//lmst
s = (float)(i%(d->width+1))/d->width;
t = (float)(i/(d->width+1))/d->height;
for (sty = 0; sty < 1; sty++)
{
mesh->lmst_array[sty][i][0] = (s*surf->extents[0] + surf->light_s[sty] + 0.5) / (mod->lightmaps.width);
mesh->lmst_array[sty][i][1] = (t*surf->extents[1] + surf->light_t[sty] + 0.5) / (mod->lightmaps.height);
}
//normals
VectorCopy(surf->plane->normal, mesh->normals_array[i]);
VectorCopy(surf->texinfo->vecs[0], mesh->snormals_array[i]);
VectorNegate(surf->texinfo->vecs[1], mesh->tnormals_array[i]);
//rgba
for (sty = 0; sty < 1; sty++)
{
mesh->colors4f_array[sty][i][0] = 1;
mesh->colors4f_array[sty][i][1] = 1;
mesh->colors4f_array[sty][i][2] = 1;
mesh->colors4f_array[sty][i][3] = ((int)dv->alpha&255)/255.0;
}
}
return;
}
#endif
mesh->istrifan = true;
//output the mesh's indicies
for (i=0 ; i<mesh->numvertexes-2 ; i++)
{
@ -2463,6 +2529,20 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
}
}
#ifdef HL2BSPS
if (mod->fromgame == fg_halflife2)
{
s = DotProduct (vec, surf->texinfo->lmvecs[0]) + surf->texinfo->lmvecs[0][3];
t = DotProduct (vec, surf->texinfo->lmvecs[1]) + surf->texinfo->lmvecs[1][3];
for (sty = 0; sty < 1; sty++)
{
mesh->lmst_array[sty][i][0] = (s - surf->texturemins[0] + surf->light_s[sty] + 0.5) / (mod->lightmaps.width);
mesh->lmst_array[sty][i][1] = (t - surf->texturemins[1] + surf->light_t[sty] + 0.5) / (mod->lightmaps.height);
}
}
#endif
//figure out the texture directions, for bumpmapping and stuff
if (mod->normals && (surf->texinfo->flags & 0x800) && (mod->normals[vertidx][0] || mod->normals[vertidx][1] || mod->normals[vertidx][2]))
{
@ -2820,6 +2900,9 @@ static int Mod_Batches_Generate(model_t *mod)
{
#ifdef Q2BSPS
case fg_quake2:
#ifdef HL2BSPS
case fg_halflife2:
#endif
batch->buildmeshes = Mod_UpdateBatchShader_Q2;
break;
#endif
@ -3142,6 +3225,13 @@ static void Mod_Batches_Build(model_t *mod, builddata_t *bd)
mesh = surf->mesh = &meshlist[i];
mesh->numvertexes = surf->numedges;
mesh->numindexes = (surf->numedges-2)*3;
#ifdef HL2BSPS
if (surf->dispinfo)
{
mesh->numvertexes = (surf->dispinfo->width+1)*(surf->dispinfo->height+1);
mesh->numindexes = surf->dispinfo->numindexes;
}
#endif
}
else
mesh = surf->mesh;
@ -4074,6 +4164,9 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m
switch(loadmodel->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8:
#endif
case LM_E5BGR9:
lofsscale = 4;
break;
@ -5022,7 +5115,12 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
else
#endif
#ifdef Q2BSPS
if (mod->fromgame == fg_quake2)
if (mod->fromgame == fg_quake2
#ifdef HL2BSPS
|| mod->fromgame == fg_halflife2
#endif
)
{
COM_FileBase (mod->name, loadname, sizeof(loadname));
for(a = 0; a < mod->numtextures; a++)

View File

@ -54,6 +54,13 @@ typedef enum {
SHADER_SORT_COUNT
} shadersort_t;
typedef struct csurface_s
{
char name[16];
int flags;
int value;
} q2csurface_t;
#ifdef FTE_TARGET_WEB
#define MAX_BONES 256
#elif defined(IQMTOOL)
@ -276,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);
@ -348,7 +355,7 @@ void GL_DeselectVAO(void);
typedef struct texture_s
{
char name[64];
char name[128];
unsigned vwidth, vheight; //used for lightmap coord generation
struct shader_s *shader;
@ -389,6 +396,9 @@ typedef struct
#define SURF_NOFLAT 0x08000
#define SURF_DRAWALPHA 0x10000
#define SURF_NODRAW 0x20000 //set on non-vertical halflife water submodel surfaces
#ifdef HL2BSPS
#define SURF_ONNODE 0x40000 //o.O
#endif
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
@ -403,8 +413,12 @@ typedef struct mtexinfo_s
texture_t *texture;
int flags;
#ifdef HL2BSPS
float lmvecs[2][4];
#endif
//it's a q2 thing.
int numframes;
// int numframes;
struct mtexinfo_s *next;
} mtexinfo_t;
@ -439,6 +453,31 @@ typedef struct
texid_t image;
} menvmap_t;
#ifdef HL2BSPS
typedef struct dispinfo_s
{
struct msurface_s *surf;
vec3_t aamin;
vec3_t aamax;
pvscache_t pvs; //which pvs clusters this displacement is visible in...
unsigned int contents;
unsigned int width;
unsigned int height;
vecV_t *xyz; //(width+1)*(height+1)
index_t *idx; //width*height*6;
size_t numindexes;
struct dispvert_s
{
vec3_t norm;
vec2_t st;
float alpha;
} *verts;
//unsigned short *flags;
q2csurface_t csurface; //collision info for q2 gamecode.
} dispinfo_t;
#endif
#define LMSHIFT_DEFAULT 4
typedef struct msurface_s
{
@ -460,6 +499,9 @@ typedef struct msurface_s
batch_t *sbatch;
mtexinfo_t *texinfo;
#ifdef HL2BSPS
dispinfo_t *dispinfo;
#endif
int visframe; // should be drawn when node is crossed
#ifdef RTLIGHTS
int shadowframe;
@ -594,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);
/*
@ -874,7 +916,12 @@ typedef struct {
//
typedef enum {mod_brush, mod_sprite, mod_alias, mod_dummy, mod_halflife, mod_heightmap} modtype_t;
typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom, fg_doom3} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps)
typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife,
#ifdef HL2BSPS
fg_halflife2, //these should probably be switched to bits, so that I can easily check multiple (and define to 0 to easily no-op code).
#endif
fg_new, fg_doom, fg_doom3} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps)
#define MF_ROCKET (1u<<0) // leave a trail
#define MF_GRENADE (1u<<1) // leave a trail
@ -1068,7 +1115,10 @@ typedef struct model_s
//internally, we still use integers for lighting, with .7 bits of extra precision.
LM_L8,
LM_RGB8,
LM_E5BGR9
LM_E5BGR9,
#ifdef HL2BSPS
LM_E8BGR8, //erk?
#endif
} fmt;
qboolean deluxemapping; //lightmaps are interleaved with deluxemap data (lightmap indicies should only be even values)
qboolean deluxemapping_modelspace; //deluxemaps are in modelspace - we need different glsl.
@ -1080,6 +1130,19 @@ typedef struct model_s
portal_t *portal;
unsigned int numportals;
#ifdef HL2BSPS
dispinfo_t *displacements;
unsigned int numdisplacements;
struct modelstaticent_s
{
float fademindist;
float fademaxdist;
vec3_t lightorg;
entity_t ent;
} *staticents;
size_t numstaticents;
#endif
modelfuncs_t funcs;
//
// additional model data
@ -1183,5 +1246,9 @@ qofs_t CM_ReadPortalState (model_t *mod, qbyte *ptr, qofs_t ptrsize);
#endif //Q2BSPS
#ifdef HL2BSPS
void CModHL2_DrawAreaPortals(model_t *mod);
#endif
void CategorizePlane ( mplane_t *plane );
void CalcSurfaceExtents (model_t *mod, msurface_t *s);

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)
@ -2543,6 +2545,21 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
switch(cl.worldmodel->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
unsigned int l = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]];
scale *= pow(2, (signed char)(l>>24));
r += max3(((l>> 0)&0xff), ((l>> 8)&0xff), ((l>>16)&0xff)) * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1)<<2;
}
break;
#endif
case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -2601,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;
}
@ -2637,7 +2654,11 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
float scale, overbright;
int maps;
if (mod->fromgame == fg_quake2)
if (mod->fromgame == fg_quake2
#ifdef HL2BSPS
|| mod->fromgame == fg_halflife2
#endif
)
{
if (node->contents != -1)
return NULL; // solid
@ -2681,8 +2702,18 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
#ifdef HL2BSPS
if (mod->fromgame == fg_halflife2)
{
s = DotProduct (mid, tex->lmvecs[0]) + tex->lmvecs[0][3];
t = DotProduct (mid, tex->lmvecs[1]) + tex->lmvecs[1][3];
}
else
#endif
{
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
}
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
@ -2714,6 +2745,34 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
{
switch(mod->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
deluxmap = ((surf->samples - mod->lightdata)>>2)*3 + mod->deluxdata;
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<4;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
//scale *= pow(2, (int)(lm>>27)-15-9+8);
scale *= pow(2, (signed char)(lm>>24));
l[0] += ((lm>> 0)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[0];
l[1] += ((lm>> 8)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[1];
l[2] += ((lm>>16)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[2];
l[3] += (deluxmap[0]-127)*scale;
l[4] += (deluxmap[1]-127)*scale;
l[5] += (deluxmap[2]-127)*scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1)<<2;
deluxmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1) * 3;
}
break;
#endif
case LM_E5BGR9:
deluxmap = ((surf->samples - mod->lightdata)>>2)*3 + mod->deluxdata;
@ -2792,6 +2851,25 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
{
switch(mod->lightmaps.fmt)
{
#ifdef HL2BSPS
case LM_E8BGR8: //FIXME
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{
unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
//scale *= pow(2, (int)(lm>>27)-15-9+8);
scale *= pow(2, (signed char)(lm>>24));
l[0] += ((lm>> 0)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[0];
l[1] += ((lm>> 8)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[1];
l[2] += ((lm>>16)&0xff) * scale * cl_lightstyle[surf->styles[maps]].colours[2];
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1)<<2;
}
break;
#endif
case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -2849,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;
@ -2873,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];
@ -2924,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

@ -726,6 +726,11 @@ static void R_RenderScene_Internal(void)
TRACE(("dbg: calling R_RenderDlights\n"));
R_RenderDlights ();
#ifdef HL2BSPS
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && cl.worldmodel && cl.worldmodel->fromgame == fg_halflife2)
CModHL2_DrawAreaPortals(cl.worldmodel);
#endif
if (r_refdef.recurse)
RQ_RenderBatch();
else

View File

@ -627,7 +627,10 @@ qboolean Shader_ParseSkySides (char *shadername, char *texturename, texid_t *ima
"%s_%s",
"%s%s",
"env/%s%s",
"gfx/env/%s%s"
"gfx/env/%s%s",
#ifdef HL2BSPS
"materials/skybox/%s%s",
#endif
};
if (*texturename == '$')
@ -663,7 +666,8 @@ qboolean Shader_ParseSkySides (char *shadername, char *texturename, texid_t *ima
}
if (!images[i]->width)
{
Con_Printf("Sky \"%s\" missing texture: %s\n", shadername, path);
if (allokay)
Con_Printf("Sky \"%s\" missing texture: [gfx/env/]%s%s\n", shadername, texturename, skyname_suffix[countof(skyname_suffix)-1][i]);
images[i] = missing_texture;
allokay = false;
}
@ -1357,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
@ -2336,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.
@ -2489,6 +2495,17 @@ static void Shader_HLSL11ProgramName (parsestate_t *ps, const char **ptr)
Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D11);
}
static void Shaderpass_BlendFunc (parsestate_t *ps, const char **ptr);
static void Shader_ProgBlendFunc (parsestate_t *ps, const char **ptr)
{
if (ps->s->prog)
{
ps->pass = ps->s->passes;
Shaderpass_BlendFunc(ps, ptr);
ps->pass = NULL;
}
}
static void Shader_ReflectCube(parsestate_t *ps, const char **ptr)
{
char *token = Shader_ParseSensString(ptr);
@ -2847,7 +2864,7 @@ static shaderkey_t shaderkeys[] =
{"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl
{"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d with embedded hlsl
{"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d with embedded hlsl
// {"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode.
{"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode.
// {"progmap", Shader_ProgMap, "fte"}, //avoids needing extra subpasses (actually just inserts an extra pass).
//dp compat
@ -7069,8 +7086,12 @@ void Shader_DefaultSkinShell(parsestate_t *ps, const char *shortname, const void
void Shader_Default2D(parsestate_t *ps, const char *shortname, const void *genargs)
{
shader_t *s = ps->s;
qboolean wrap;
if (Shader_ParseShader(ps, "default2d"))
return;
wrap = Com_FloatArgument(s->name, "WRAP", 4, 0);
if (sh_config.progs_supported && qrenderer != QR_DIRECT3D9
#ifdef HAVE_LEGACY
&& !dpcompat_nopremulpics.ival
@ -7080,35 +7101,35 @@ void Shader_Default2D(parsestate_t *ps, const char *shortname, const void *genar
//hexen2 needs premultiplied alpha to avoid looking ugly
//but that results in problems where things are drawn with alpha not 0, so scale vertex colour by alpha in the fragment program
Shader_DefaultScript(ps, shortname,
"{\n"
va("{\n"
"affine\n"
"nomipmaps\n"
"program default2d#PREMUL\n"
"{\n"
"clampmap $diffuse\n"
"%s $diffuse\n"
"blendfunc gl_one gl_one_minus_src_alpha\n"
"}\n"
"sort additive\n"
"}\n"
);
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP|IF_HIGHPRIORITY));
"}\n", (wrap?"map":"clampmap")
));
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|(wrap?0:IF_CLAMP)|IF_HIGHPRIORITY));
}
else
{
Shader_DefaultScript(ps, shortname,
"{\n"
va("{\n"
"affine\n"
"nomipmaps\n"
"{\n"
"clampmap $diffuse\n"
"%s $diffuse\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc gl_src_alpha gl_one_minus_src_alpha\n"
"}\n"
"sort additive\n"
"}\n"
);
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP|IF_HIGHPRIORITY));
"}\n", (wrap?"map":"clampmap")
));
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|(wrap?0:IF_CLAMP)|IF_HIGHPRIORITY));
}
}
void Shader_PolygonShader(struct shaderparsestate_s *ps, const char *shortname, const void *args)
@ -7276,6 +7297,457 @@ static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shader
}
}
#ifdef MATERIAL_VMT
typedef struct
{
char **savefile;
char *sourcefile;
char type[MAX_QPATH];
char normalmap[MAX_QPATH];
struct
{
char name[MAX_QPATH];
} tex[5];
char envmap[MAX_QPATH];
char envmapmask[MAX_QPATH];
char envfrombase;
char halflambert;
float alphatestref;
char *blendfunc;
qboolean alphatest;
qboolean culldisable;
qboolean ignorez;
char *replaceblock;
} vmtstate_t;
static qboolean VMT_ReadVMT(const char *materialname, vmtstate_t *st); //this is made more complicated on account of includes allowing recursion
static char *VMT_ParseBlock(const char *fname, vmtstate_t *st, char *line)
{ //assumes the open { was already parsed, but will parse the close.
char *replace = NULL;
com_tokentype_t ttype;
char key[MAX_OSPATH];
char value[MAX_OSPATH];
char *qmark;
qboolean cond;
for(;line;)
{
line = COM_ParseType(line, key, sizeof(key), &ttype);
if (ttype == TTP_RAWTOKEN && !strcmp(key, "}"))
break; //end-of-block
line = COM_ParseType(line, value, sizeof(value), &ttype);
if (ttype == TTP_RAWTOKEN && !strcmp(value, "{"))
{ //sub block. we don't go into details here.
if (!Q_strcasecmp(key, "replace"))
replace = line;
else
Con_DPrintf("%s: Unknown block \"%s\"\n", fname, key);
line = VMT_ParseBlock(fname, NULL, line);
continue;
}
while ((qmark = strchr(key, '?')))
{
*qmark++ = 0;
if (!Q_strcasecmp(key, "srgb"))
cond = !!(vid.flags & VID_SRGBAWARE);
else
{
Con_DPrintf("%s: Unknown vmt conditional \"%s\"\n", fname, key);
cond = false;
}
if (!cond)
{
*key = 0;
break;
}
else
memmove(key, qmark, strlen(qmark)+1);
}
if (!*key || !st)
;
else if (!Q_strcasecmp(key, "include"))
{
if (!VMT_ReadVMT(value, st))
return NULL;
}
else if (!Q_strcasecmp(key, "$basetexture") || !Q_strcasecmp(key, "$hdrbasetexture")) //fixme: hdr version should probably override the other. order matters.
Q_strncpyz(st->tex[0].name, value, sizeof(st->tex[0].name));
else if (!Q_strcasecmp(key, "$hdrcompressedtexture")) //named texture is R8G8B8E8 and needs to be decompressed manually... should probably just use e5bgr9 but we don't have a way to transcode it here.
;
else if (!Q_strcasecmp(key, "$basetexturetransform"))
;
else if (!Q_strcasecmp(key, "$bumpmap")) // same as normalmap ~eukara
{
Q_strncpyz(st->normalmap, value, sizeof(st->normalmap));
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
}
else if (!Q_strcasecmp(key, "$ssbump"))
;
else if (!Q_strcasecmp(key, "$ssbumpmathfix"))
;
else if (!Q_strcasecmp(key, "$basetexture2") || !strcmp(key, "$texture2"))
Q_strncpyz(st->tex[1].name, value, sizeof(st->tex[1].name));
else if (!Q_strcasecmp(key, "$basetexturetransform2"))
;
else if (!Q_strcasecmp(key, "$surfaceprop"))
;
else if (!Q_strcasecmp(key, "$ignorez"))
st->ignorez = !!atoi(value);
else if (!Q_strcasecmp(key, "$nocull") && (!strcmp(value, "1")||!strcmp(value, "0")))
st->culldisable = atoi(value);
else if (!Q_strcasecmp(key, "$alphatest") && (!strcmp(value, "1")||!strcmp(value, "0")))
st->alphatest = atoi(value);
else if (!Q_strcasecmp(key, "$alphatestreference"))
st->alphatestref = atof(value);
else if (!Q_strcasecmp(key, "$alphafunc"))
{
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
}
else if (!Q_strcasecmp(key, "$alpha"))
{
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
}
else if (!Q_strcasecmp(key, "$translucent"))
{
if (atoi(value))
st->blendfunc = "src_alpha one_minus_src_alpha\n";
}
else if (!Q_strcasecmp(key, "$additive"))
{
if (atoi(value))
st->blendfunc = "src_one one_minus_src_alpha\n";
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
}
else if (!Q_strcasecmp(key, "$halflambert"))
st->halflambert = 1;
else if (!Q_strcasecmp(key, "$color"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$vertexcolor"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$vertexalpha"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$decal"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$decalscale"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$decalsize"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$envmap"))
Q_strncpyz(st->envmap, value, sizeof(st->envmap));
else if (!Q_strcasecmp(key, "$envmapmask"))
Q_strncpyz(st->envmapmask, value, sizeof(st->envmapmask));
else if (!Q_strcasecmp(key, "$envmapcontrast"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$envmaptint"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$envmapsaturation"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$basealphaenvmapmask"))
st->envfrombase=1;
else if (!Q_strcasecmp(key, "$normalmapalphaenvmapmask"))
st->envfrombase=0;
else if (!Q_strcasecmp(key, "$crackmaterial"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$selfillum"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$selfillummask"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$selfillumtint"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$nofog"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$nomip"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$nodecal"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$detail"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$detailscale"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$detailtint"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$detailblendfactor"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$detailblendmode"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$surfaceprop2"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$AllowAlphaToCoverage"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$blendmodulatetexture"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
//water/reflection stuff
else if (!Q_strcasecmp(key, "$refracttinttexture"))
Q_strncpyz(st->tex[0].name, value, sizeof(st->tex[0].name));
else if (!Q_strcasecmp(key, "$refracttexture"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$refractamount"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$refracttint"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$reflecttexture"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$reflectamount"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$reflecttint"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$fresnelpower"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$minreflectivity"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$maxreflectivity"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$normalmap"))
{
Q_strncpyz(st->normalmap, value, sizeof(st->normalmap));
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
}
else if (!Q_strcasecmp(key, "$bumpframe"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$fogenable"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$fogcolor"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$fogstart"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$fogend"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$abovewater"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$underwateroverlay"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$reflectentities"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$scale"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$bottommaterial"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$scroll1"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (!Q_strcasecmp(key, "$scroll2"))
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
else if (*key == '%')
; //editor lines
else
Con_Printf("%s: Unknown field \"%s\"\n", fname, key);
}
if (replace)
VMT_ParseBlock(fname, st, replace);
return line;
}
static void Shader_GenerateFromVMT(parsestate_t *ps, vmtstate_t *st, const char *shortname)
{
size_t offset = 0;
char script[8192];
char *progargs = "";
if (!*st->tex[0].name) //fill in a default...
Q_strncpyz(st->tex[0].name, shortname, sizeof(st->tex[0].name));
if (st->alphatest)
progargs = "#MASK=0.5#MASKLT"; //alphamask has to be handled by glsl (when glsl is used)
Q_strlcatfz(script, &offset, sizeof(script), "\n");
if (!Q_strcasecmp(st->type, "WorldVertexTransition"))
{ //attempt to do terrain blending
Q_strncpyz(st->type, "vmt_transition#TWOWAY", sizeof(st->type));
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
Q_strlcatfz(script, &offset, sizeof(script), "\tuppermap \"%s%s.vtf\"\n", strcmp(st->tex[1].name, "materials/")?"materials/":"", st->tex[1].name);
}
else if (!Q_strcasecmp(st->type, "Decal"))
{
Q_strncpyz(st->type, "vmt_vertexlit", sizeof(st->type));
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
Q_strlcatfz(script, &offset, sizeof(script), "\tpolygonOffset 1\n");
}
else if (!Q_strcasecmp(st->type, "DecalModulate"))
{
Q_strlcatfz(script, &offset, sizeof(script),
"\t{\n"
"\t\tprogram \"vmt_vertexlit%s\"\n"
"\t\tblendFunc gl_dst_color gl_one_minus_src_alpha\n"
"\t}\n", progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
Q_strlcatfz(script, &offset, sizeof(script), "\tpolygonOffset 1\n");
}
else if (!Q_strcasecmp(st->type, "Water"))
{
Q_strlcatfz(script, &offset, sizeof(script),
"\t{\n"
"\t\tprogram \"vmt_water%s\"\n"
"\t\tmap $refraction\n"
"\t\tmap $reflection\n"
"\t}\n", progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
}
else if (!Q_strcasecmp(st->type, "Refract"))
{
Q_strlcatfz(script, &offset, sizeof(script),
"\t{\n"
"\t\tprogram \"vmt_refract%s\"\n"
"\t\tmap $refraction\n"
"\t}\n", progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
}
else if (!Q_strcasecmp(st->type, "VertexlitGeneric"))
{
if (*st->envmap && st->envfrombase)
{
if (st->halflambert)
Q_strncpyz(st->type, "vmt_vertexlit#ENVFROMBASE#HALFLAMBERT", sizeof(st->type));
else
Q_strncpyz(st->type, "vmt_vertexlit#ENVFROMBASE", sizeof(st->type));
}
else
{
if (st->halflambert)
Q_strncpyz(st->type, "vmt_vertexlit#HALFLAMBERT", sizeof(st->type));
else
Q_strncpyz(st->type, "vmt_vertexlit", sizeof(st->type));
}
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
if (*st->normalmap)
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
}
else if (!Q_strcasecmp(st->type, "LightmappedGeneric"))
{
/* reflectmask from diffuse map alpha */
if (*st->envmap && st->envfrombase)
Q_strncpyz(st->type, "vmt_lightmapped#ENVFROMBASE", sizeof(st->type));
else if (*st->envmap && *st->envmapmask) /* dedicated reflectmask */
Q_strncpyz(st->type, "vmt_lightmapped#ENVFROMMASK", sizeof(st->type));
else /* take from normalmap */
Q_strncpyz(st->type, "vmt_lightmapped", sizeof(st->type));
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
if (*st->normalmap)
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
}
else
{
/* render-target camera/monitor - eukara*/
if (!Q_strcasecmp(st->tex[0].name, "_rt_Camera"))
Q_strlcatfz(script, &offset, sizeof(script),
"\t{\n"
"\t\tmap $rt:base\n"
"\t}\n"/*, progargs*/);
else
{
/* the default should just be unlit, let's not make any assumptions - eukara*/
Q_strncpyz(st->type, "vmt_unlit", sizeof(st->type));
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
}
}
if (*st->envmapmask)
Q_strlcatfz(script, &offset, sizeof(script), "\treflectmask \"%s%s.vtf\"\n", strcmp(st->envmapmask, "materials/")?"materials/":"", st->envmapmask);
if (*st->envmap)
Q_strlcatfz(script, &offset, sizeof(script), "\treflectcube \"%s%s.vtf\"\n", strcmp(st->envmap, "materials/")?"materials/":"", st->envmap);
if (st->alphatest)
Q_strlcatfz(script, &offset, sizeof(script), "\talphatest ge128\n");
if (st->culldisable)
Q_strlcatfz(script, &offset, sizeof(script), "\tcull disable\n");
if (st->ignorez)
Q_strlcatfz(script, &offset, sizeof(script), "\tnodepth\n");
if (st->blendfunc)
Q_strlcatfz(script, &offset, sizeof(script), "\tprogblendfunc %s\n", st->blendfunc);
Q_strlcatfz(script, &offset, sizeof(script), "}\n");
Shader_Reset(ps->s);
Shader_ReadShader(ps, script, NULL);
if (st->sourcefile)
{ //cat the original file on there...
if (st->savefile)
{
char *winsucks; //strip any '\r' chars in there that like to show as ugly glyphs.
for (winsucks = st->sourcefile; *winsucks; winsucks++)
if (*winsucks=='\r')
*winsucks = ' ';
Z_StrCat(st->savefile, "\n/*\n");
Z_StrCat(st->savefile, st->sourcefile);
Z_StrCat(st->savefile, "*/");
}
BZ_Free(st->sourcefile);
}
}
static qboolean VMT_ReadVMT(const char *fname, vmtstate_t *st)
{
char *line, *file = NULL;
com_tokentype_t ttype;
char token[MAX_QPATH];
char *prefix="", *postfix="";
//don't dupe the mandatory materials/ prefix
if (strncmp(fname, "materials/", 10))
prefix = "materials/";
if (strcmp(COM_GetFileExtension(fname, NULL), ".vmt"))
postfix = ".vmt";
Q_snprintfz(token, sizeof(token), "%s%s%s", prefix, fname, postfix);
file = FS_LoadMallocFile(token, NULL);
if (file)
{
if (st->savefile)
{
if (st->sourcefile)
{
Z_StrCat(&st->sourcefile, fname);
Z_StrCat(&st->sourcefile, ":\n");
Z_StrCat(&st->sourcefile, file);
}
else
st->sourcefile = Z_StrDup(file);
}
line = file;
line = COM_ParseType(line, st->type, sizeof(st->type), &ttype);
line = COM_ParseType(line, token, sizeof(token), &ttype);
if (!strcmp(token, "{"))
{
line = VMT_ParseBlock(fname, st, line);
}
BZ_Free(file);
return !!line;
}
return false;
}
static qboolean Shader_LoadVMT(parsestate_t *ps, const char *filename)
{
vmtstate_t st;
memset(&st, 0, sizeof(st));
st.savefile = ps->saveshaderbody;
if (!VMT_ReadVMT(filename, &st))
{
if (st.sourcefile)
BZ_Free(st.sourcefile);
return false;
}
Shader_GenerateFromVMT(ps, &st, filename);
return true;
}
#endif
static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
{
size_t offset = 0, length;
@ -7293,6 +7765,11 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
char shaderfile[MAX_QPATH];
if (!*token)
{
#ifdef MATERIAL_VMT
if (Shader_LoadVMT(ps, parsename))
return true;
#endif
Q_snprintfz(shaderfile, sizeof(shaderfile), "%s.mat", parsename);
file = COM_LoadTempMoreFile(shaderfile, &length);
}

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

@ -42,6 +42,9 @@ cvar_t r_skyboxname = CVARFC ("r_skybox", "", CVAR_RENDERERCALLBACK | CVAR
cvar_t r_skybox_orientation = CVARFD ("r_glsl_skybox_orientation", "0 0 0 0", CVAR_SHADERSYSTEM, "Defines the axis around which skyboxes will rotate (the first three values). The fourth value defines the speed the skybox rotates at, in degrees per second.");
cvar_t r_skyfog = CVARD ("r_skyfog", "0.5", "This controls an alpha-blend value for fog on skyboxes, cumulative with regular fog alpha.");
#ifdef MATERIAL_VMT
static shader_t *forcedskyfaces[6];
#endif
static shader_t *forcedsky;
static shader_t *skyboxface;
static shader_t *skygridface;
@ -55,6 +58,9 @@ void R_SkyShutdown(void)
skyboxface = NULL;
skygridface = NULL;
forcedsky = NULL;
#ifdef MATERIAL_VMT
memset(forcedskyfaces, 0, sizeof(forcedskyfaces));
#endif
}
//lets the backend know which fallback envmap it can use.
@ -89,8 +95,21 @@ void R_SetSky(const char *sky)
if (!*sky)
return; //no need to do anything
#ifdef MATERIAL_VMT //hl2 skies have specific shaders (with their own maps) for each face. can't automatically use cubemap optimisations - we would need to interrogate the shaders. :(
for (i = 0; i < 6; i++)
{
static const char *facenames[] = {"rt", "bk", "lf", "ft", "up", "dn"};
forcedskyfaces[i] = R_RegisterCustom(va("materials/skybox/%s%s", sky, facenames[i]), SUF_NONE, NULL, NULL); //don't allow a fallback, so we know when it fails.
if (!forcedskyfaces[i])
break;
}
if (i == 6)
return; //okay, we have all 6 faces okay...
memset(forcedskyfaces, 0, sizeof(forcedskyfaces));
#endif
memset(&tex, 0, sizeof(tex));
//equirectangular skies
tex.base = R_LoadHiResTexture(sky, "env:gfx/env", IF_LOADNOW|IF_NOMIPMAP);
if (tex.reflectcube && tex.reflectcube->status == TEX_LOADING)
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
@ -442,6 +461,13 @@ qboolean R_DrawSkyChain (batch_t *batch)
if (!opaque)
GL_DrawSkySphere(batch, skyshader);
}
#ifdef MATERIAL_VMT
else if (forcedskyfaces[0])
{
R_CalcSkyChainBounds(batch);
GL_DrawSkyBox (NULL, batch);
}
#endif
else if (skyboxtex && TEXVALID(*skyboxtex))
{ //draw a skybox if we were given the textures
R_CalcSkyChainBounds(batch);
@ -1130,7 +1156,7 @@ static void GL_DrawSkyBox (texid_t *texnums, batch_t *s)
skyfacemesh.numindexes = 6;
skyfacemesh.numvertexes = 4;
if (!skyboxface)
if (texnums && !skyboxface)
skyboxface = R_RegisterShader("skyboxface", SUF_NONE,
"{\n"
"program default2d\n"
@ -1152,8 +1178,15 @@ static void GL_DrawSkyBox (texid_t *texnums, batch_t *s)
GL_MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, skyface_vertex[2], skyface_texcoord[2]);
GL_MakeSkyVec (skymaxs[0][i], skymins[1][i], i, skyface_vertex[3], skyface_texcoord[3]);
skyboxface->defaulttextures->base = texnums[skytexorder[i]];
R_DrawSkyMesh(s, &skyfacemesh, skyboxface);
#ifdef MATERIAL_VMT
if (!texnums)
R_DrawSkyMesh(s, &skyfacemesh, forcedskyfaces[skytexorder[i]]);
else
#endif
{
skyboxface->defaulttextures->base = texnums[skytexorder[i]];
R_DrawSkyMesh(s, &skyfacemesh, skyboxface);
}
}
}

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

@ -1792,9 +1792,9 @@ typedef struct
vfsfile_t funcs;
char *data;
int maxlen;
unsigned int writepos;
unsigned int readpos;
size_t maxlen;
size_t writepos;
size_t readpos;
void *mutex;
int refs;
qboolean terminate; //one end has closed, make the other report failures now that its no longer needed.
@ -1861,6 +1861,8 @@ static int QDECL VFSPIPE_ReadBytes(vfsfile_t *f, void *buffer, int len)
static int QDECL VFSPIPE_WriteBytes(vfsfile_t *f, const void *buffer, int len)
{
vfspipe_t *p = (vfspipe_t*)f;
if (len < 0)
return -1;
Sys_LockMutex(p->mutex);
if (p->terminate)
{ //if we started with 2 refs, and we're down to one, and we're writing, then its the reader that closed. that means writing is redundant and we should signal an error.
@ -1874,20 +1876,20 @@ static int QDECL VFSPIPE_WriteBytes(vfsfile_t *f, const void *buffer, int len)
p->writepos -= p->readpos;
p->readpos = 0;
}
if (p->writepos + len > p->maxlen)
if (p->writepos + (unsigned int)len > p->maxlen)
{
p->maxlen = p->writepos + len;
if (p->maxlen < (p->writepos-p->readpos)*2) //over-allocate a little
p->maxlen = (p->writepos-p->readpos)*2;
if (p->maxlen > 0x8000000)
if (p->maxlen > 0x8000000 && p->data)
{
p->maxlen = 0x8000000;
len = p->maxlen - p->writepos;
if (!len)
{
p->maxlen = max(p->maxlen, 0x8000000);
if (p->maxlen <= p->writepos)
{ //can't write anything.
Sys_UnlockMutex(p->mutex);
return -1; //try and get the caller to stop
return -1;
}
len = min(len, p->maxlen - p->writepos);
}
p->data = realloc(p->data, p->maxlen);
}

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

@ -1090,7 +1090,7 @@ void Q23BSP_FindTouchedLeafs(model_t *model, struct pvscache_s *ent, const float
int topnode;
int i, j;
int area;
int nullarea = (model->fromgame == fg_quake2)?0:-1;
int nullarea = (model->fromgame != fg_quake3)?0:-1; //q2 always has area0, while q3 defines the outside as not-an-area.
//ent->num_leafs == q2's ent->num_clusters
ent->num_leafs = 0;

View File

@ -6,7 +6,7 @@ VKSDKPATH ?= ~/VulkanSDK/1.1.73.0/x86_64/bin/
all:
NAMES= fixedemu fixedemu_flat altwater bloom_blur bloom_filter bloom_final colourtint crepuscular_opaque crepuscular_rays crepuscular_sky depthonly default2d defaultadditivesprite defaultskin defaultsky defaultskybox defaultfill defaultsprite defaultwall defaultwarp defaultgammacb drawflat_wall lpp_depthnorm lpp_light lpp_wall postproc_fisheye postproc_panorama postproc_laea postproc_stereographic postproc_equirectangular fxaa underwaterwarp menutint terrain rtlight
NAMES= fixedemu fixedemu_flat altwater bloom_blur bloom_filter bloom_final colourtint crepuscular_opaque crepuscular_rays crepuscular_sky depthonly default2d defaultadditivesprite defaultskin defaultsky defaultskybox defaultfill defaultsprite defaultwall defaultwarp defaultgammacb drawflat_wall lpp_depthnorm lpp_light lpp_wall postproc_fisheye postproc_panorama postproc_laea postproc_stereographic postproc_equirectangular fxaa underwaterwarp menutint terrain rtlight vmt_lightmapped vmt_refract vmt_unlit vmt_vertexlit vmt_water vmt_transition
ALLNAMES+=$(foreach v,$(NAMES),glsl/$v.glsl)

View File

@ -44,6 +44,12 @@ char shaders[][64] =
"menutint",
"terrain",
"rtlight",
"vmt_lightmapped",
"vmt_refract",
"vmt_transition",
"vmt_unlit",
"vmt_vertexlit",
"vmt_water",
""
};

View File

@ -7,6 +7,8 @@
!!permu BUMP
!!permu SPECULAR
!!permu REFLECTCUBEMASK
//!!permu TWOWAY //blend between diffuse and the 'upper' texture.
//!!permu EIGHTBIT //our fancy software banding.
!!permu FAKESHADOWS
!!cvarf r_glsl_offsetmapping_scale
!!cvardf r_glsl_pcf
@ -16,12 +18,14 @@
!!samps !EIGHTBIT =BUMP normalmap
!!samps !EIGHTBIT =REFLECTCUBEMASK reflectmask reflectcube
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
!!samps =EIGHTBIT paletted 1
!!samps =EIGHTBIT colourmap=0
!!samps =EIGHTBIT paletted
!!samps =SPECULAR specular
!!samps !VERTEXLIT lightmap
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3
!!samps =DELUXE deluxemap
!!samps =LIGHTSTYLED =DELUXE deluxemap1 deluxemap2 deluxemap3
!!samps =TWOWAY upper
!!samps =FAKESHADOWS shadowmap
#if defined(ORM) || defined(SG)
@ -56,7 +60,9 @@
varying vec2 lm0;
#endif
#endif
#ifdef TWOWAY
varying float alpha;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
@ -81,6 +87,9 @@ void main ()
#ifdef FLOW
tc.s += e_time * -0.5;
#endif
#ifdef TWOWAY
alpha = v_colour.a;
#endif
#ifdef VERTEXLIT
#ifdef LIGHTSTYLED
//FIXME, only one colour.
@ -249,7 +258,6 @@ void main()
#ifdef FRAGMENT_SHADER
#define s_colourmap s_t0
#include "sys/pbr.h"
#include "sys/pcf.h"
@ -283,6 +291,11 @@ void main ()
//Read the base texture (with EIGHTBIT only alpha is needed)
vec4 col = texture2D(s_diffuse, tc);
#ifdef TWOWAY
gl_FragColor *= (1.0-alpha);
gl_FragColor += alpha*texture2D(s_upper, tc);
#endif
#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))
vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);
#elif defined(PBR) || defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)

View File

@ -0,0 +1,166 @@
!!ver 110
!!permu FOG
!!permu BUMP
!!permu LIGHTSTYLED
!!permu REFLECTCUBEMASK
!!samps diffuse
!!samps lightmap
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3
!!samps =BUMP normalmap
// envmaps only
!!samps =REFLECTCUBEMASK reflectmask reflectcube
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
#include "sys/defs.h"
varying vec2 tex_c;
varying vec2 lm0;
#ifdef LIGHTSTYLED
varying vec2 lm1, lm2, lm3;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
varying vec3 eyevector;
varying mat3 invsurface;
#endif
#ifdef VERTEX_SHADER
void lightmapped_init(void)
{
lm0 = v_lmcoord;
#ifdef LIGHTSTYLED
lm1 = v_lmcoord2;
lm2 = v_lmcoord3;
lm3 = v_lmcoord4;
#endif
}
void main ()
{
lightmapped_init();
tex_c = v_texcoord;
gl_Position = ftetransform();
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
invsurface = mat3(v_svector, v_tvector, v_normal);
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot(eyeminusvertex, v_svector.xyz);
eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
eyevector.z = dot(eyeminusvertex, v_normal.xyz);
#endif
#ifdef FAKESHADOWS
vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));
#endif
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
#ifdef FAKESHADOWS
#include "sys/pcf.h"
#endif
#ifdef LIGHTSTYLED
#define LIGHTMAP0 texture2D(s_lightmap0, lm0).rgb
#define LIGHTMAP1 texture2D(s_lightmap1, lm1).rgb
#define LIGHTMAP2 texture2D(s_lightmap2, lm2).rgb
#define LIGHTMAP3 texture2D(s_lightmap3, lm3).rgb
#else
#define LIGHTMAP texture2D(s_lightmap, lm0).rgb
#endif
vec3 lightmap_fragment()
{
vec3 lightmaps;
#ifdef LIGHTSTYLED
lightmaps = LIGHTMAP0 * e_lmscale[0].rgb;
lightmaps += LIGHTMAP1 * e_lmscale[1].rgb;
lightmaps += LIGHTMAP2 * e_lmscale[2].rgb;
lightmaps += LIGHTMAP3 * e_lmscale[3].rgb;
#else
lightmaps = LIGHTMAP * e_lmscale.rgb;
#endif
/* the light we're getting is always too bright */
lightmaps *= 0.75;
/* clamp at 1.5 */
if (lightmaps.r > 1.5)
lightmaps.r = 1.5;
if (lightmaps.g > 1.5)
lightmaps.g = 1.5;
if (lightmaps.b > 1.5)
lightmaps.b = 1.5;
return lightmaps;
}
void main (void)
{
vec4 diffuse_f;
diffuse_f = texture2D(s_diffuse, tex_c);
#ifdef MASKLT
if (diffuse_f.a < float(MASK))
discard;
#endif
#ifdef FAKESHADOWS
diffuse_f.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
#endif
/* deluxemapping isn't working on Source BSP yet */
diffuse_f.rgb *= lightmap_fragment();
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
/* We currently only use the normal/bumpmap for cubemap warping. move this block out once we do proper radiosity normalmapping */
#ifdef BUMP
/* Source's normalmaps are in the DX format where the green channel is flipped */
vec4 normal_f = texture2D(s_normalmap, tex_c);
normal_f.g *= -1.0;
normal_f.rgb = normalize(normal_f.rgb - 0.5);
#else
vec4 normal_f = vec4(0.0,0.0,1.0,0.0);
#endif
#if defined(ENVFROMMASK)
/* We have a dedicated reflectmask */
#define refl texture2D(s_reflectmask, tex_c).r
#else
/* when ENVFROMBASE is set or a normal isn't present, we're getting the reflectivity info from the diffusemap's alpha channel */
#if defined(ENVFROMBASE) || !defined(BUMP)
#define refl 1.0 - diffuse_f.a
#else
#define refl normal_f.a * 0.5
#endif
#endif
vec3 cube_c = reflect(normalize(-eyevector), normal_f.rgb);
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
cube_c = (m_model * vec4(cube_c.xyz, 0.0)).xyz;
diffuse_f.rgb += (textureCube(s_reflectcube, cube_c).rgb * vec3(refl,refl,refl));
#endif
gl_FragColor = fog4(diffuse_f);
}
#endif

View File

@ -0,0 +1,47 @@
!!ver 110
!!samps diffuse
!!samps =BUMP normalmap
!!samps =REFLECTCUBEMASK reflectmask reflectcube
!!samps refraction=0
#include "sys/defs.h"
varying vec2 tex_c;
varying mat3 invsurface;
varying vec4 tf_c;
varying vec3 eyeminusvertex;
#ifdef VERTEX_SHADER
void main ()
{
invsurface[0] = v_svector;
invsurface[1] = v_tvector;
invsurface[2] = v_normal;
tf_c = ftetransform();
tex_c = v_texcoord;
gl_Position = tf_c;
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
void main ( void )
{
vec2 refl_c;
vec3 refr_f;
vec3 norm_f;
vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 );
norm_f = ( texture2D( s_normalmap, tex_c).xyz);
norm_f.g *= -1.0;
norm_f = normalize( norm_f );
// Reflection/View coordinates
refl_c = ( 1.0 + ( tf_c.xy / tf_c.w ) ) * 0.5;
refr_f = texture2D(s_refraction, refl_c + (norm_f.st) ).rgb;
out_f.rgb = refr_f * texture2D(s_diffuse, tex_c).rgb;
gl_FragColor = out_f;
}
#endif

View File

@ -0,0 +1,160 @@
!!ver 110
!!permu FOG
!!permu BUMP
!!permu LIGHTSTYLED
!!permu REFLECTCUBEMASK
!!permu UPPERLOWER
!!samps diffuse upper
!!samps lightmap
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3
!!samps =BUMP normalmap
// envmaps only
!!samps =REFLECTCUBEMASK reflectmask reflectcube
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
#include "sys/defs.h"
varying vec2 tex_c;
varying vec4 vex_color;
varying vec2 lm0;
#ifdef LIGHTSTYLED
varying vec2 lm1, lm2, lm3;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
varying vec3 eyevector;
varying mat3 invsurface;
#endif
#ifdef VERTEX_SHADER
void lightmapped_init(void)
{
lm0 = v_lmcoord;
#ifdef LIGHTSTYLED
lm1 = v_lmcoord2;
lm2 = v_lmcoord3;
lm3 = v_lmcoord4;
#endif
}
void main ()
{
lightmapped_init();
tex_c = v_texcoord;
gl_Position = ftetransform();
vex_color = v_colour;
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
invsurface = mat3(v_svector, v_tvector, v_normal);
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot(eyeminusvertex, v_svector.xyz);
eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
eyevector.z = dot(eyeminusvertex, v_normal.xyz);
#endif
#ifdef FAKESHADOWS
vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));
#endif
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
#ifdef FAKESHADOWS
#include "sys/pcf.h"
#endif
#ifdef LIGHTSTYLED
#define LIGHTMAP0 texture2D(s_lightmap0, lm0).rgb
#define LIGHTMAP1 texture2D(s_lightmap1, lm1).rgb
#define LIGHTMAP2 texture2D(s_lightmap2, lm2).rgb
#define LIGHTMAP3 texture2D(s_lightmap3, lm3).rgb
#else
#define LIGHTMAP texture2D(s_lightmap, lm0).rgb
#endif
vec3 lightmap_fragment()
{
vec3 lightmaps;
#ifdef LIGHTSTYLED
lightmaps = LIGHTMAP0 * e_lmscale[0].rgb;
lightmaps += LIGHTMAP1 * e_lmscale[1].rgb;
lightmaps += LIGHTMAP2 * e_lmscale[2].rgb;
lightmaps += LIGHTMAP3 * e_lmscale[3].rgb;
#else
lightmaps = LIGHTMAP * e_lmscale.rgb;
#endif
/* the light we're getting is always too bright */
lightmaps *= 0.75;
/* clamp at 1.5 */
if (lightmaps.r > 1.5)
lightmaps.r = 1.5;
if (lightmaps.g > 1.5)
lightmaps.g = 1.5;
if (lightmaps.b > 1.5)
lightmaps.b = 1.5;
return lightmaps;
}
void main (void)
{
vec4 diffuse_f;
diffuse_f.rgb = mix(texture2D(s_diffuse, tex_c).rgb, texture2D(s_upper, tex_c).rgb, vex_color.a);
diffuse_f.a = 1.0;
/* deluxemapping isn't working on Source BSP yet, FIXME */
diffuse_f.rgb *= lightmap_fragment();
#ifdef FAKESHADOWS
diffuse_f.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
#endif
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
/* We currently only use the normal/bumpmap for cubemap warping. move this block out once we do proper radiosity normalmapping */
#ifdef BUMP
/* Source's normalmaps are in the DX format where the green channel is flipped */
vec4 normal_f = texture2D(s_normalmap, tex_c);
normal_f.g *= -1.0;
normal_f.rgb = normalize(normal_f.rgb - 0.5);
#else
vec4 normal_f = vec4(0.0,0.0,1.0,0.0);
#endif
/* when ENVFROMBASE is set or a normal isn't present, we're getting the reflectivity info from the diffusemap's alpha channel */
#if defined(ENVFROMBASE) || !defined(BUMP)
/* since we're sampling from the diffuse = 1.0 fully visible, 0.0 = fully reflective */
#define refl 1.0 - diffuse_f.a
#else
#define refl normal_f.a * 0.5
#endif
vec3 cube_c = reflect(normalize(-eyevector), normal_f.rgb);
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
cube_c = (m_model * vec4(cube_c.xyz, 0.0)).xyz;
diffuse_f.rgb += (textureCube(s_reflectcube, cube_c).rgb * vec3(refl,refl,refl));
#endif
gl_FragColor = fog4(diffuse_f);
}
#endif

View File

@ -0,0 +1,30 @@
!!ver 110
!!permu FOG
!!samps diffuse
#include "sys/defs.h"
#include "sys/fog.h"
varying vec2 tex_c;
#ifdef VERTEX_SHADER
void main ()
{
tex_c = v_texcoord;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
void main ()
{
vec4 diffuse_f = texture2D( s_diffuse, tex_c );
#ifdef MASKLT
if (diffuse_f.a < float(MASK))
discard;
#endif
gl_FragColor = fog4( diffuse_f );
}
#endif

View File

@ -0,0 +1,140 @@
!!ver 110
!!permu FRAMEBLEND
!!permu BUMP
!!permu FOG
!!permu SKELETAL
!!permu AMBIENTCUBE
!!samps diffuse fullbright normalmap
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
// envmaps only
!!samps =REFLECTCUBEMASK reflectmask reflectcube
!!cvardf r_skipDiffuse
#include "sys/defs.h"
varying vec2 tex_c;
varying vec3 norm;
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
varying vec3 eyevector;
varying mat3 invsurface;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
void main (void)
{
vec3 n, s, t, w;
tex_c = v_texcoord;
gl_Position = skeletaltransform_wnst(w,n,s,t);
norm = n;
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
invsurface = mat3(v_svector, v_tvector, v_normal);
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot(eyeminusvertex, v_svector.xyz);
eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
eyevector.z = dot(eyeminusvertex, v_normal.xyz);
#endif
#ifdef FAKESHADOWS
vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));
#endif
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
#include "sys/pcf.h"
float lambert(vec3 normal, vec3 dir)
{
return max(dot(normal, dir), 0.0);
}
float halflambert(vec3 normal, vec3 dir)
{
return (lambert(normal, dir) * 0.5) + 0.5;
}
void main (void)
{
vec4 diffuse_f = texture2D(s_diffuse, tex_c);
vec3 light;
#ifdef MASKLT
if (diffuse_f.a < float(MASK))
discard;
#endif
/* Normal/Bumpmap Shenanigans */
#ifdef BUMP
/* Source's normalmaps are in the DX format where the green channel is flipped */
vec3 normal_f = texture2D(s_normalmap, tex_c).rgb;
normal_f.g *= -1.0;
normal_f = normalize(normal_f.rgb - 0.5);
#else
vec3 normal_f = vec3(0.0,0.0,1.0);
#endif
/* CUBEMAPS ONLY */
#ifdef REFLECTCUBEMASK
/* when ENVFROMBASE is set or a normal isn't present, we're getting the reflectivity info from the diffusemap's alpha channel */
#if defined(ENVFROMBASE) || !defined(BUMP)
#define refl 1.0 - diffuse_f.a
#else
#define refl texture2D(s_normalmap, tex_c).a
#endif
vec3 cube_c = reflect(normalize(-eyevector), normal_f.rgb);
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
cube_c = (m_model * vec4(cube_c.xyz, 0.0)).xyz;
diffuse_f.rgb += (textureCube(s_reflectcube, cube_c).rgb * vec3(refl,refl,refl));
#endif
#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
/* the light we're getting is always too bright */
light *= 0.75;
/* clamp at 1.5 */
if (light.r > 1.5)
light.r = 1.5;
if (light.g > 1.5)
light.g = 1.5;
if (light.b > 1.5)
light.b = 1.5;
#endif
diffuse_f.rgb *= light;
#ifdef FAKESHADOWS
diffuse_f.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
#endif
gl_FragColor = fog4(diffuse_f * e_colourident) * e_lmscale;
}
#endif

View File

@ -0,0 +1,178 @@
!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler
!!cvardf r_glsl_turbscale_refract=1 //simpler scaler
!!samps diffuse normalmap
!!samps refract=0 //always present
!!samps reflect=1
!!permu FOG
#include "sys/defs.h"
//modifier: REFLECT (s_t2 is a reflection instead of diffusemap)
//modifier: STRENGTH_REFL (distortion strength - 0.1 = fairly gentle, 0.2 = big waves)
//modifier: STRENGTH_REFL (distortion strength - 0.1 = fairly gentle, 0.2 = big waves)
//modifier: FRESNEL_EXP (5=water)
//modifier: TXSCALE (wave size - 0.2)
//modifier: RIPPLEMAP (s_t3 contains a ripplemap
//modifier: TINT_REFR (some colour value)
//modifier: TINT_REFL (some colour value)
//modifier: ALPHA (mix in the normal water texture over the top)
//modifier: USEMODS (use single-texture scrolling via tcmods - note, also forces the engine to actually use tcmod etc)
//a few notes on DP compat:
//'dpwater' makes numerous assumptions about DP internals
//by default there is a single pass that uses the pass's normal tcmods
//the fresnel has a user-supplied min+max rather than an exponent
//both parts are tinted individually
//if alpha is enabled, the regular water texture is blended over the top, again using the same crappy tcmods...
//legacy crap
#ifndef FRESNEL
#define FRESNEL 5.0
#endif
#ifndef TINT
#define TINT 0.7,0.8,0.7
#endif
#ifndef STRENGTH
#define STRENGTH 0.1
#endif
#ifndef TXSCALE
#define TXSCALE 1
#endif
//current values (referring to legacy defaults where needed)
#ifndef FRESNEL_EXP
#define FRESNEL_EXP 4.0
#endif
#ifndef FRESNEL_MIN
#define FRESNEL_MIN 0.0
#endif
#ifndef FRESNEL_RANGE
#define FRESNEL_RANGE 1.0
#endif
#ifndef STRENGTH_REFL
#define STRENGTH_REFL STRENGTH
#endif
#ifndef STRENGTH_REFR
#define STRENGTH_REFR STRENGTH
#endif
#ifndef TXSCALE1
#define TXSCALE1 TXSCALE
#endif
#ifndef TXSCALE2
#define TXSCALE2 TXSCALE
#endif
#ifndef TINT_REFR
#define TINT_REFR TINT
#endif
#ifndef TINT_REFL
#define TINT_REFL 1.0,1.0,1.0
#endif
#ifndef FOGTINT
#define FOGTINT 0.2,0.3,0.2
#endif
varying vec2 tc;
varying vec4 tf;
varying vec3 norm;
varying vec3 eye;
#ifdef VERTEX_SHADER
void main (void)
{
tc = v_texcoord.st;
tf = ftetransform();
norm = v_normal;
eye = e_eyepos - v_position.xyz;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
void main (void)
{
vec2 stc; //screen tex coords
vec2 ntc; //normalmap/diffuse tex coords
vec3 n, refr, refl;
float fres;
float depth;
stc = (1.0 + (tf.xy / tf.w)) * 0.5;
//hack the texture coords slightly so that there are less obvious gaps
stc.t -= 1.5*norm.z/1080.0;
#if 0//def USEMODS
ntc = tc;
n = texture2D(s_normalmap, ntc).xyz - 0.5;
#else
//apply q1-style warp, just for kicks
ntc.s = tc.s + sin(tc.t+e_time)*0.125;
ntc.t = tc.t + sin(tc.s+e_time)*0.125;
//generate the two wave patterns from the normalmap
n = (texture2D(s_normalmap, vec2(TXSCALE1)*tc + vec2(e_time*0.1, 0.0)).xyz);
n += (texture2D(s_normalmap, vec2(TXSCALE2)*tc - vec2(0, e_time*0.097)).xyz);
n -= 1.0 - 4.0/256.0;
#endif
#ifdef RIPPLEMAP
n += texture2D(s_ripplemap, stc).rgb*3.0;
#endif
n = normalize(n);
//the fresnel term decides how transparent the water should be
fres = pow(1.0-abs(dot(n, normalize(eye))), float(FRESNEL_EXP)) * float(FRESNEL_RANGE) + float(FRESNEL_MIN);
#ifdef DEPTH
float far = #include "cvar/gl_maxdist";
float near = #include "cvar/gl_mindist";
//get depth value at the surface
float sdepth = gl_FragCoord.z;
sdepth = (2.0*near) / (far + near - sdepth * (far - near));
sdepth = mix(near, far, sdepth);
//get depth value at the ground beyond the surface.
float gdepth = texture2D(s_refractdepth, stc).x;
gdepth = (2.0*near) / (far + near - gdepth * (far - near));
if (gdepth >= 0.5)
{
gdepth = sdepth;
depth = 0.0;
}
else
{
gdepth = mix(near, far, gdepth);
depth = gdepth - sdepth;
}
//reduce the normals in shallow water (near walls, reduces the pain of linear sampling)
if (depth < 100.0)
n *= depth/100.0;
#else
depth = 1.0;
#endif
//refraction image (and water fog, if possible)
refr = texture2D(s_refract, stc + n.st*float(STRENGTH_REFR)*float(r_glsl_turbscale_refract)).rgb * vec3(TINT_REFR);
#ifdef DEPTH
refr = mix(refr, vec3(FOGTINT), min(depth/4096.0, 1.0));
#endif
//reflection/diffuse
refl = texture2D(s_reflect, stc - n.st*float(STRENGTH_REFL)*float(r_glsl_turbscale_reflect)).rgb * vec3(TINT_REFL);
//interplate by fresnel
refr = mix(refr, refl, fres);
#ifdef ALPHA
vec4 ts = texture2D(s_diffuse, ntc);
vec4 surf = fog4blend(vec4(ts.rgb, float(ALPHA)*ts.a));
refr = mix(refr, surf.rgb, surf.a);
#else
refr = fog3(refr);
#endif
//done
gl_FragColor = vec4(refr, 1.0);
}
#endif