Sprite directional lighting, add SpriteBacklight option to level header

- Sprites have directional lighting, like walls
- For normal sprites: contrast is much stronger than walls
- Papersprites look the same as walls

- SpriteBacklight option in level header weakens the contrast for sprites only
  - SpriteBacklight subtracts from LightContrast
  - E.g. SpriteBacklight = 0 would let it match LightContrast
  - E.g. SpriteBacklight = 60 would make the contrast much weaker
  - Negative values make the contrast stronger
This commit is contained in:
James R 2023-06-05 18:53:12 -07:00
parent 5eeb29d552
commit 6b125ea575
5 changed files with 60 additions and 0 deletions

View file

@ -1278,6 +1278,10 @@ void readlevelheader(MYFILE *f, char * name)
{
mapheaderinfo[num]->light_contrast = (UINT8)i;
}
else if (fastcmp(word, "SPRITEBACKLIGHT"))
{
mapheaderinfo[num]->sprite_backlight = (SINT8)i;
}
else if (fastcmp(word, "LIGHTANGLE"))
{
if (fastcmp(word2, "EVEN"))

View file

@ -503,6 +503,7 @@ struct mapheader_t
UINT16 palette; ///< PAL lump to use on this map
UINT16 encorepal; ///< PAL for encore mode
UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting.
SINT8 sprite_backlight; ///< Subtract from wall lighting for sprites only.
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional.
angle_t light_angle; ///< Angle of directional wall lighting.
@ -762,6 +763,7 @@ extern fixed_t mapobjectscale;
extern struct maplighting
{
UINT8 contrast;
SINT8 backlight;
boolean directional;
angle_t angle;
} maplighting;

View file

@ -438,6 +438,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->mobj_scale = FRACUNIT;
mapheaderinfo[num]->default_waypoint_radius = 0;
mapheaderinfo[num]->light_contrast = 16;
mapheaderinfo[num]->sprite_backlight = 0;
mapheaderinfo[num]->use_light_angle = false;
mapheaderinfo[num]->light_angle = 0;
#if 1 // equivalent to "Followers = DEFAULT"

View file

@ -6732,6 +6732,7 @@ void P_InitSpecials(void)
// Set map lighting settings.
maplighting.contrast = mapheaderinfo[gamemap-1]->light_contrast;
maplighting.backlight = mapheaderinfo[gamemap-1]->sprite_backlight;
maplighting.directional = mapheaderinfo[gamemap-1]->use_light_angle;
maplighting.angle = mapheaderinfo[gamemap-1]->light_angle;

View file

@ -1630,6 +1630,26 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis)
box->x2test = 0;
}
static fixed_t R_GetSpriteDirectionalLighting(angle_t angle)
{
// Copied from P_UpdateSegLightOffset
const UINT8 contrast = min(max(0, maplighting.contrast - maplighting.backlight), UINT8_MAX);
const fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT;
fixed_t light = FRACUNIT;
fixed_t extralight = 0;
light = FixedMul(FINECOSINE(angle >> ANGLETOFINESHIFT), FINECOSINE(maplighting.angle >> ANGLETOFINESHIFT))
+ FixedMul(FINESINE(angle >> ANGLETOFINESHIFT), FINESINE(maplighting.angle >> ANGLETOFINESHIFT));
light = (light + FRACUNIT) / 2;
light = FixedMul(light, FRACUNIT - FSIN(abs(AngleDeltaSigned(angle, maplighting.angle)) / 2));
extralight = -contrastFixed + FixedMul(light, contrastFixed * 2);
return extralight;
}
//
// R_ProjectSprite
// Generates a vissprite for a thing
@ -2275,6 +2295,38 @@ static void R_ProjectSprite(mobj_t *thing)
lightnum = (lightnum + R_ThingLightLevel(oldthing)) >> LIGHTSEGSHIFT;
if (maplighting.directional == true)
{
fixed_t extralight = R_GetSpriteDirectionalLighting(papersprite
? interp.angle + (ang >= ANGLE_180 ? -ANGLE_90 : ANGLE_90)
: R_PointToAngle(interp.x, interp.y));
// Less change in contrast in dark sectors
extralight = FixedMul(extralight, min(max(0, lightnum), LIGHTLEVELS - 1) * FRACUNIT / (LIGHTLEVELS - 1));
if (papersprite)
{
// Papersprite contrast should match walls
lightnum += FixedFloor((extralight / 8) + (FRACUNIT / 2)) / FRACUNIT;
}
else
{
fixed_t n = FixedDiv(FixedMul(xscale, LIGHTRESOLUTIONFIX), ((MAXLIGHTSCALE-1) << LIGHTSCALESHIFT));
// Less change in contrast at further distances, to counteract DOOM diminished light
extralight = FixedMul(extralight, min(n, FRACUNIT));
// Contrast is stronger for normal sprites, stronger than wall lighting is at the same distance
lightnum += FixedFloor((extralight / 4) + (FRACUNIT / 2)) / FRACUNIT;
}
// Semibright objects will be made slightly brighter to compensate contrast
if (R_ThingIsSemiBright(oldthing))
{
lightnum += 2;
}
}
if (lightnum < 0)
lights_array = scalelight[0];
else if (lightnum >= LIGHTLEVELS)