Reset lighting table and lightmaps

This commit is contained in:
Jarrod Doyle 2024-10-05 14:52:09 +01:00
parent ea72c3af4a
commit ab738203d6
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
2 changed files with 183 additions and 116 deletions

View File

@ -274,16 +274,16 @@ public class WorldRep : IChunk
AddLight(layer, x, y, c.Z, c.Y, c.X);
}
public readonly void Reset(Vector3 ambientLight, bool hdr)
public void Reset(Vector3 ambientLight, bool hdr)
{
// TODO: This should set to one layer when we write our own lighttable etc
var bytesPerLayer = Width * Height * Bpp;
for (var i = 0; i < Layers; i++)
{
Pixels.Clear();
Pixels.Add(new byte[bytesPerLayer]);
Layers = 1;
for (var j = 0; j < bytesPerLayer; j++)
{
Pixels[i][j] = 0;
}
Pixels[0][j] = 0;
}
for (var y = 0; y < Height; y++)
@ -568,30 +568,31 @@ public class WorldRep : IChunk
public int LightCount;
public int DynamicLightCount;
public int AnimMapCount;
public LightData[] Lights;
public List<LightData> Lights;
public LightData[] ScratchpadLights;
public AnimCellMap[] AnimCellMaps;
public List<AnimCellMap> AnimCellMaps;
// TODO: Support olddark
public LightTable(BinaryReader reader)
{
LightCount = reader.ReadInt32();
DynamicLightCount = reader.ReadInt32();
Lights = new LightData[LightCount + DynamicLightCount];
for (var i = 0; i < Lights.Length; i++)
var totalLightCount = LightCount + DynamicLightCount;
Lights = new List<LightData>(totalLightCount);
for (var i = 0; i < totalLightCount; i++)
{
Lights[i] = new LightData(reader);
Lights.Add(new LightData(reader));
}
ScratchpadLights = new LightData[32];
for (var i = 0; i < ScratchpadLights.Length; i++)
for (var i = 0; i < 32; i++)
{
ScratchpadLights[i] = new LightData(reader);
}
AnimMapCount = reader.ReadInt32();
AnimCellMaps = new AnimCellMap[AnimMapCount];
for (var i = 0; i < AnimCellMaps.Length; i++)
AnimCellMaps = new List<AnimCellMap>(AnimMapCount);
for (var i = 0; i < AnimMapCount; i++)
{
AnimCellMaps[i] = new AnimCellMap(reader);
AnimCellMaps.Add(new AnimCellMap(reader));
}
}
@ -613,6 +614,29 @@ public class WorldRep : IChunk
map.Write(writer);
}
}
public void Reset()
{
LightCount = 0;
DynamicLightCount = 0;
AnimMapCount = 0;
Lights.Clear();
AnimCellMaps.Clear();
}
public void AddLight(LightData data, bool dynamicLight = false)
{
if (dynamicLight)
{
DynamicLightCount++;
}
else
{
LightCount++;
}
Lights.Add(data);
}
}
public ChunkHeader Header { get; set; }

View File

@ -57,8 +57,6 @@ class Program
var mis = Timing.TimeStage("Parse DB", () => new DbFile(misPath));
var hierarchy = Timing.TimeStage("Build Hierarchy", () => BuildHierarchy(misPath, mis));
var lights = Timing.TimeStage("Gather Lights", () => BuildLightList(mis, hierarchy, campaign));
// Build embree mesh
if (!mis.Chunks.TryGetValue("WREXT", out var wrRaw))
return;
@ -75,6 +73,7 @@ class Program
if (!mis.Chunks.TryGetValue("RENDPARAMS", out var rendParamsRaw))
return;
var ambient = ((RendParams)rendParamsRaw).ambientLight * 255;
var lights = Timing.TimeStage("Gather Lights", () => BuildLightList(mis, hierarchy, campaign));
Timing.TimeStage("Light", () => CastSceneParallel(scene, worldRep, [.. lights], ambient));
var dir = Path.GetDirectoryName(misPath);
@ -109,25 +108,45 @@ class Program
};
}
// Get list of brush lights, and object lights (ignore anim lights for now)
private static List<Light> BuildLightList(DbFile mis, ObjectHierarchy hierarchy, ResourcePathManager.CampaignResources campaign)
// Gather all the brush, object, and anim ligths. Resets the lighting table
// TODO: Handle dynamic lights
private static List<Light> BuildLightList(
DbFile mis,
ObjectHierarchy hierarchy,
ResourcePathManager.CampaignResources campaign)
{
var lights = new List<Light>();
if (mis.Chunks.TryGetValue("BRLIST", out var brListRaw))
// Get the chunks we need
if (!mis.TryGetChunk<WorldRep>("WREXT", out var worldRep) ||
!mis.TryGetChunk<BrList>("BRLIST", out var brList))
{
var brList = (BrList)brListRaw;
return lights;
}
worldRep.LightingTable.Reset();
foreach (var brush in brList.Brushes)
{
if (brush.media == BrList.Brush.Media.Light)
{
var sz = brush.size;
lights.Add(new Light
var light = new Light
{
position = brush.position,
color = HsbToRgb(sz.Y, sz.Z, Math.Min(sz.X, 255.0f)),
radius = float.MaxValue,
r2 = float.MaxValue,
};
lights.Add(light);
worldRep.LightingTable.AddLight(new WorldRep.LightTable.LightData
{
Location = light.position,
Direction = light.spotlightDir,
Color = light.color / 32.0f, // TODO: This is based on light_scale config var
InnerAngle = -1.0f,
Radius = 0,
});
}
else if (brush.media == BrList.Brush.Media.Object)
@ -146,6 +165,7 @@ class Program
{
position = brush.position,
spotlightDir = -Vector3.UnitZ,
spotlightInnerAngle = -1.0f,
};
if (propModelname != null)
@ -203,10 +223,22 @@ class Program
}
lights.Add(light);
worldRep.LightingTable.AddLight(new WorldRep.LightTable.LightData
{
Location = light.position,
Direction = light.spotlightDir,
Color = light.color / 32.0f, // TODO: This is based on light_scale config var
InnerAngle = light.spotlightInnerAngle,
OuterAngle = light.spotlightOuterAngle,
Radius = propLight.Radius,
});
}
if (propAnimLight != null)
{
var lightIndex = worldRep.LightingTable.LightCount;
propAnimLight.LightTableLightIndex = (ushort)lightIndex;
var light = new Light
{
position = baseLight.position + propAnimLight.Offset,
@ -228,7 +260,15 @@ class Program
}
lights.Add(light);
}
worldRep.LightingTable.AddLight(new WorldRep.LightTable.LightData
{
Location = light.position,
Direction = light.spotlightDir,
Color = light.color / 32.0f, // TODO: This is based on light_scale config var
InnerAngle = light.spotlightInnerAngle,
OuterAngle = light.spotlightOuterAngle,
Radius = propAnimLight.Radius,
});
}
}
}
@ -314,6 +354,8 @@ class Program
Parallel.ForEach(wr.Cells, cell =>
{
// TODO: Reset cell anim light count and palette
var numPolys = cell.PolyCount;
var numRenderPolys = cell.RenderPolyCount;
var numPortalPolys = cell.PortalPolyCount;
@ -335,6 +377,7 @@ class Program
var info = cell.LightList[polyIdx];
var lightmap = cell.Lightmaps[polyIdx];
info.AnimLightBitmask = 0;
lightmap.Reset(ambientLight, hdr);
// Get world position of lightmap (0, 0) (+0.5 so we cast from the center of a pixel)