change light strength to light linearity 0.0 = inverse square, 1.0 = linear
This commit is contained in:
parent
55940ba21d
commit
74a49ca919
13 changed files with 54 additions and 56 deletions
|
|
@ -384,7 +384,7 @@ struct FMapThing
|
|||
int friendlyseeblocks;
|
||||
FName arg0str;
|
||||
double SoftShadowRadius;
|
||||
double LightStrength;
|
||||
double LightLinearity;
|
||||
bool LightNoShadowMap;
|
||||
bool LightDontLightActors;
|
||||
bool LightDontLightMap;
|
||||
|
|
|
|||
|
|
@ -796,8 +796,8 @@ public:
|
|||
th->SoftShadowRadius = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_light_strength:
|
||||
th->LightStrength = CheckFloat(key);
|
||||
case NAME_light_linearity:
|
||||
th->LightLinearity = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_light_noshadowmap:
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ xx(DynamicLight)
|
|||
xx(SpotInnerAngle)
|
||||
xx(SpotOuterAngle)
|
||||
xx(SoftShadowRadius)
|
||||
xx(LightStrength)
|
||||
xx(LightLinearity)
|
||||
xx(lightflags)
|
||||
xx(lighttype)
|
||||
xx(InternalDynamicLight)
|
||||
|
|
@ -871,7 +871,7 @@ xx(lm_suncolor)
|
|||
|
||||
// Light keywords
|
||||
xx(light_softshadowradius)
|
||||
xx(light_strength)
|
||||
xx(light_linearity)
|
||||
xx(light_noshadowmap)
|
||||
xx(light_dontlightactors)
|
||||
xx(light_dontlightmap)
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static FDynamicLight *GetLight(FLevelLocals *Level)
|
|||
}
|
||||
|
||||
|
||||
static inline constexpr float calcStrength(float radius)
|
||||
float LightCalcStrength(float radius)
|
||||
{
|
||||
radius *= 2; // radius in shaders is actualy diameter, so multiply it here to match
|
||||
return std::min(1500.0f, (radius * radius) / 10);
|
||||
|
|
@ -122,12 +122,10 @@ void AttachLight(AActor *self)
|
|||
light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags);
|
||||
light->pArgs = self->args;
|
||||
light->pSoftShadowRadius = &self->FloatVar(NAME_SoftShadowRadius);
|
||||
light->pStrength = &self->FloatVar(NAME_LightStrength);
|
||||
light->pLinearity = &self->FloatVar(NAME_LightLinearity);
|
||||
|
||||
if(*light->pStrength <= 0)
|
||||
{
|
||||
*light->pStrength = -calcStrength(light->m_currentRadius);
|
||||
}
|
||||
light->lightStrength = LightCalcStrength(light->pArgs[LIGHT_INTENSITY]);
|
||||
|
||||
|
||||
light->specialf1 = DAngle::fromDeg(double(self->SpawnAngle)).Normalized360().Degrees();
|
||||
light->Sector = self->Sector;
|
||||
|
|
@ -250,10 +248,7 @@ void FDynamicLight::Activate()
|
|||
}
|
||||
if (m_currentRadius <= 0) m_currentRadius = 1;
|
||||
|
||||
if(pStrength && *pStrength <= 0)
|
||||
{
|
||||
*pStrength = -calcStrength(m_currentRadius);
|
||||
}
|
||||
lightStrength = LightCalcStrength(m_currentRadius);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -377,9 +372,9 @@ void FDynamicLight::Tick()
|
|||
if (m_currentRadius <= 0) m_currentRadius = 1;
|
||||
|
||||
|
||||
if(pStrength && *pStrength <= 0 && oldradius != m_currentRadius)
|
||||
if(oldradius != m_currentRadius)
|
||||
{
|
||||
*pStrength = -calcStrength(m_currentRadius);
|
||||
lightStrength = LightCalcStrength(m_currentRadius);
|
||||
}
|
||||
UpdateLocation();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ protected:
|
|||
DAngle m_spotOuterAngle = DAngle::fromDeg(25.0);
|
||||
DAngle m_pitch = nullAngle;
|
||||
double SoftShadowRadius = 5.0;
|
||||
double Strength = 0.0;
|
||||
double Linearity = 0.0;
|
||||
|
||||
friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def);
|
||||
};
|
||||
|
|
@ -225,7 +225,8 @@ 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); }
|
||||
float GetLinearity() const { return (float)(*pLinearity); }
|
||||
float GetStrength() const { return lightStrength; }
|
||||
int GetRed() const { return pArgs[LIGHT_RED]; }
|
||||
int GetGreen() const { return pArgs[LIGHT_GREEN]; }
|
||||
int GetBlue() const { return pArgs[LIGHT_BLUE]; }
|
||||
|
|
@ -274,7 +275,7 @@ public:
|
|||
const LightFlags *pLightFlags;
|
||||
const double* pSoftShadowRadius; // Softshadows. Physical size of the light source
|
||||
|
||||
double* pStrength; // Softshadows. Physical size of the light source
|
||||
const double* pLinearity;
|
||||
|
||||
double specialf1;
|
||||
FDynamicLight *next, *prev;
|
||||
|
|
@ -296,7 +297,7 @@ public:
|
|||
bool swapped;
|
||||
bool explicitpitch;
|
||||
|
||||
double tmpStrength;
|
||||
float lightStrength;
|
||||
|
||||
// Locations in the level mesh light list. Ends with index = 0 or all entries used
|
||||
enum { max_levelmesh_entries = 4 };
|
||||
|
|
|
|||
|
|
@ -6214,9 +6214,9 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position)
|
|||
mobj->FloatVar(NAME_SoftShadowRadius) = 5.0;
|
||||
}
|
||||
|
||||
if (mthing->LightStrength > 0.0)
|
||||
if (mthing->LightLinearity > 0.0)
|
||||
{
|
||||
mobj->FloatVar(NAME_LightStrength) = mthing->LightStrength;
|
||||
mobj->FloatVar(NAME_LightLinearity) = mthing->LightLinearity;
|
||||
}
|
||||
|
||||
if (mthing->LightNoShadowMap)
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TDeletingArray<FLightD
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern float LightCalcStrength(float radius);
|
||||
|
||||
void FLightDefaults::ApplyProperties(FDynamicLight * light) const
|
||||
{
|
||||
auto oldtype = light->lighttype;
|
||||
|
|
@ -128,15 +130,8 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const
|
|||
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->pLinearity = &Linearity;
|
||||
light->lightStrength = LightCalcStrength(light->pArgs[LIGHT_INTENSITY]);
|
||||
|
||||
light->pLightFlags = &m_lightFlags;
|
||||
if (m_lightFlags & LF_SPOT)
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
|
|||
// Store attenuate flag in the sign bit of the float.
|
||||
if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex;
|
||||
|
||||
float lightType = 0.0f;
|
||||
bool lightType = false;
|
||||
float spotInnerAngle = 0.0f;
|
||||
float spotOuterAngle = 0.0f;
|
||||
float spotDirX = 0.0f;
|
||||
|
|
@ -128,7 +128,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
|
|||
float spotDirZ = 0.0f;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
lightType = 1.0f;
|
||||
lightType = true;
|
||||
spotInnerAngle = (float)light->pSpotInnerAngle->Cos();
|
||||
spotOuterAngle = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
|
|
@ -139,15 +139,19 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
|
|||
spotDirY = float(-negPitch.Sin());
|
||||
spotDirZ = float(-Angle.Sin() * xzLen);
|
||||
}
|
||||
|
||||
|
||||
float softShadowRadius = light->GetSoftShadowRadius();
|
||||
|
||||
float linearity = light->GetLinearity();
|
||||
|
||||
float strength = light->GetStrength();
|
||||
|
||||
float *data = &dld.arrays[i][dld.arrays[i].Reserve(16)];
|
||||
data[0] = float(pos.X);
|
||||
data[1] = float(pos.Z);
|
||||
data[2] = float(pos.Y);
|
||||
data[3] = radius;
|
||||
data[3] = lightType ? -radius : radius;
|
||||
data[4] = r;
|
||||
data[5] = g;
|
||||
data[6] = b;
|
||||
|
|
@ -155,7 +159,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
|
|||
data[8] = spotDirX;
|
||||
data[9] = spotDirY;
|
||||
data[10] = spotDirZ;
|
||||
data[11] = lightType;
|
||||
data[11] = std::clamp(linearity, 0.0f, 1.0f);
|
||||
data[12] = spotInnerAngle;
|
||||
data[13] = spotOuterAngle;
|
||||
data[14] = softShadowRadius;
|
||||
|
|
@ -172,7 +176,6 @@ void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVec
|
|||
z += sundir.Z * dist;
|
||||
|
||||
int i = 0;
|
||||
float lightType = 0.0f;
|
||||
float spotInnerAngle = 0.0f;
|
||||
float spotOuterAngle = 0.0f;
|
||||
float spotDirX = 0.0f;
|
||||
|
|
@ -194,7 +197,7 @@ void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVec
|
|||
data[8] = spotDirX;
|
||||
data[9] = spotDirY;
|
||||
data[10] = spotDirZ;
|
||||
data[11] = lightType;
|
||||
data[11] = 0.0f; // unused
|
||||
data[12] = spotInnerAngle;
|
||||
data[13] = spotOuterAngle;
|
||||
data[14] = 0.0f; // unused
|
||||
|
|
|
|||
|
|
@ -4,19 +4,21 @@ vec3 lightContribution(int i, vec3 normal)
|
|||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float radius = abs(lightpos.w);
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
if (radius < lightdistance)
|
||||
return vec3(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
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, lightspot2.w);
|
||||
float attenuation = distanceAttenuation(lightdistance, radius, lightspot2.w, lightspot1.w);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightpos.w < 0.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); // Sign bit is the spotlight flag
|
||||
|
||||
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ 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, lightspot2.w);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), abs(lightpos.w), lightspot2.w, lightspot1.w);
|
||||
if (lightpos.w < 0.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); // Sign bit is the spotlight flag
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
|
|
@ -119,9 +119,9 @@ 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, lightspot2.w);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
float attenuation = distanceAttenuation(distance(lightpos.xyz, pixelpos.xyz), abs(lightpos.w), lightspot2.w, lightspot1.w);
|
||||
if (lightpos.w < 0.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); // Sign bit is the spotlight flag
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
#ifdef LIGHT_ATTENUATION_INVERSE_SQUARE
|
||||
|
||||
float distanceAttenuation(float dist, float radius, float strength)
|
||||
float distanceAttenuation(float dist, float radius, float strength, float linearity)
|
||||
{
|
||||
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;
|
||||
return mix((b * b) / (dist * dist + 1.0) * strength, clamp((radius - dist) / radius, 0.0, 1.0), linearity);
|
||||
}
|
||||
|
||||
#else //elif defined(LIGHT_ATTENUATION_LINEAR)
|
||||
|
||||
#define distanceAttenuation(dist, radius, strength) clamp((radius - dist) / radius, 0.0, 1.0)
|
||||
#define distanceAttenuation(dist, radius, strength, linearity) clamp((radius - dist) / radius, 0.0, 1.0)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,15 +3,17 @@ vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA, float
|
|||
vec4 lightpos = lights[i];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float radius = abs(lightpos.w);
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
if (radius < lightdistance)
|
||||
return vec2(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
float attenuation = distanceAttenuation(lightdistance, lightpos.w, lightspot2.w);
|
||||
float attenuation = distanceAttenuation(lightdistance, radius, lightspot2.w, lightspot1.w);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightpos.w < 0.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); // Sign bit is the spotlight flag
|
||||
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ class DynamicLight : Actor
|
|||
double SpotInnerAngle;
|
||||
double SpotOuterAngle;
|
||||
double SoftShadowRadius;
|
||||
double LightStrength; // used for Inverse-square falloff lights
|
||||
double LightLinearity; // used for Inverse-square falloff lights
|
||||
private int lighttype;
|
||||
private int lightflags;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue