diff --git a/changelog.txt b/changelog.txt index d1a913ea..cb497cd2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,6 +9,7 @@ * light: lit files now automatically generated when coloured lights detected * light: implemented 4x4 oversampling with -extra4 command line * light: implemented the -gate option to help speed processing (default 0.001) +* light: implemented the "_softangle" key for spotlights 2013-02-25 TyrUtils v0.5 diff --git a/include/light/entities.h b/include/light/entities.h index e9af006f..0e77c4f5 100644 --- a/include/light/entities.h +++ b/include/light/entities.h @@ -56,6 +56,8 @@ typedef struct entity_s { vec3_t spotvec; float spotangle; float spotfalloff; + float spotangle2; + float spotfalloff2; int style; int light; diff --git a/light.txt b/light.txt index 01f22c2d..ea1beaaf 100644 --- a/light.txt +++ b/light.txt @@ -135,6 +135,13 @@ ENTITY PARAMETERS Specifies the angle in degrees for a spotlight cone. Default 40. + "_softangle" "n" + + Specifies the angle in degrees for an inner spotlight cone (must be + less than the "angle" cone. Creates a softer transition between the + full brightness of the inner cone to the edge of the outer cone. + Default 0 (disabled). + "targetname" "name" Turns the light into a switchable light, toggled by another entity diff --git a/light/entities.c b/light/entities.c index 830f8a0f..55044131 100644 --- a/light/entities.c +++ b/light/entities.c @@ -126,8 +126,15 @@ SetupSpotlights(void) entity->spotlight = true; } if (entity->spotlight) { - vec_t angle = entity->spotangle ? entity->spotangle : 40; + vec_t angle, angle2; + + angle = (entity->spotangle > 0) ? entity->spotangle : 40; entity->spotfalloff = -cos(angle / 2 * Q_PI / 180); + + angle2 = entity->spotangle2; + if (angle2 <= 0 || angle2 > angle) + angle2 = angle; + entity->spotfalloff2 = -cos(angle2 / 2 * Q_PI / 180); } } } @@ -302,11 +309,12 @@ LoadEntities(void) entity->light = atof(com_token); else if (!strcmp(key, "style")) { entity->style = atof(com_token); - if ((unsigned)entity->style > 254) - Error("Bad light style %i (must be 0-254)", - entity->style); + if (entity->style < 0 || entity->style > 254) + Error("Bad light style %i (must be 0-254)", entity->style); } else if (!strcmp(key, "angle")) entity->spotangle = atof(com_token); + else if (!strcmp(key, "_softangle")) + entity->spotangle2 = atof(com_token); else if (!strcmp(key, "wait")) entity->atten = atof(com_token); else if (!strcmp(key, "delay")) diff --git a/light/ltface.c b/light/ltface.c index fa30e913..c6826d48 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -477,7 +477,7 @@ SingleLightFace(const entity_t *light, lightinfo_t * l, const vec3_t faceoffset, const vec3_t colors) { vec_t dist; - vec_t angle; + vec_t angle, spotscale; vec_t add; const vec_t *surf; qboolean newmap, hit; @@ -540,10 +540,17 @@ SingleLightFace(const entity_t *light, lightinfo_t * l, /* Check spotlight cone */ VectorScale(ray, 1.0 / dist, ray); angle = DotProduct(ray, l->facenormal); + spotscale = 1; if (light->spotlight) { vec_t falloff = DotProduct(light->spotvec, ray); if (falloff > light->spotfalloff) continue; + if (falloff > light->spotfalloff2) { + /* Interpolate between the two spotlight falloffs */ + spotscale = falloff - light->spotfalloff2; + spotscale /= light->spotfalloff - light->spotfalloff2; + spotscale = 1.0 - spotscale; + } } /* Test for line of sight */ @@ -551,7 +558,7 @@ SingleLightFace(const entity_t *light, lightinfo_t * l, continue; angle = (1.0 - scalecos) + scalecos * angle; - add = GetLightValue(light, dist) * angle; + add = GetLightValue(light, dist) * angle * spotscale; lightsamp[c] += add; if (colored) VectorMA(colorsamp[c], add / 255, colors, colorsamp[c]);