Add LightStrength to UDMF, move SoftShadowRadius from AActor to DynamicLight

This commit is contained in:
Ricardo Luís Vaz Silva 2024-10-08 20:46:27 -03:00 committed by Magnus Norddahl
commit 56787bbc17
15 changed files with 88 additions and 20 deletions

View file

@ -429,6 +429,9 @@ Note: All <bool> fields default to false unless mentioned otherwise.
lm_suncolor = <int>; // ZDRay lightmap sun color. Default is white (0xFFFFFF).
light_softshadowradius = <float>; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0
light_strength = <float>; // Light strenght for Inverse-square falloff lights. Default = 0.0 (auto)
friendlyseeblocks = <int>; // How far (in block units) a friendly monster can see other monsters. Default 10

View file

@ -384,6 +384,7 @@ struct FMapThing
int friendlyseeblocks;
FName arg0str;
double SoftShadowRadius;
double LightStrength;
};

View file

@ -793,7 +793,11 @@ public:
break;
case NAME_light_softshadowradius:
th->SoftShadowRadius = (float)CheckFloat(key);
th->SoftShadowRadius = CheckFloat(key);
break;
case NAME_light_strength:
th->LightStrength = CheckFloat(key);
break;
case NAME_lm_suncolor:

View file

@ -320,6 +320,8 @@ xx(RedSkull)
xx(DynamicLight)
xx(SpotInnerAngle)
xx(SpotOuterAngle)
xx(SoftShadowRadius)
xx(LightStrength)
xx(lightflags)
xx(lighttype)
xx(InternalDynamicLight)
@ -869,6 +871,7 @@ xx(lm_suncolor)
// Light keywords
xx(light_softshadowradius)
xx(light_strength)
xx(skew_bottom_type)
xx(skew_middle_type)

View file

@ -99,6 +99,12 @@ static FDynamicLight *GetLight(FLevelLocals *Level)
}
static inline constexpr float calcStrength(float radius)
{
radius *= 2; // radius in shaders is actualy diameter, so multiply it here to match
return std::min(1500.0f, (radius * radius) / 10);
}
//==========================================================================
//
// Attaches a dynamic light descriptor to a dynamic light actor.
@ -115,7 +121,14 @@ void AttachLight(AActor *self)
light->pPitch = &self->Angles.Pitch;
light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags);
light->pArgs = self->args;
light->pSoftShadowRadius = &self->SoftShadowRadius;
light->pSoftShadowRadius = &self->FloatVar(NAME_SoftShadowRadius);
light->pStrength = &self->FloatVar(NAME_LightStrength);
if(*light->pStrength <= 0)
{
*light->pStrength = -calcStrength(light->m_currentRadius);
}
light->specialf1 = DAngle::fromDeg(double(self->SpawnAngle)).Normalized360().Degrees();
light->Sector = self->Sector;
light->target = self;
@ -213,7 +226,6 @@ void FDynamicLight::ReleaseLight()
FreeList.Push(this);
}
//==========================================================================
//
// [TS]
@ -237,6 +249,11 @@ void FDynamicLight::Activate()
m_currentRadius = float(m_cycler.GetVal());
}
if (m_currentRadius <= 0) m_currentRadius = 1;
if(pStrength && *pStrength <= 0)
{
*pStrength = -calcStrength(m_currentRadius);
}
}
@ -254,6 +271,8 @@ void FDynamicLight::Tick()
return;
}
int oldradius = m_currentRadius;
if (owned)
{
if (!target->state || !target->ShouldRenderLocally())
@ -345,8 +364,9 @@ void FDynamicLight::Tick()
intensity = Sector? Sector->lightlevel * scale : 0;
intensity = clamp<float>(intensity, 0.f, 255.f);
m_currentRadius = intensity;
break;
}
@ -355,6 +375,12 @@ void FDynamicLight::Tick()
break;
}
if (m_currentRadius <= 0) m_currentRadius = 1;
if(pStrength && *pStrength <= 0 && oldradius != m_currentRadius)
{
*pStrength = -calcStrength(m_currentRadius);
}
UpdateLocation();
}

View file

@ -131,6 +131,7 @@ protected:
DAngle m_spotOuterAngle = DAngle::fromDeg(25.0);
DAngle m_pitch = nullAngle;
double SoftShadowRadius = 5.0;
double Strength = 0.0;
friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def);
};
@ -224,6 +225,7 @@ struct FDynamicLight
bool IsActive() const { return m_active; }
float GetRadius() const { return (IsActive() ? m_currentRadius * 2.f : 0.f); }
float GetSoftShadowRadius() const { return (float)(*pSoftShadowRadius); }
float GetStrength() const { return std::abs((float)*pStrength); }
int GetRed() const { return pArgs[LIGHT_RED]; }
int GetGreen() const { return pArgs[LIGHT_GREEN]; }
int GetBlue() const { return pArgs[LIGHT_BLUE]; }
@ -272,6 +274,8 @@ public:
const LightFlags *pLightFlags;
const double* pSoftShadowRadius; // Softshadows. Physical size of the light source
double* pStrength; // Softshadows. Physical size of the light source
double specialf1;
FDynamicLight *next, *prev;
sector_t *Sector;
@ -292,6 +296,8 @@ public:
bool swapped;
bool explicitpitch;
double tmpStrength;
// Locations in the level mesh light list. Ends with index = 0 or all entries used
enum { max_levelmesh_entries = 4 };
struct

View file

@ -1375,8 +1375,6 @@ public:
// (note: this is put into AActor instead of the PlayerPawn because non-players also use the value)
double LandingSpeed;
double SoftShadowRadius = 5.0; // Light source's soft shadow radius
// ThingIDs
void SetTID (int newTID);

