From 6b125ea5759cd45cb1d7f76cace351ccadc4cbb5 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Jun 2023 18:53:12 -0700 Subject: [PATCH] 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 --- src/deh_soc.c | 4 ++++ src/doomstat.h | 2 ++ src/p_setup.c | 1 + src/p_spec.c | 1 + src/r_things.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+) diff --git a/src/deh_soc.c b/src/deh_soc.c index f6ae6a285..d0ca37e45 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -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")) diff --git a/src/doomstat.h b/src/doomstat.h index 950645ef6..53071a319 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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; diff --git a/src/p_setup.c b/src/p_setup.c index 02e19702d..c9a79c812 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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" diff --git a/src/p_spec.c b/src/p_spec.c index 1a794c3ef..51a62332c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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; diff --git a/src/r_things.c b/src/r_things.c index ca164a398..4d1c17263 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -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)