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); 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; 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++) for (var j = 0; j < bytesPerLayer; j++)
{ {
Pixels[i][j] = 0; Pixels[0][j] = 0;
}
} }
for (var y = 0; y < Height; y++) for (var y = 0; y < Height; y++)
@ -568,30 +568,31 @@ public class WorldRep : IChunk
public int LightCount; public int LightCount;
public int DynamicLightCount; public int DynamicLightCount;
public int AnimMapCount; public int AnimMapCount;
public LightData[] Lights; public List<LightData> Lights;
public LightData[] ScratchpadLights; public LightData[] ScratchpadLights;
public AnimCellMap[] AnimCellMaps; public List<AnimCellMap> AnimCellMaps;
// TODO: Support olddark // TODO: Support olddark
public LightTable(BinaryReader reader) public LightTable(BinaryReader reader)
{ {
LightCount = reader.ReadInt32(); LightCount = reader.ReadInt32();
DynamicLightCount = reader.ReadInt32(); DynamicLightCount = reader.ReadInt32();
Lights = new LightData[LightCount + DynamicLightCount]; var totalLightCount = LightCount + DynamicLightCount;
for (var i = 0; i < Lights.Length; i++) 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]; ScratchpadLights = new LightData[32];
for (var i = 0; i < ScratchpadLights.Length; i++) for (var i = 0; i < 32; i++)
{ {
ScratchpadLights[i] = new LightData(reader); ScratchpadLights[i] = new LightData(reader);
} }
AnimMapCount = reader.ReadInt32(); AnimMapCount = reader.ReadInt32();
AnimCellMaps = new AnimCellMap[AnimMapCount]; AnimCellMaps = new List<AnimCellMap>(AnimMapCount);
for (var i = 0; i < AnimCellMaps.Length; i++) 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); 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; } public ChunkHeader Header { get; set; }

View File

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