View file

@ -6181,8 +6181,6 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position)
if (mthing->fillcolor)
mobj->fillcolor = (mthing->fillcolor & 0xffffff) | (ColorMatcher.Pick((mthing->fillcolor & 0xff0000) >> 16,
(mthing->fillcolor & 0xff00) >> 8, (mthing->fillcolor & 0xff)) << 24);
if (mthing->SoftShadowRadius >= 0.0)
mobj->SoftShadowRadius = mthing->SoftShadowRadius;
// allow color strings for lights and reshuffle the args for spot lights
if (i->IsDescendantOf(NAME_DynamicLight))
@ -6206,6 +6204,20 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position)
mobj->AngleVar(NAME_SpotInnerAngle) = DAngle::fromDeg(mthing->args[1]);
mobj->AngleVar(NAME_SpotOuterAngle) = DAngle::fromDeg(mthing->args[2]);
}
if (mthing->SoftShadowRadius >= 0.0)
{
mobj->FloatVar(NAME_SoftShadowRadius) = mthing->SoftShadowRadius;
}
else
{
mobj->FloatVar(NAME_SoftShadowRadius) = 5.0;
}
if (mthing->LightStrength > 0.0)
{
mobj->FloatVar(NAME_LightStrength) = mthing->LightStrength;
}
}
mobj->CallBeginPlay ();

View file

@ -127,6 +127,17 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const
light->specialf1 = m_Param;
light->pArgs = m_Args;
light->pSoftShadowRadius = &SoftShadowRadius;
if(Strength > 0.0)
{
light->pStrength = const_cast<double*>(&Strength); // casting const to non-const, but positive strength values will not be modified
}
else
{
light->tmpStrength = 0.0;
light->pStrength = &light->tmpStrength;
}
light->pLightFlags = &m_lightFlags;
if (m_lightFlags & LF_SPOT)
{

View file

@ -31,6 +31,7 @@
#include"hw_cvars.h"
#include "v_video.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "g_levellocals.h"
// If we want to share the array to avoid constant allocations it needs to be thread local unless it'd be littered with expensive synchronization.
thread_local FDynLightData lightdata;
@ -140,6 +141,8 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
}
float softShadowRadius = light->GetSoftShadowRadius();
float strength = light->GetStrength();
float *data = &dld.arrays[i][dld.arrays[i].Reserve(16)];
data[0] = float(pos.X);
data[1] = float(pos.Z);
@ -156,7 +159,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
data[12] = spotInnerAngle;
data[13] = spotOuterAngle;
data[14] = softShadowRadius;
data[15] = 0.0f; // unused
data[15] = strength;
}
void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVector3& sundir, const FVector3& suncolor)
@ -177,6 +180,8 @@ void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVec
float spotDirZ = 0.0f;
float shadowIndex = -1025.f; // Note: 1025 disables shadowmap and the attenuate flag is in the sign bit of the float
float strength = 1500.0f;
float* data = &dld.arrays[i][dld.arrays[i].Reserve(16)];
data[0] = float(x);
data[1] = float(z);
@ -193,5 +198,5 @@ void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVec
data[12] = spotInnerAngle;
data[13] = spotOuterAngle;
data[14] = 0.0f; // unused
data[15] = 0.0f; // unused
data[15] = strength;
}

View file

@ -13,7 +13,7 @@ vec3 lightContribution(int i, vec3 normal)
float dotprod = dot(normal, lightdir);
if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues.
float attenuation = distanceAttenuation(lightdistance, lightpos.w);
float attenuation = distanceAttenuation(lightdistance, lightpos.w, lightspot2.w);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);

View file

@ -79,7 +79,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight)
vec3 L = normalize(lightpos.xyz - worldpos);
vec3 H = normalize(V + L);
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), lightpos.w);
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), lightpos.w, lightspot2.w);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
if (lightcolor.a < 0.0)
@ -119,7 +119,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight)
vec3 L = normalize(lightpos.xyz - worldpos);
vec3 H = normalize(V + L);
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), lightpos.w);
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), lightpos.w, lightspot2.w);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
if (lightcolor.a < 0.0)

View file

@ -1,8 +1,8 @@
#ifdef LIGHT_ATTENUATION_INVERSE_SQUARE
float distanceAttenuation(float dist, float radius)
float distanceAttenuation(float dist, float radius, float strength)
{
float strength = min(1500.0, (radius * radius) / 10);
float a = dist / radius;
float b = clamp(1.0 - a * a * a * a, 0.0, 1.0);
return (b * b) / (dist * dist + 1.0) * strength;
@ -10,9 +10,6 @@ float distanceAttenuation(float dist, float radius)
#else //elif defined(LIGHT_ATTENUATION_LINEAR)
float distanceAttenuation(float dist, float radius)
{
return clamp((radius - dist) / radius, 0.0, 1.0);
}
#define distanceAttenuation(dist, radius, strength) clamp((radius - dist) / radius, 0.0, 1.0)
#endif

View file

@ -8,7 +8,7 @@ vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA, float
if (lightpos.w < lightdistance)
return vec2(0.0); // Early out lights touching surface but not this fragment
float attenuation = distanceAttenuation(lightdistance, lightpos.w);
float attenuation = distanceAttenuation(lightdistance, lightpos.w, lightspot2.w);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);

View file

@ -2,6 +2,8 @@ class DynamicLight : Actor
{
double SpotInnerAngle;
double SpotOuterAngle;
double SoftShadowRadius;
double LightStrength; // used for Inverse-square falloff lights
private int lighttype;
private int lightflags;