// LordHavoc: 256 dynamic lights
#define MAX_DLIGHTS 256
-// LordHavoc: this affects the lighting scale of the whole game
-#define LIGHTOFFSET 1024.0f
-// max lights shining on one entity
-#define MAXENTLIGHTS 128
// flags for rtlight rendering
#define LIGHTFLAG_NORMALMODE 1
// this is R_Shadow_Cubemap(rtlight->cubemapname)
rtexture_t *currentcubemap;
- // lightmap renderer stuff (remove someday!)
- // the size of the light
- vec_t lightmap_cullradius;
- // the size of the light, squared
- vec_t lightmap_cullradius2;
- // the brightness of the light
- vec3_t lightmap_light;
- // to avoid sudden brightness change at cullradius, subtract this
- vec_t lightmap_subtract;
-
// static light info
// true if this light should be compiled as a static light
int isstatic;
// 4 frame numbers (-1 if not used) and their blending scalers (0-1), if interpolation is not desired, use frame instead
frameblend_t frameblend[4];
- // caching results of static light traces (this is semi-persistent)
- double entlightstime;
- vec3_t entlightsorigin;
- int entlightsframe;
- int numentlights;
- unsigned short entlights[MAXENTLIGHTS];
+ // current lighting from map
+ vec3_t modellight_ambient;
+ vec3_t modellight_diffuse; // q3bsp
+ vec3_t modellight_lightdir; // q3bsp
}
entity_render_t;
vertstrings_count = 1;
fragstrings_count = 1;
permutationname[0] = 0;
- if (permutation & SHADERPERMUTATION_DELUXEMAPPING)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
{
- vertstrings_list[vertstrings_count++] = "#define USEDELUXEMAP\n";
- fragstrings_list[fragstrings_count++] = "#define USEDELUXEMAP\n";
- strlcat(permutationname, " deluxemap", sizeof(permutationname));
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
+ strlcat(permutationname, " lightsource", sizeof(permutationname));
}
- if (permutation & SHADERPERMUTATION_LIGHTSOURCE)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
{
- vertstrings_list[vertstrings_count++] = "#define USELIGHTSOURCE\n";
- fragstrings_list[fragstrings_count++] = "#define USELIGHTSOURCE\n";
- strlcat(permutationname, " lightsource", sizeof(permutationname));
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
+ strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
+ }
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
+ {
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
+ strlcat(permutationname, " lightdirection", sizeof(permutationname));
+ }
+ if (permutation & SHADERPERMUTATION_GLOW)
+ {
+ vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
+ fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
+ strlcat(permutationname, " glow", sizeof(permutationname));
}
if (permutation & SHADERPERMUTATION_COLORMAPPING)
{
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
+ p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
+ p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
- if (p->loc_Texture_Normal) qglUniform1iARB(p->loc_Texture_Normal, 0);
- if (p->loc_Texture_Color) qglUniform1iARB(p->loc_Texture_Color, 1);
- if (p->loc_Texture_Gloss) qglUniform1iARB(p->loc_Texture_Gloss, 2);
- if (p->loc_Texture_Cube) qglUniform1iARB(p->loc_Texture_Cube, 3);
- if (p->loc_Texture_FogMask) qglUniform1iARB(p->loc_Texture_FogMask, 4);
- if (p->loc_Texture_Pants) qglUniform1iARB(p->loc_Texture_Pants, 5);
- if (p->loc_Texture_Shirt) qglUniform1iARB(p->loc_Texture_Shirt, 6);
- if (p->loc_Texture_Lightmap) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
- if (p->loc_Texture_Deluxemap) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
+ p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
+ p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
+ p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
+ p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
+ if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
+ if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
+ if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
+ if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
+ if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
+ if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
+ if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
+ if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
+ if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
+ if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
qglUseProgramObjectARB(0);
CHECKGLERROR
}
Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
}
-void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
{
// select a permutation of the lighting shader appropriate to this
// combination of texture, entity, light source, and fogging, only use the
// minimum features necessary to avoid wasting rendering time in the
// fragment shader on features that are not being used
int permutation = 0;
+ float specularscale = texture->specularscale;
r_glsl_permutation = NULL;
if (r_shadow_rtlight)
- permutation |= SHADERPERMUTATION_LIGHTSOURCE;
+ {
+ permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
+ specularscale *= r_shadow_rtlight->specularscale;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ permutation |= SHADERPERMUTATION_CUBEFILTER;
+ }
+ else if (modellighting)
+ {
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
+ if (texture->skin.glow)
+ permutation |= SHADERPERMUTATION_GLOW;
+ }
else if (false)
- permutation |= SHADERPERMUTATION_DELUXEMAPPING;
+ {
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
+ if (texture->skin.glow)
+ permutation |= SHADERPERMUTATION_GLOW;
+ }
+ else
+ {
+ if (texture->skin.glow)
+ permutation |= SHADERPERMUTATION_GLOW;
+ }
+ if (specularscale > 0)
+ permutation |= SHADERPERMUTATION_SPECULAR;
if (fogenabled)
permutation |= SHADERPERMUTATION_FOG;
- if ((dopants || doshirt))
+ if (texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (specularscale > 0)
- permutation |= SHADERPERMUTATION_SPECULAR;
- if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
- permutation |= SHADERPERMUTATION_CUBEFILTER;
if (r_glsl_offsetmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING;
if (r_glsl_surfacenormalize.integer)
CHECKGLERROR
qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
- if (r_shadow_rtlight)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
+ {
R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
- if (r_glsl_permutation->loc_Texture_Normal) R_Mesh_TexBind(0, R_GetTexture(normalmaptexture));
- if (r_glsl_permutation->loc_Texture_Color) R_Mesh_TexBind(1, R_GetTexture(basetexture));
- if (r_glsl_permutation->loc_FogColor)
+ if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
+ if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
+ if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+ if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
+ if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
+ if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
+ }
+ else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
+ {
+ if (r_glsl_permutation->loc_AmbientColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
+ if (r_glsl_permutation->loc_DiffuseColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
+ if (r_glsl_permutation->loc_SpecularColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
+ if (r_glsl_permutation->loc_LightDir >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
+ }
+ else
+ {
+ if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
+ if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
+ if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
+ }
+ if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
+ if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
+ if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
+ if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
+ if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
+ if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
+ if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
+ if (r_glsl_permutation->loc_FogColor >= 0)
{
// additive passes are only darkened by fog, not tinted
if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
else
qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
}
- if (r_glsl_permutation->loc_LightPosition) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
- if (r_glsl_permutation->loc_EyePosition) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, r_shadow_entityeyeorigin[0], r_shadow_entityeyeorigin[1], r_shadow_entityeyeorigin[2]);
- if (r_glsl_permutation->loc_LightColor) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
- if (r_glsl_permutation->loc_Texture_Pants) R_Mesh_TexBind(5, R_GetTexture(pantstexture));
- if (r_glsl_permutation->loc_Texture_Shirt) R_Mesh_TexBind(6, R_GetTexture(shirttexture));
- if (r_glsl_permutation->loc_Color_Pants) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
- if (r_glsl_permutation->loc_Color_Shirt) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
- if (r_glsl_permutation->loc_FogRangeRecip) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
- if (r_glsl_permutation->loc_AmbientScale) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
- if (r_glsl_permutation->loc_DiffuseScale) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
- if (r_glsl_permutation->loc_Texture_Gloss) R_Mesh_TexBind(2, R_GetTexture(glosstexture));
- if (r_glsl_permutation->loc_SpecularPower) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, 8);
- if (r_glsl_permutation->loc_SpecularScale) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
- if (r_glsl_permutation->loc_OffsetMapping_Scale) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
- if (r_glsl_permutation->loc_OffsetMapping_Bias) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
+ if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
+ if (r_glsl_permutation->loc_Color_Pants >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
+ if (r_glsl_permutation->loc_Color_Shirt >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
+ if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
+ if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
+ if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
CHECKGLERROR
}
//==================================================================================
+static void R_UpdateEntityLighting(entity_render_t *ent)
+{
+ vec3_t tempdiffusenormal;
+ VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
+ VectorClear(ent->modellight_diffuse);
+ VectorClear(ent->modellight_lightdir);
+ if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
+ r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+ else // highly rare
+ VectorSet(ent->modellight_ambient, 1, 1, 1);
+ Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
+ VectorNormalize(ent->modellight_lightdir);
+ ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
+ ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
+ ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
+ ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
+ ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
+ ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
+}
+
static void R_MarkEntities (void)
{
int i, renderimask;
ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
{
- R_UpdateEntLights(ent);
ent->visframe = r_framecount;
+ R_UpdateEntityLighting(ent);
}
}
}
ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
{
- R_UpdateEntLights(ent);
ent->visframe = r_framecount;
+ R_UpdateEntityLighting(ent);
}
}
}
r_framecount++;
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
+
R_MeshQueue_BeginScene();
R_SetFrustum();
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
+
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
}
/*
t->currenttexmatrix = r_waterscrollmatrix;
else
t->currenttexmatrix = identitymatrix;
+
+ t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
+ t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
+ t->glosstexture = r_texture_white;
+ t->specularpower = 8;
+ t->specularscale = 0;
+ if (r_shadow_gloss.integer > 0)
+ {
+ if (t->skin.gloss)
+ {
+ if (r_shadow_glossintensity.value > 0)
+ {
+ t->glosstexture = t->skin.gloss;
+ t->specularscale = r_shadow_glossintensity.value;
+ }
+ }
+ else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
+ t->specularscale = r_shadow_gloss2intensity.value;
+ }
+
t->currentnumlayers = 0;
if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
{
if (gl_lightmaps.integer)
R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
- else if (t->currentmaterialflags & MATERIALFLAG_SKY)
- {
- // transparent sky would be ridiculous
- if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
- R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
- }
- else
+ else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
{
int blendfunc1, blendfunc2, depthmask;
if (t->currentmaterialflags & MATERIALFLAG_ADD)
R_Mesh_VertexPointer(rsurface_vertex3f);
}
+static void RSurf_Draw(const msurface_t *surface)
+{
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+}
+
static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
{
int i;
float f;
float *v, *c, *c2;
- RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
if (lightmode >= 2)
{
// model lighting
- vec4_t ambientcolor4f;
+ vec4_t ambientcolor;
vec3_t diffusecolor;
- vec3_t diffusenormal;
- if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
+ vec3_t lightdir;
+ VectorCopy(ent->modellight_lightdir, lightdir);
+ ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
+ ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
+ ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
+ diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
+ diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
+ diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
+ if (VectorLength2(diffusecolor) > 0)
{
- rsurface_lightmapcolor4f = varray_color4f;
- R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
+ int numverts = surface->num_vertices;
+ v = rsurface_vertex3f + 3 * surface->num_firstvertex;
+ c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
+ c = varray_color4f + 4 * surface->num_firstvertex;
+ // q3-style directional shading
+ for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
+ {
+ if ((f = DotProduct(c2, lightdir)) > 0)
+ {
+ VectorMA(ambientcolor, f, diffusecolor, c);
+ c[3] = a;
+ }
+ else
+ VectorCopy4(ambientcolor, c);
+ }
r = 1;
g = 1;
b = 1;
a = 1;
applycolor = false;
+ rsurface_lightmapcolor4f = varray_color4f;
}
else
{
- r = ambientcolor4f[0];
- g = ambientcolor4f[1];
- b = ambientcolor4f[2];
- a = ambientcolor4f[3];
+ r = ambientcolor[0];
+ g = ambientcolor[1];
+ b = ambientcolor[2];
rsurface_lightmapcolor4f = NULL;
}
}
}
R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
GL_Color(r, g, b, a);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
- GL_LockArrays(0, 0);
-}
-
-static void RSurf_Draw(const msurface_t *surface)
-{
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
- GL_LockArrays(0, 0);
+ RSurf_Draw(surface);
}
static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
rmeshstate_t m;
if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
return;
+ r_shadow_rtlight = NULL;
renderstats.entities_surfaces += texturenumsurfaces;
// FIXME: identify models using a better check than ent->model->brush.shadowmesh
lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
qglDisable(GL_CULL_FACE);
- if (texture->currentnumlayers)
+ if (texture->currentmaterialflags & MATERIALFLAG_SKY)
+ {
+ // transparent sky would be ridiculous
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ GL_DepthMask(true);
+ if (skyrendernow)
+ {
+ skyrendernow = false;
+ if (skyrendermasked)
+ {
+ R_Sky();
+ // restore entity matrix and GL_Color
+ R_Mesh_Matrix(&ent->matrix);
+ GL_Color(1,1,1,1);
+ }
+ }
+ // LordHavoc: HalfLife maps have freaky skypolys...
+ //if (!ent->model->brush.ishlbsp)
+ {
+ if (skyrendermasked)
+ {
+ // depth-only (masking)
+ GL_ColorMask(0,0,0,0);
+ // just to make sure that braindead drivers don't draw anything
+ // despite that colormask...
+ GL_BlendFunc(GL_ZERO, GL_ONE);
+ }
+ else
+ {
+ // fog sky
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ }
+ GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
+ RSurf_Draw(surface);
+ }
+ if (skyrendermasked)
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ }
+ }
+ }
+ else if (r_glsl.integer && gl_support_fragment_shader)
+ {
+ if (texture->currentmaterialflags & MATERIALFLAG_ADD)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ }
+ else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthMask(false);
+ }
+ else
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ }
+
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
+ R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
+ if (!r_glsl_permutation)
+ return;
+ if (lightmode == 2)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ RSurf_Draw(surface);
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
+ if (surface->lightmaptexture)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
+ }
+ RSurf_Draw(surface);
+ }
+ }
+ qglUseProgramObjectARB(0);
+ }
+ else if (texture->currentnumlayers)
{
int layerindex;
texturelayer_t *layer;
applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
switch (layer->type)
{
- case TEXTURELAYERTYPE_SKY:
- if (skyrendernow)
- {
- skyrendernow = false;
- if (skyrendermasked)
- {
- R_Sky();
- // restore entity matrix and GL_Color
- R_Mesh_Matrix(&ent->matrix);
- GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
- }
- }
- // LordHavoc: HalfLife maps have freaky skypolys...
- //if (!ent->model->brush.ishlbsp)
- {
- if (skyrendermasked)
- {
- // depth-only (masking)
- GL_ColorMask(0,0,0,0);
- // just to make sure that braindead drivers don't draw anything
- // despite that colormask...
- GL_BlendFunc(GL_ZERO, GL_ONE);
- }
- else
- {
- // fog sky
- GL_BlendFunc(GL_ONE, GL_ZERO);
- }
- memset(&m, 0, sizeof(m));
- R_Mesh_State(&m);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
- RSurf_Draw(surface);
- }
- if (skyrendermasked)
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- }
- break;
case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
memset(&m, 0, sizeof(m));
m.tex[1] = R_GetTexture(layer->texture);
R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
if (!r_showtrispass)
renderstats.entities_triangles += counttriangles;
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
}
void Mod_Q1BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
{
Mod_Q1BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
+ VectorSet(diffusenormal, 0, 0, -1);
}
static void Mod_Q1BSP_DecompressVis(const unsigned char *in, const unsigned char *inend, unsigned char *out, unsigned char *outend)
}
}
-static void Mod_Q1BSP_LoadLightList(void)
-{
- int a, n, numlights;
- char tempchar, *s, *t, *lightsstring, lightsfilename[1024];
- mlight_t *e;
-
- strlcpy (lightsfilename, loadmodel->name, sizeof (lightsfilename));
- FS_StripExtension (lightsfilename, lightsfilename, sizeof(lightsfilename));
- strlcat (lightsfilename, ".lights", sizeof (lightsfilename));
- s = lightsstring = (char *) FS_LoadFile(lightsfilename, tempmempool, false, NULL);
- if (s)
- {
- numlights = 0;
- while (*s)
- {
- while (*s && *s != '\n' && *s != '\r')
- s++;
- if (!*s)
- {
- Mem_Free(lightsstring);
- Con_Printf("lights file must end with a newline\n");
- return;
- }
- s++;
- numlights++;
- }
- loadmodel->brushq1.lights = (mlight_t *)Mem_Alloc(loadmodel->mempool, numlights * sizeof(mlight_t));
- s = lightsstring;
- n = 0;
- while (*s && n < numlights)
- {
- t = s;
- while (*s && *s != '\n' && *s != '\r')
- s++;
- if (!*s)
- {
- Con_Printf("misparsed lights file!\n");
- break;
- }
- e = loadmodel->brushq1.lights + n;
- tempchar = *s;
- *s = 0;
- a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style);
- *s = tempchar;
- if (a != 14)
- {
- Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
- break;
- }
- if (*s == '\r')
- s++;
- if (*s == '\n')
- s++;
- n++;
- }
- if (*s)
- Con_Printf("misparsed lights file!\n");
- loadmodel->brushq1.numlights = numlights;
- Mem_Free(lightsstring);
- }
-}
-
static void Mod_Q1BSP_LoadVisibility(lump_t *l)
{
loadmodel->brushq1.num_compressedpvs = 0;
mainmempool = mod->mempool;
- Mod_Q1BSP_LoadLightList();
-
// make a single combined shadow mesh to allow optimized shadow volume creation
numshadowmeshtriangles = 0;
for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
}
svbspmesh_t;
-typedef struct mlight_s
-{
- // location of light
- vec3_t origin;
- // distance attenuation scale (smaller is a larger light)
- float falloff;
- // color and brightness combined
- vec3_t light;
- // brightness bias, used for limiting radius without a hard edge
- float subtract;
- // spotlight direction
- vec3_t spotdir;
- // cosine of spotlight cone angle (or 0 if not a spotlight)
- float spotcone;
- // distance bias (larger value is softer and darker)
- float distbias;
- // light style controlling this light
- int style;
- // maximum extent of the light for shading purposes
- float lightradius;
- // maximum extent of the light for culling purposes
- float cullradius;
- float cullradius2;
- /*
- // surfaces this shines on
- int numsurfaces;
- msurface_t **surfaces;
- // lit area
- vec3_t mins, maxs;
- // precomputed shadow volume meshs
- //svbspmesh_t *shadowvolume;
- //vec3_t shadowvolumemins, shadowvolumemaxs;
- shadowmesh_t *shadowvolume;
- */
-}
-mlight_t;
-
// Q2 bsp stuff
#define Q2BSPVERSION 38
typedef enum texturelayertype_e
{
TEXTURELAYERTYPE_INVALID,
- TEXTURELAYERTYPE_SKY,
TEXTURELAYERTYPE_LITTEXTURE_COMBINE,
TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS,
TEXTURELAYERTYPE_LITTEXTURE_VERTEX,
// current texture transform matrix (used for water scrolling)
matrix4x4_t currenttexmatrix;
+ qboolean colormapping;
+ rtexture_t *basetexture;
+ rtexture_t *glosstexture;
+ float specularscale;
+ float specularpower;
+
int currentnumlayers;
texturelayer_t currentlayers[16];
int num_lightdata;
unsigned char *lightdata;
- int numlights;
- mlight_t *lights;
-
// lightmap update chains for light styles
int light_styles;
unsigned char *light_style;
#include "cl_collision.h"
#include "r_shadow.h"
-cvar_t r_modellights = {CVAR_SAVE, "r_modellights", "4", "how many lights from a .lights file (produced by hlight) are worthy of directional shading on a model (others are applied to the whole model as ambient lighting)"};
cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
void R_Light_Init(void)
{
- Cvar_RegisterVariable(&r_modellights);
Cvar_RegisterVariable(&r_coronas);
Cvar_RegisterVariable(&gl_flashblend);
R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap);
else
VectorSet(ambientcolor, 1, 1, 1);
- // FIXME: this .lights related stuff needs to be ported into the Mod_Q1BSP code
- if (r_refdef.worldmodel->brushq1.numlights)
- {
- int i;
- vec3_t v;
- float f;
- mlight_t *sl;
- for (i = 0;i < r_refdef.worldmodel->brushq1.numlights;i++)
- {
- sl = r_refdef.worldmodel->brushq1.lights + i;
- if (r_refdef.lightstylevalue[sl->style] > 0)
- {
- VectorSubtract (p, sl->origin, v);
- f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract);
- if (f > 0 && CL_TraceBox(p, vec3_origin, vec3_origin, sl->origin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
- {
- f *= r_refdef.lightstylevalue[sl->style] * (1.0f / 65536.0f);
- if (f > 0)
- VectorMA(ambientcolor, f, sl->light, ambientcolor);
- }
- }
- }
- }
-
if (dynamic)
{
int i;
float f, v[3];
dlight_t *light;
- // FIXME: this really should handle dlights as diffusecolor/diffusenormal somehow
- // FIXME: this should be updated to match rtlight falloff!
for (i = 0;i < r_refdef.numlights;i++)
{
light = r_refdef.lights[i];
- VectorSubtract(p, light->origin, v);
- f = DotProduct(v, v);
- if (f < light->rtlight.lightmap_cullradius2 && CL_TraceBox(p, vec3_origin, vec3_origin, light->origin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
- {
- f = (1.0f / (f + LIGHTOFFSET)) - light->rtlight.lightmap_subtract;
- if (f > 0)
- VectorMA(ambientcolor, f, light->rtlight.lightmap_light, ambientcolor);
- }
+ Matrix4x4_Transform(&light->rtlight.matrix_worldtolight, p, v);
+ f = 1 - VectorLength2(v);
+ if (f > 0 && CL_TraceBox(p, vec3_origin, vec3_origin, light->origin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+ VectorMA(ambientcolor, f, light->rtlight.currentcolor, ambientcolor);
}
}
}
-
-typedef struct nearlight_s
-{
- vec3_t origin;
- //vec_t cullradius2;
- vec3_t light;
- // how much this light would contribute to ambient if replaced
- vec3_t ambientlight;
- vec_t subtract;
- vec_t falloff;
- vec_t offset;
- // used for choosing only the brightest lights
- vec_t intensity;
-}
-nearlight_t;
-
-static int nearlights;
-static nearlight_t nearlight[MAX_DLIGHTS];
-
-int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, const entity_render_t *ent, float colorr, float colorg, float colorb, float colora, int worldcoords)
-{
- int i, j, maxnearlights;
- float v[3], f, mscale, stylescale, intensity, ambientcolor[3], tempdiffusenormal[3];
- nearlight_t *nl;
- mlight_t *sl;
-
- nearlights = 0;
- maxnearlights = r_modellights.integer;
- ambient4f[0] = ambient4f[1] = ambient4f[2] = r_ambient.value * (2.0f / 128.0f);
- VectorClear(diffusecolor);
- VectorClear(diffusenormal);
- if (!(ent->flags & RENDER_LIGHT))
- {
- // highly rare
- VectorSet(ambient4f, 1, 1, 1);
- maxnearlights = 0;
- }
- else if (r_lightmapintensity <= 0)
- maxnearlights = 0;
- else
- {
- if (r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
- {
- r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ambient4f, diffusecolor, tempdiffusenormal);
- Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, diffusenormal);
- VectorNormalize(diffusenormal);
- }
- else
- VectorSet(ambient4f, 1, 1, 1);
- }
-
- // scale of the model's coordinate space, to alter light attenuation to match
- // make the mscale squared so it can scale the squared distance results
- mscale = ent->scale * ent->scale;
- // FIXME: no support for .lights on non-Q1BSP?
- nl = &nearlight[0];
- for (i = 0;i < ent->numentlights;i++)
- {
- sl = r_refdef.worldmodel->brushq1.lights + ent->entlights[i];
- stylescale = r_refdef.lightstylevalue[sl->style] * (1.0f / 65536.0f);
- VectorSubtract (ent->origin, sl->origin, v);
- f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract) * stylescale;
- VectorScale(sl->light, f, ambientcolor);
- intensity = DotProduct(ambientcolor, ambientcolor);
- if (f < 0)
- intensity *= -1.0f;
- if (nearlights < maxnearlights)
- j = nearlights++;
- else
- {
- for (j = 0;j < maxnearlights;j++)
- {
- if (nearlight[j].intensity < intensity)
- {
- if (nearlight[j].intensity > 0)
- VectorAdd(ambient4f, nearlight[j].ambientlight, ambient4f);
- break;
- }
- }
- }
- if (j >= maxnearlights)
- {
- // this light is less significant than all others,
- // add it to ambient
- if (intensity > 0)
- VectorAdd(ambient4f, ambientcolor, ambient4f);
- }
- else
- {
- nl = nearlight + j;
- nl->intensity = intensity;
- // transform the light into the model's coordinate system
- if (worldcoords)
- VectorCopy(sl->origin, nl->origin);
- else
- Matrix4x4_Transform(&ent->inversematrix, sl->origin, nl->origin);
- // integrate mscale into falloff, for maximum speed
- nl->falloff = sl->falloff * mscale;
- VectorCopy(ambientcolor, nl->ambientlight);
- nl->light[0] = sl->light[0] * stylescale * colorr * 4.0f;
- nl->light[1] = sl->light[1] * stylescale * colorg * 4.0f;
- nl->light[2] = sl->light[2] * stylescale * colorb * 4.0f;
- nl->subtract = sl->subtract;
- nl->offset = sl->distbias;
- }
- }
- ambient4f[0] *= colorr;
- ambient4f[1] *= colorg;
- ambient4f[2] *= colorb;
- ambient4f[3] = colora;
- diffusecolor[0] *= colorr;
- diffusecolor[1] *= colorg;
- diffusecolor[2] *= colorb;
- return nearlights != 0 || DotProduct(diffusecolor, diffusecolor) > 0;
-}
-
-void R_LightModel_CalcVertexColors(const float *ambientcolor4f, const float *diffusecolor, const float *diffusenormal, int numverts, const float *vertex3f, const float *normal3f, float *color4f)
-{
- int i, j, usediffuse;
- float color[4], v[3], dot, dist2, f, dnormal[3];
- nearlight_t *nl;
- usediffuse = DotProduct(diffusecolor, diffusecolor) > 0;
- // negate the diffuse normal to avoid the need to negate the
- // dotproduct on each vertex
- VectorNegate(diffusenormal, dnormal);
- if (usediffuse)
- VectorNormalize(dnormal);
- // directional shading code here
- for (i = 0;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
- {
- VectorCopy4(ambientcolor4f, color);
-
- // silly directional diffuse shading
- if (usediffuse)
- {
- // we have to negate this result because it is the incoming light
- // direction, not simply the normal to dotproduct with.
- dot = DotProduct(normal3f, dnormal);
- if (dot < 0)
- VectorMA(color, -dot, diffusecolor, color);
- }
-
- // pretty good lighting
- for (j = 0, nl = &nearlight[0];j < nearlights;j++, nl++)
- {
- VectorSubtract(nl->origin, vertex3f, v);
- // first eliminate negative lighting (back side)
- dot = DotProduct(normal3f, v);
- if (dot > 0)
- {
- // we'll need this again later to normalize the dotproduct
- dist2 = DotProduct(v,v);
- // do the distance attenuation math
- f = (1.0f / (dist2 * nl->falloff + nl->offset)) - nl->subtract;
- if (f > 0)
- {
- // we must divide dot by sqrt(dist2) to compensate for
- // the fact we did not normalize v before doing the
- // dotproduct, the result is in the range 0 to 1 (we
- // eliminated negative numbers already)
- f *= dot / sqrt(dist2);
- // blend in the lighting
- VectorMA(color, f, nl->light, color);
- }
- }
- }
- VectorCopy4(color, color4f);
- }
-}
-
-void R_UpdateEntLights(entity_render_t *ent)
-{
- int i;
- const mlight_t *sl;
- vec3_t v;
- if (r_lightmapintensity <= 0)
- return;
- VectorSubtract(ent->origin, ent->entlightsorigin, v);
- if (ent->entlightsframe != (r_framecount - 1) || (realtime > ent->entlightstime && DotProduct(v,v) >= 1.0f))
- {
- ent->entlightstime = realtime + 0.1;
- VectorCopy(ent->origin, ent->entlightsorigin);
- ent->numentlights = 0;
- if (r_refdef.worldmodel)
- for (i = 0, sl = r_refdef.worldmodel->brushq1.lights;i < r_refdef.worldmodel->brushq1.numlights && ent->numentlights < MAXENTLIGHTS;i++, sl++)
- if (CL_TraceBox(ent->origin, vec3_origin, vec3_origin, sl->origin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
- ent->entlights[ent->numentlights++] = i;
- }
- ent->entlightsframe = r_framecount;
-}
-
void R_DrawCoronas(void);
void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic);
-int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, const entity_render_t *ent, float colorr, float colorg, float colorb, float colora, int worldcoords);
-void R_LightModel_CalcVertexColors(const float *ambientcolor4f, const float *diffusecolor, const float *diffusenormal, int numverts, const float *vertex3f, const float *normal3f, float *color4f);
-void R_UpdateEntLights(entity_render_t *ent);
#endif
{
// ARB2 GLSL shader path (GFFX5200, Radeon 9500)
int surfacelistindex;
- R_SetupSurfaceShader(ent, texture, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, pantstexture, shirttexture, normalmaptexture, glosstexture, specularscale, dopants, doshirt);
+ R_SetupSurfaceShader(ent, texture, r_shadow_entityeyeorigin, lightcolorbase, false);
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
const msurface_t *surface = surfacelist[surfacelistindex];
{
// FIXME: support MATERIALFLAG_NODEPTHTEST
vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
- rtexture_t *basetexture;
- rtexture_t *pantstexture;
- rtexture_t *shirttexture;
- rtexture_t *glosstexture;
- float specularscale;
- qboolean dopants, doshirt;
- glosstexture = r_texture_black;
- specularscale = 0;
- if (r_shadow_gloss.integer > 0)
- {
- if (texture->skin.gloss)
- {
- if (r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
- {
- glosstexture = texture->skin.gloss;
- specularscale = r_shadow_rtlight->specularscale * r_shadow_glossintensity.value;
- }
- }
- else
- {
- if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
- {
- glosstexture = r_texture_white;
- specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value;
- }
- }
- }
// calculate colors to render this texture with
lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * ent->colormod[0] * texture->currentalpha;
lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * ent->colormod[1] * texture->currentalpha;
lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * ent->colormod[2] * texture->currentalpha;
- if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
+ if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + (r_shadow_rtlight->specularscale * texture->specularscale) * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
return;
if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
qglDisable(GL_CULL_FACE);
else
qglEnable(GL_CULL_FACE);
- dopants = texture->skin.pants != NULL && VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f);
- doshirt = texture->skin.shirt != NULL && VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
- if (dopants + doshirt)
+ if (texture->colormapping)
{
+ qboolean dopants = texture->skin.pants != NULL && VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f);
+ qboolean doshirt = texture->skin.shirt != NULL && VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
if (dopants)
{
lightcolorpants[0] = lightcolorbase[0] * ent->colormap_pantscolor[0];
lightcolorpants[2] = lightcolorbase[2] * ent->colormap_pantscolor[2];
}
else
- {
- pantstexture = r_texture_black;
VectorClear(lightcolorpants);
- }
if (doshirt)
{
- shirttexture = texture->skin.shirt;
lightcolorshirt[0] = lightcolorbase[0] * ent->colormap_shirtcolor[0];
lightcolorshirt[1] = lightcolorbase[1] * ent->colormap_shirtcolor[1];
lightcolorshirt[2] = lightcolorbase[2] * ent->colormap_shirtcolor[2];
}
else
- {
- shirttexture = r_texture_black;
VectorClear(lightcolorshirt);
- }
switch (r_shadow_rendermode)
{
case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
- R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->skin.base, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_GLSL:
- R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->skin.base, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_DOT3:
- R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->skin.base, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
- R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->skin.base, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, texture->basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, dopants, doshirt);
break;
default:
Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
}
else
{
- basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
switch (r_shadow_rendermode)
{
case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
- R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, basetexture, r_texture_black, r_texture_black, texture->skin.nmap, glosstexture, specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_GLSL:
- R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, basetexture, r_texture_black, r_texture_black, texture->skin.nmap, glosstexture, specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_DOT3:
- R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, basetexture, r_texture_black, r_texture_black, texture->skin.nmap, glosstexture, specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
- R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, basetexture, r_texture_black, r_texture_black, texture->skin.nmap, glosstexture, specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, texture->basetexture, r_texture_black, r_texture_black, texture->skin.nmap, texture->glosstexture, r_shadow_rtlight->specularscale * texture->specularscale, false, false);
break;
default:
Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
for (k = 0;k < 3;k++)
for (j = 0;j < 4;j++)
rtlight->matrix_worldtolight.m[k][j] *= scale;
-
- rtlight->lightmap_cullradius = bound(0, rtlight->radius, 2048.0f);
- rtlight->lightmap_cullradius2 = rtlight->lightmap_cullradius * rtlight->lightmap_cullradius;
- VectorScale(rtlight->color, rtlight->radius * (rtlight->style >= 0 ? r_refdef.lightstylevalue[rtlight->style] : 128) * 0.125f, rtlight->lightmap_light);
- rtlight->lightmap_subtract = 1.0f / rtlight->lightmap_cullradius2;
}
// compiles rtlight geometry
void R_QueueTextureSurfaceList(entity_render_t *ent, struct texture_s *texture, int texturenumsurfaces, const struct msurface_s **texturesurfacelist, const vec3_t modelorg);
void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces);
-#define SHADERPERMUTATION_DELUXEMAPPING (1<<0) // (lightmap) use directional pixel shading
-#define SHADERPERMUTATION_LIGHTSOURCE (1<<1) // (lightsource) indicates this is lightsource rendering mode
-#define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
-#define SHADERPERMUTATION_COLORMAPPING (1<<3) // indicates this is a colormapped skin
-#define SHADERPERMUTATION_SPECULAR (1<<4) // (lightsource or deluxemapping) render specular effects
-#define SHADERPERMUTATION_CUBEFILTER (1<<5) // (lightsource) use cubemap light filter
-#define SHADERPERMUTATION_OFFSETMAPPING (1<<6) // adjust texcoords to roughly simulate a displacement mapped surface
-#define SHADERPERMUTATION_SURFACENORMALIZE (1<<7) // (lightsource or deluxemapping) improved bumpmapping
-#define SHADERPERMUTATION_GEFORCEFX (1<<8) // use half vector types if available (NVIDIA specific)
-#define SHADERPERMUTATION_COUNT (1<<9) // how many permutations are possible
+#define SHADERPERMUTATION_MODE_LIGHTSOURCE (1<<0) // (lightsource) use directional pixel shading from light source (rtlight)
+#define SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP (1<<1) // (lightmap) use directional pixel shading from texture containing light directions (deluxemap)
+#define SHADERPERMUTATION_MODE_LIGHTDIRECTION (1<<2) // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
+#define SHADERPERMUTATION_GLOW (1<<3) // (lightmap) blend in an additive glow texture
+#define SHADERPERMUTATION_FOG (1<<4) // tint the color by fog color or black if using additive blend mode
+#define SHADERPERMUTATION_COLORMAPPING (1<<5) // indicates this is a colormapped skin
+#define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
+#define SHADERPERMUTATION_CUBEFILTER (1<<7) // (lightsource) use cubemap light filter
+#define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
+#define SHADERPERMUTATION_SURFACENORMALIZE (1<<9) // (lightsource or deluxemapping) improved bumpmapping
+#define SHADERPERMUTATION_GEFORCEFX (1<<10) // use half vector types if available (NVIDIA specific)
+#define SHADERPERMUTATION_COUNT (1<<11) // how many permutations are possible
typedef struct r_glsl_permutation_s
{
int loc_Texture_Shirt;
int loc_Texture_Lightmap;
int loc_Texture_Deluxemap;
+ int loc_Texture_Glow;
int loc_FogColor;
int loc_LightPosition;
int loc_EyePosition;
int loc_SpecularPower;
int loc_OffsetMapping_Scale;
int loc_OffsetMapping_Bias;
+ int loc_AmbientColor;
+ int loc_DiffuseColor;
+ int loc_SpecularColor;
+ int loc_LightDir;
}
r_glsl_permutation_t;
r_glsl_permutation_t *r_glsl_permutation;
void R_GLSL_CompilePermutation(int permutation);
-void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt);
+void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting);
#endif