Compare commits

..

No commits in common. "fe100bb938a51cdbcd1b8b8155103c3483b99695" and "ca017e3f7bae1e30aa9d9b9b77beff1edd9b5b73" have entirely different histories.

4 changed files with 27 additions and 158 deletions

View File

@ -1,73 +0,0 @@
namespace KeepersCompound.LGS.Database.Chunks;
public enum SoftnessMode
{
Standard,
HighFourPoint,
HighFivePoint,
HighNinePoint,
MediumFourPoint,
MediumFivePoint,
MediumNinePoint,
LowFourPoint,
}
public class LmParams : IChunk
{
public enum LightingMode
{
Quick,
Raycast,
Objcast,
}
public enum DepthMode
{
Lm16,
Lm32,
Lm32x,
}
public ChunkHeader Header { get; set; }
public float Attenuation { get; set; }
public float Saturation { get; set; }
public LightingMode ShadowType { get; set; }
public SoftnessMode ShadowSoftness { get; set; }
public float CenterWeight { get; set; }
public DepthMode ShadowDepth { get; set; }
public bool LightmappedWater { get; set; }
public int LightmapScale { get; set; }
private int _dataSize;
private uint _unknown;
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
{
_dataSize = reader.ReadInt32();
Attenuation = reader.ReadSingle();
Saturation = reader.ReadSingle();
ShadowType = (LightingMode)reader.ReadUInt32();
ShadowSoftness = (SoftnessMode)reader.ReadUInt32();
CenterWeight = reader.ReadSingle();
ShadowDepth = (DepthMode)reader.ReadUInt32();
LightmappedWater = reader.ReadBoolean();
reader.ReadBytes(3);
LightmapScale = reader.ReadInt32();
_unknown = reader.ReadUInt32();
}
public void WriteData(BinaryWriter writer)
{
writer.Write(_dataSize);
writer.Write(Attenuation);
writer.Write(Saturation);
writer.Write((uint)ShadowType);
writer.Write((uint)ShadowSoftness);
writer.Write(CenterWeight);
writer.Write((uint)ShadowDepth);
writer.Write(LightmappedWater);
writer.Write(new byte[3]);
writer.Write(LightmapScale);
writer.Write(_unknown);
}
}

View File

@ -150,7 +150,6 @@ public class DbFile
"TXLIST" => new TxList(),
"WREXT" => new WorldRep(),
"BRLIST" => new BrList(),
"LM_PARAM" => new LmParams(),
"RENDPARAMS" => new RendParams(),
"P$ModelName" => new PropertyChunk<PropLabel>(),
"P$Scale" => new PropertyChunk<PropVector>(),

View File

@ -10,10 +10,9 @@ public class LightMapper
{
private class Settings
{
public Vector3 AmbientLight;
public bool Hdr;
public SoftnessMode MultiSampling;
public float MultiSamplingCenterWeight;
public bool MultiSampling;
public Vector3 AmbientLight;
}
private ResourcePathManager.CampaignResources _campaign;
@ -37,11 +36,10 @@ public class LightMapper
_lights = [];
}
public void Light()
public void Light(bool multiSampling)
{
// TODO: Throw?
if (!_mission.TryGetChunk<RendParams>("RENDPARAMS", out var rendParams) ||
!_mission.TryGetChunk<LmParams>("LM_PARAM", out var lmParams) ||
!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep))
{
return;
@ -51,16 +49,13 @@ public class LightMapper
{
Hdr = worldRep.DataHeader.LightmapFormat == 2,
AmbientLight = rendParams.ambientLight * 255,
MultiSampling = lmParams.ShadowSoftness,
MultiSamplingCenterWeight = lmParams.CenterWeight,
MultiSampling = multiSampling,
};
Timing.TimeStage("Gather Lights", BuildLightList);
Timing.TimeStage("Set Light Indices", SetCellLightIndices);
Timing.TimeStage("Trace Scene", () => TraceScene(settings));
Timing.TimeStage("Update AnimLight Cell Mapping", SetAnimLightCellMaps);
// lmParams.ShadowType = LmParams.LightingMode.Raycast;
}
public void Save(string missionName)
@ -440,11 +435,26 @@ public class LightMapper
var pos = topLeft;
pos += x * 0.25f * renderPoly.TextureVectors.Item1;
pos += y * 0.25f * renderPoly.TextureVectors.Item2;
var hit = false;
var strength = 0f;
if (settings.MultiSampling)
{
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 (TracePixelMultisampled(
settings.MultiSampling, light, pos, renderPoly.Center, plane, planeMapper, v2ds,
renderPoly.TextureVectors.Item1, renderPoly.TextureVectors.Item2,
settings.MultiSamplingCenterWeight, out var strength))
if (hit)
{
// 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
@ -474,73 +484,6 @@ 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)
{
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;
}
bool NinePoint(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 s1);
hit |= TracePixel(light, pos + xOffset - yOffset, polyCenter, plane, planeMapper, v2ds, out var s2);
hit |= TracePixel(light, pos - xOffset + yOffset, polyCenter, plane, planeMapper, v2ds, out var s3);
hit |= TracePixel(light, pos + xOffset + yOffset, polyCenter, plane, planeMapper, v2ds, out var s4);
hit |= TracePixel(light, pos - xOffset, polyCenter, plane, planeMapper, v2ds, out var s5);
hit |= TracePixel(light, pos + xOffset, polyCenter, plane, planeMapper, v2ds, out var s6);
hit |= TracePixel(light, pos - yOffset, polyCenter, plane, planeMapper, v2ds, out var s7);
hit |= TracePixel(light, pos + yOffset, polyCenter, plane, planeMapper, v2ds, out var s8);
hit |= TracePixel(light, pos, polyCenter, plane, planeMapper, v2ds, out var centerStrength);
strength = (s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8) / 8f;
strength = (1.0f - centerWeight) * strength + centerWeight * centerStrength;
return hit;
}
return mode switch {
SoftnessMode.Standard when light.QuadLit => FourPoint(4f, out strength),
SoftnessMode.HighFourPoint => FourPoint(4f, out strength),
SoftnessMode.HighFivePoint => FivePoint(4f, out strength),
SoftnessMode.HighNinePoint => NinePoint(4f, out strength),
SoftnessMode.MediumFourPoint => FourPoint(8f, out strength),
SoftnessMode.MediumFivePoint => FivePoint(8f, out strength),
SoftnessMode.MediumNinePoint => NinePoint(8f, out strength),
SoftnessMode.LowFourPoint => FourPoint(16f, out strength),
_ => TracePixel(light, pos, polyCenter, plane, planeMapper, v2ds, out strength)
};
}
private bool TracePixel(
Light light,
Vector3 pos,
@ -548,10 +491,8 @@ public class LightMapper
Plane plane,
MathUtils.PlanePointMapper planeMapper,
Vector2[] v2ds,
out float strength)
ref float strength)
{
strength = 0f;
// Embree has robustness issues when hitting poly edges which
// results in false misses. To alleviate this we pre-push everything
// slightly towards the center of the poly.

View File

@ -21,13 +21,15 @@ public class LightCommand : ICommand
public required string MissionName { get; init; }
[CommandOption("output", 'o', Description = "Name of output file excluding extension.")]
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)
{
Timing.Reset();
var lightMapper = new LightMapper(InstallPath, CampaignName, MissionName);
lightMapper.Light();
lightMapper.Light(MultiSampling);
lightMapper.Save(OutputName);
Timing.LogAll();