From f4d5dcbd5aefcb45f532ccbe8468ee2d7562438b Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Sun, 16 Feb 2025 11:44:02 +0000 Subject: [PATCH] Apply LmParams attenuation --- KeepersCompound.Lightmapper/Light.cs | 20 ++++++++++++-------- KeepersCompound.Lightmapper/LightMapper.cs | 13 ++++++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/KeepersCompound.Lightmapper/Light.cs b/KeepersCompound.Lightmapper/Light.cs index 7c77426..d6c1b07 100644 --- a/KeepersCompound.Lightmapper/Light.cs +++ b/KeepersCompound.Lightmapper/Light.cs @@ -56,23 +56,26 @@ public class Light SpotlightDir = Vector3.Normalize(Vector3.Transform(vhotLightDir, scale * rotate)); } - public float StrengthAtPoint(Vector3 point, Plane plane, uint lightCutoff) + public float StrengthAtPoint(Vector3 point, Plane plane, uint lightCutoff, float attenuation) { // Calculate light strength at a given point. As far as I can tell - // this is exact to Dark (I'm a genius??). It's just an inverse distance - // falloff with diffuse angle, except we have to scale the length. + // this is exact to Dark (I'm a genius??). var dir = Position - point; - var angle = Vector3.Dot(Vector3.Normalize(dir), plane.Normal); var len = dir.Length(); - var slen = len / 4.0f; - var strength = (angle + 1.0f) / slen; + dir = Vector3.Normalize(dir); + + // Base strength is a scaled inverse falloff + var strength = 4.0f / MathF.Pow(len, attenuation); + + // Diffuse light angle + strength *= 1.0f + MathF.Pow(Vector3.Dot(dir, plane.Normal), attenuation); // Inner radius starts a linear falloff to 0 at the radius if (InnerRadius != 0 && len > InnerRadius) { - strength *= (Radius - len) / (Radius - InnerRadius); + strength *= MathF.Pow((Radius - len) / (Radius - InnerRadius), attenuation); } - + // Anim lights have a (configurable) minimum light cutoff. This is checked before // spotlight multipliers are applied so we don't cutoff the spot radius falloff. if (Anim && strength * Brightness < lightCutoff) @@ -102,6 +105,7 @@ public class Light } else { + // Interestingly DromEd doesn't apply attenuation here spotlightMultiplier = (spotAngle - outer) / (inner - outer); } diff --git a/KeepersCompound.Lightmapper/LightMapper.cs b/KeepersCompound.Lightmapper/LightMapper.cs index aed3f78..cdb0763 100644 --- a/KeepersCompound.Lightmapper/LightMapper.cs +++ b/KeepersCompound.Lightmapper/LightMapper.cs @@ -22,12 +22,19 @@ public class LightMapper { public Vector3[] AmbientLight; public bool Hdr; + public float Attenuation; + public float Saturation; public SoftnessMode MultiSampling; public float MultiSamplingCenterWeight; public bool LightmappedWater; public SunSettings Sunlight; public uint AnimLightCutoff; public bool UsePvs; + + public override string ToString() + { + return $"Ambient Levels: {AmbientLight}, Hdr: {Hdr}, Attenuation: {Attenuation}, Saturation: {Saturation}"; + } } private ResourcePathManager.CampaignResources _campaign; @@ -106,6 +113,8 @@ public class LightMapper { Hdr = worldRep.DataHeader.LightmapFormat == 2, AmbientLight = [..ambientLight], + Attenuation = lmParams.Attenuation, + Saturation = lmParams.Saturation, MultiSampling = lmParams.ShadowSoftness, MultiSamplingCenterWeight = lmParams.CenterWeight, LightmappedWater = lmParams.LightmappedWater, @@ -114,6 +123,8 @@ public class LightMapper UsePvs = pvs, }; + Log.Information("Lighting Settings: {Settings}", settings); + Timing.TimeStage("Gather Lights", BuildLightList); Timing.TimeStage("Set Light Indices", () => SetCellLightIndices(settings)); Timing.TimeStage("Trace Scene", () => TraceScene(settings)); @@ -791,7 +802,7 @@ public class LightMapper if (!TraceOcclusion(_scene, light.Position, point)) { - strength += targetWeights[idx] * light.StrengthAtPoint(point, plane, settings.AnimLightCutoff); + strength += targetWeights[idx] * light.StrengthAtPoint(point, plane, settings.AnimLightCutoff, settings.Attenuation); } }