Add support for most of the shadow softness settings

This commit is contained in:
Jarrod Doyle 2024-10-29 18:01:50 +00:00
parent ff91ad567b
commit 99697180cd
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
2 changed files with 84 additions and 27 deletions

View File

@ -10,9 +10,10 @@ public class LightMapper
{ {
private class Settings private class Settings
{ {
public bool Hdr;
public bool MultiSampling;
public Vector3 AmbientLight; public Vector3 AmbientLight;
public bool Hdr;
public SoftnessMode MultiSampling;
public float MultiSamplingCenterWeight;
} }
private ResourcePathManager.CampaignResources _campaign; private ResourcePathManager.CampaignResources _campaign;
@ -36,10 +37,11 @@ public class LightMapper
_lights = []; _lights = [];
} }
public void Light(bool multiSampling) public void Light()
{ {
// TODO: Throw? // TODO: Throw?
if (!_mission.TryGetChunk<RendParams>("RENDPARAMS", out var rendParams) || if (!_mission.TryGetChunk<RendParams>("RENDPARAMS", out var rendParams) ||
!_mission.TryGetChunk<LmParams>("LM_PARAM", out var lmParams) ||
!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep)) !_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep))
{ {
return; return;
@ -49,13 +51,16 @@ public class LightMapper
{ {
Hdr = worldRep.DataHeader.LightmapFormat == 2, Hdr = worldRep.DataHeader.LightmapFormat == 2,
AmbientLight = rendParams.ambientLight * 255, AmbientLight = rendParams.ambientLight * 255,
MultiSampling = multiSampling, MultiSampling = lmParams.ShadowSoftness,
MultiSamplingCenterWeight = lmParams.CenterWeight,
}; };
Timing.TimeStage("Gather Lights", BuildLightList); Timing.TimeStage("Gather Lights", BuildLightList);
Timing.TimeStage("Set Light Indices", SetCellLightIndices); Timing.TimeStage("Set Light Indices", SetCellLightIndices);
Timing.TimeStage("Trace Scene", () => TraceScene(settings)); Timing.TimeStage("Trace Scene", () => TraceScene(settings));
Timing.TimeStage("Update AnimLight Cell Mapping", SetAnimLightCellMaps); Timing.TimeStage("Update AnimLight Cell Mapping", SetAnimLightCellMaps);
// lmParams.ShadowType = LmParams.LightingMode.Raycast;
} }
public void Save(string missionName) public void Save(string missionName)
@ -436,25 +441,10 @@ public class LightMapper
pos += x * 0.25f * renderPoly.TextureVectors.Item1; pos += x * 0.25f * renderPoly.TextureVectors.Item1;
pos += y * 0.25f * renderPoly.TextureVectors.Item2; pos += y * 0.25f * renderPoly.TextureVectors.Item2;
var hit = false; if (TracePixelMultisampled(
var strength = 0f; settings.MultiSampling, light, pos, renderPoly.Center, plane, planeMapper, v2ds,
renderPoly.TextureVectors.Item1, renderPoly.TextureVectors.Item2,
if (settings.MultiSampling) settings.MultiSamplingCenterWeight, out var strength))
{
var xOffset = 0.25f * 0.25f * renderPoly.TextureVectors.Item1;
var yOffset = 0.25f * 0.25f * renderPoly.TextureVectors.Item2;
hit |= TracePixel(light, pos - xOffset - yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
hit |= TracePixel(light, pos + xOffset - yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
hit |= TracePixel(light, pos - xOffset + yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
hit |= TracePixel(light, pos + xOffset + yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
strength /= 4f;
}
else
{
hit |= TracePixel(light, pos, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
}
if (hit)
{ {
// If we're an anim light there's a lot of stuff we need to update // If we're an anim light there's a lot of stuff we need to update
// Firstly we need to add the light to the cells anim light palette // Firstly we need to add the light to the cells anim light palette
@ -484,6 +474,73 @@ public class LightMapper
}); });
} }
public bool TracePixelMultisampled(
SoftnessMode mode,
Light light,
Vector3 pos,
Vector3 polyCenter,
Plane plane,
MathUtils.PlanePointMapper planeMapper,
Vector2[] v2ds,
Vector3 texU,
Vector3 texV,
float centerWeight,
out float strength)
{
bool FourPoint(float offsetScale, out float strength)
{
var hit = false;
var xOffset = texU / offsetScale;
var yOffset = texV / offsetScale;
hit |= TracePixel(light, pos - xOffset - yOffset, polyCenter, plane, planeMapper, v2ds, out var strength1);
hit |= TracePixel(light, pos + xOffset - yOffset, polyCenter, plane, planeMapper, v2ds, out var strength2);
hit |= TracePixel(light, pos - xOffset + yOffset, polyCenter, plane, planeMapper, v2ds, out var strength3);
hit |= TracePixel(light, pos + xOffset + yOffset, polyCenter, plane, planeMapper, v2ds, out var strength4);
strength = (strength1 + strength2 + strength3 + strength4) / 4f;
return hit;
}
bool FivePoint(float offsetScale, out float strength)
{
strength = 0f;
var hit = false;
hit |= TracePixel(light, pos, polyCenter, plane, planeMapper, v2ds, out var centerStrength);
hit |= FourPoint(offsetScale, out strength);
strength = (1.0f - centerWeight) * strength + centerWeight * centerStrength;
return hit;
}
strength = 0f;
var hit = false;
switch (mode)
{
case SoftnessMode.Standard when light.QuadLit:
case SoftnessMode.HighFourPoint:
hit = FourPoint(4f, out strength);
break;
case SoftnessMode.HighFivePoint:
hit = FivePoint(4f, out strength);
break;
case SoftnessMode.MediumFourPoint:
hit = FourPoint(8f, out strength);
break;
case SoftnessMode.MediumFivePoint:
hit = FivePoint(8f, out strength);
break;
case SoftnessMode.LowFourPoint:
hit = FourPoint(16f, out strength);
break;
// TODO: Work out how the 8 points are sampled hmm
case SoftnessMode.HighNinePoint:
case SoftnessMode.MediumNinePoint:
case SoftnessMode.Standard:
hit = TracePixel(light, pos, polyCenter, plane, planeMapper, v2ds, out strength);
break;
}
return hit;
}
private bool TracePixel( private bool TracePixel(
Light light, Light light,
Vector3 pos, Vector3 pos,
@ -491,8 +548,10 @@ public class LightMapper
Plane plane, Plane plane,
MathUtils.PlanePointMapper planeMapper, MathUtils.PlanePointMapper planeMapper,
Vector2[] v2ds, Vector2[] v2ds,
ref float strength) out float strength)
{ {
strength = 0f;
// Embree has robustness issues when hitting poly edges which // Embree has robustness issues when hitting poly edges which
// results in false misses. To alleviate this we pre-push everything // results in false misses. To alleviate this we pre-push everything
// slightly towards the center of the poly. // slightly towards the center of the poly.

View File

@ -21,15 +21,13 @@ public class LightCommand : ICommand
public required string MissionName { get; init; } public required string MissionName { get; init; }
[CommandOption("output", 'o', Description = "Name of output file excluding extension.")] [CommandOption("output", 'o', Description = "Name of output file excluding extension.")]
public string OutputName { get; init; } = "kc_lit"; public string OutputName { get; init; } = "kc_lit";
[CommandOption("multiSampling", 'm', Description = "Enables multi-sampled shadows. Higher quality but slower.")]
public bool MultiSampling { get; init; } = false;
public ValueTask ExecuteAsync(IConsole console) public ValueTask ExecuteAsync(IConsole console)
{ {
Timing.Reset(); Timing.Reset();
var lightMapper = new LightMapper(InstallPath, CampaignName, MissionName); var lightMapper = new LightMapper(InstallPath, CampaignName, MissionName);
lightMapper.Light(MultiSampling); lightMapper.Light();
lightMapper.Save(OutputName); lightMapper.Save(OutputName);
Timing.LogAll(); Timing.LogAll();