light: implement delay 4 and 5 as in visbjp light

Implement the two extra light attenuation formulae that were added to
Benjt Jardrup's light util (http://user.tninet.se/~xir870k/readmevis.txt).

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-02-28 16:16:34 +10:30
parent 725fffbd7a
commit 8f3d28c2ac
3 changed files with 81 additions and 13 deletions

View File

@ -40,6 +40,11 @@ typedef enum {
LF_INVERSE = 1, /* Inverse (1/x), scaled by 1/128 */
LF_INVERSE2 = 2, /* Inverse square (1/(x^2)), scaled by 1/(128^2) */
LF_INFINITE = 3, /* No attenuation, same brightness at any distance */
LF_LOCALMIN = 4, /* No attenuation, non-additive minlight effect within
line of sight of the light source. */
LF_INVERSE2A = 5, /* Inverse square, with distance adjusted to avoid
exponentially bright values near the source.
(1/(x+128)^2), scaled by 1/(128^2) */
LF_COUNT
} light_formula_t;

View File

@ -99,10 +99,15 @@ ENTITY PARAMETERS
"delay" "n"
Select an attenuation formaula for the light:
0 => linear attenuation (default)
0 => Linear attenuation (default)
1 => 1/x attenuation
2 => 1/(x^2) attenuation
3 => no attenuation (light stays same brightness at any distance)
3 => No attenuation (light stays same brightness at any distance)
4 => "local minlight" - No attenuation and like minlight, it won't
raise the lighting above it's light value. Unlike minlight, it
will only affect surfaces within line of sight of the entity.
5 => 1/(x^2) attenuation, but slightly more attenuated and without
the extra bright effect that "delay 2" has near the source.
"_color" "r g b"

View File

@ -460,7 +460,9 @@ scaledDistance(vec_t distance, const entity_t *light)
return scaledist * light->atten * distance;
case LF_INVERSE:
case LF_INVERSE2:
case LF_INVERSE2A:
case LF_INFINITE:
case LF_LOCALMIN:
/* Return a small distance to prevent culling these lights, since we */
/* know these formulae won't fade to nothing. */
return (distance <= 0.0) ? -0.25 : 0.25;
@ -472,20 +474,25 @@ scaledDistance(vec_t distance, const entity_t *light)
static vec_t
scaledLight(vec_t distance, const entity_t *light)
{
const vec_t tmp = scaledist * light->atten * distance;
vec_t dist;
switch (light->formula) {
case LF_INFINITE:
if (light->formula == LF_INFINITE || light->formula == LF_LOCALMIN)
return light->light;
dist = scaledist * light->atten * distance;
switch (light->formula) {
case LF_INVERSE:
return light->light / (tmp / LF_SCALE);
return light->light / (dist / LF_SCALE);
case LF_INVERSE2A:
dist += LF_SCALE;
/* Fall through */
case LF_INVERSE2:
return light->light / ((tmp * tmp) / (LF_SCALE * LF_SCALE));
return light->light / ((dist * dist) / (LF_SCALE * LF_SCALE));
case LF_LINEAR:
if (light->light > 0)
return (light->light - tmp > 0) ? light->light - tmp : 0;
return (light->light - dist > 0) ? light->light - dist : 0;
else
return (light->light + tmp < 0) ? light->light + tmp : 0;
return (light->light + dist < 0) ? light->light + dist : 0;
default:
Error("Internal error: unknown light formula");
}
@ -722,9 +729,10 @@ SkyLightFace(lightinfo_t *l, const vec3_t faceoffset, const vec3_t colors)
static void
FixMinlight(lightinfo_t *l)
{
int i, j;
int i, j, k;
vec_t *lightmap;
vec3_t *colormap;
const entity_t *entity;
/* Find a style 0 lightmap */
lightmap = NULL;
@ -739,7 +747,7 @@ FixMinlight(lightinfo_t *l)
if (!lightmap) {
if (l->numlightstyles == MAXLIGHTMAPS)
return; /* oh well... */
return; /* oh well... FIXME - should we warn? */
lightmap = l->lightmaps[l->numlightstyles];
for (i = 0; i < l->numsurfpt; i++)
lightmap[i] = worldminlight;
@ -762,6 +770,50 @@ FixMinlight(lightinfo_t *l)
}
}
}
/* Cast rays for local minlight entities */
for (i = 0, entity = entities; i < num_entities; i++, entity++) {
if (entity->formula != LF_LOCALMIN)
continue;
/* Find the lightmap with correct style */
lightmap = NULL;
colormap = NULL;
for (j = 0; j < l->numlightstyles; j++) {
if (l->lightstyles[j] == 0) {
lightmap = l->lightmaps[j];
colormap = l->lightmapcolors[j];
break;
}
}
if (!lightmap) {
if (l->numlightstyles == MAXLIGHTMAPS)
continue; /* oh well... FIXME - should we warn? */
lightmap = l->lightmaps[l->numlightstyles];
colormap = l->lightmapcolors[l->numlightstyles];
l->numlightstyles++;
}
for (j = 0; j < l->numsurfpt; j++) {
qboolean trace = false;
if (lightmap[j] < entity->light) {
trace = TestLine(entity->origin, l->surfpt[j]);
if (!trace)
continue;
lightmap[j] = entity->light;
}
if (!colored)
continue;
for (k = 0; k < 3; k++) {
if (colormap[j][k] < minlight_color[k]) {
if (!trace)
trace = TestLine(entity->origin, l->surfpt[j]);
if (trace)
colormap[j][k] = minlight_color[k];
}
}
}
}
}
@ -900,6 +952,8 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset)
if (nominlimit) {
/* cast only positive lights */
for (i = 0, entity = entities; i < num_entities; i++, entity++) {
if (entity->formula == LF_LOCALMIN)
continue;
if (colored) {
if (entity->light) {
PositiveColors(entity->light, colors, entity->lightcolor);
@ -920,10 +974,12 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset)
}
} else {
/* (!nominlimit) => cast all lights */
for (i = 0, entity = entities; i < num_entities; i++, entity++)
for (i = 0, entity = entities; i < num_entities; i++, entity++) {
if (entity->formula == LF_LOCALMIN)
continue;
if (entity->light)
SingleLightFace(entity, &l, faceoffset, colors);
}
/* cast sky light */
if (sunlight)
SkyLightFace(&l, faceoffset, colors);
@ -935,6 +991,8 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset)
if (nominlimit) {
/* cast only negative lights */
for (i = 0, entity = entities; i < num_entities; i++, entity++) {
if (entity->formula == LF_LOCALMIN)
continue;
if (colored) {
if (entity->light) {
NegativeColors(entity->light, colors, entity->lightcolor);