Split lightmap pixels array into layers

This commit is contained in:
Jarrod Doyle 2024-10-04 18:49:37 +01:00
parent 9251685d26
commit b9eae0e437
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
2 changed files with 54 additions and 39 deletions

View File

@ -152,7 +152,7 @@ public class WorldRep : IChunk
public struct Lightmap public struct Lightmap
{ {
public byte[] Pixels { get; set; } public List<byte[]> Pixels { get; set; }
public int Layers; public int Layers;
public int Width; public int Width;
@ -161,10 +161,14 @@ public class WorldRep : IChunk
public Lightmap(BinaryReader reader, byte width, byte height, uint bitmask, int bytesPerPixel) public Lightmap(BinaryReader reader, byte width, byte height, uint bitmask, int bytesPerPixel)
{ {
var count = 1 + BitOperations.PopCount(bitmask); var layers = 1 + BitOperations.PopCount(bitmask);
var length = bytesPerPixel * width * height * count; var length = bytesPerPixel * width * height;
Pixels = reader.ReadBytes(length); Pixels = new List<byte[]>();
Layers = count; for (var i = 0; i < layers; i++)
{
Pixels.Add(reader.ReadBytes(length));
}
Layers = layers;
Width = width; Width = width;
Height = height; Height = height;
Bpp = bytesPerPixel; Bpp = bytesPerPixel;
@ -177,17 +181,18 @@ public class WorldRep : IChunk
return Vector4.Zero; return Vector4.Zero;
} }
var idx = 0 + x * Bpp + y * Bpp * Width + layer * Bpp * Width * Height; var pLayer = Pixels[(int)layer];
var idx = x * Bpp + y * Bpp * Width;
switch (Bpp) switch (Bpp)
{ {
case 1: case 1:
var raw1 = Pixels[idx]; var raw1 = pLayer[idx];
return new Vector4(raw1, raw1, raw1, 255) / 255.0f; return new Vector4(raw1, raw1, raw1, 255) / 255.0f;
case 2: case 2:
var raw2 = Pixels[idx] + (Pixels[idx + 1] << 8); var raw2 = pLayer[idx] + (pLayer[idx + 1] << 8);
return new Vector4(raw2 & 31, (raw2 >> 5) & 31, (raw2 >> 10) & 31, 31) / 31.0f; return new Vector4(raw2 & 31, (raw2 >> 5) & 31, (raw2 >> 10) & 31, 31) / 31.0f;
case 4: case 4:
return new Vector4(Pixels[idx + 2], Pixels[idx + 1], Pixels[idx], Pixels[idx + 3]) / 255.0f; return new Vector4(pLayer[idx + 2], pLayer[idx + 1], pLayer[idx], pLayer[idx + 3]) / 255.0f;
default: default:
return Vector4.Zero; return Vector4.Zero;
} }
@ -198,7 +203,8 @@ public class WorldRep : IChunk
ArgumentOutOfRangeException.ThrowIfLessThan(layer, 0, nameof(layer)); ArgumentOutOfRangeException.ThrowIfLessThan(layer, 0, nameof(layer));
ArgumentOutOfRangeException.ThrowIfGreaterThan(layer, Layers, nameof(layer)); ArgumentOutOfRangeException.ThrowIfGreaterThan(layer, Layers, nameof(layer));
var pIdx = layer * Bpp * Width * Height; var pLayer = Pixels[layer];
var pIdx = 0;
var length = 4 * Width * Height; var length = 4 * Width * Height;
var bytes = new byte[length]; var bytes = new byte[length];
for (var i = 0; i < length; i += 4, pIdx += Bpp) for (var i = 0; i < length; i += 4, pIdx += Bpp)
@ -206,24 +212,24 @@ public class WorldRep : IChunk
switch (Bpp) switch (Bpp)
{ {
case 1: case 1:
var raw1 = Pixels[pIdx]; var raw1 = pLayer[pIdx];
bytes[i] = raw1; bytes[i] = raw1;
bytes[i + 1] = raw1; bytes[i + 1] = raw1;
bytes[i + 2] = raw1; bytes[i + 2] = raw1;
bytes[i + 3] = 255; bytes[i + 3] = 255;
break; break;
case 2: case 2:
var raw2 = Pixels[pIdx] + (Pixels[pIdx + 1] << 8); var raw2 = pLayer[pIdx] + (pLayer[pIdx + 1] << 8);
bytes[i] = (byte)(255 * (raw2 & 31) / 31.0f); bytes[i] = (byte)(255 * (raw2 & 31) / 31.0f);
bytes[i + 1] = (byte)(255 * ((raw2 >> 5) & 31) / 31.0f); bytes[i + 1] = (byte)(255 * ((raw2 >> 5) & 31) / 31.0f);
bytes[i + 2] = (byte)(255 * ((raw2 >> 10) & 31) / 31.0f); bytes[i + 2] = (byte)(255 * ((raw2 >> 10) & 31) / 31.0f);
bytes[i + 3] = 255; bytes[i + 3] = 255;
break; break;
case 4: case 4:
bytes[i] = Pixels[pIdx + 2]; bytes[i] = pLayer[pIdx + 2];
bytes[i + 1] = Pixels[pIdx + 1]; bytes[i + 1] = pLayer[pIdx + 1];
bytes[i + 2] = Pixels[pIdx]; bytes[i + 2] = pLayer[pIdx];
bytes[i + 3] = Pixels[pIdx + 3]; bytes[i + 3] = pLayer[pIdx + 3];
break; break;
} }
} }
@ -234,11 +240,12 @@ public class WorldRep : IChunk
// TODO: This ONLY works for rgba (bpp = 4)!!! // TODO: This ONLY works for rgba (bpp = 4)!!!
public readonly void AddLight(int layer, int x, int y, float r, float g, float b) public readonly void AddLight(int layer, int x, int y, float r, float g, float b)
{ {
var idx = (x + y * Width + layer * Width * Height) * Bpp; var idx = (x + y * Width) * Bpp;
Pixels[idx] = (byte)Math.Clamp(Pixels[idx] + r, 0, 255); var pLayer = Pixels[layer];
Pixels[idx + 1] = (byte)Math.Clamp(Pixels[idx + 1] + g, 0, 255); pLayer[idx] = (byte)Math.Clamp(pLayer[idx] + r, 0, 255);
Pixels[idx + 2] = (byte)Math.Clamp(Pixels[idx + 2] + b, 0, 255); pLayer[idx + 1] = (byte)Math.Clamp(pLayer[idx + 1] + g, 0, 255);
Pixels[idx + 3] = 255; pLayer[idx + 2] = (byte)Math.Clamp(pLayer[idx + 2] + b, 0, 255);
pLayer[idx + 3] = 255;
} }
public readonly void AddLight(int layer, int x, int y, Vector3 color, float strength, bool hdr) public readonly void AddLight(int layer, int x, int y, Vector3 color, float strength, bool hdr)
@ -267,9 +274,33 @@ 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)
{
// 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++)
{
for (var j = 0; j < bytesPerLayer; j++)
{
Pixels[i][j] = 0;
}
}
for (var y = 0; y < Height; y++)
{
for (var x = 0; x < Width; x++)
{
AddLight(0, x, y, ambientLight, 1.0f, hdr);
}
}
}
public readonly void Write(BinaryWriter writer) public readonly void Write(BinaryWriter writer)
{ {
writer.Write(Pixels); foreach (var layer in Pixels)
{
writer.Write(layer);
}
} }
} }

View File

@ -335,7 +335,7 @@ class Program
var info = cell.LightList[polyIdx]; var info = cell.LightList[polyIdx];
var lightmap = cell.Lightmaps[polyIdx]; var lightmap = cell.Lightmaps[polyIdx];
ResetLightmap(ambientLight, lightmap, 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)
var topLeft = cell.Vertices[cell.Indices[cellIdxOffset]]; var topLeft = cell.Vertices[cell.Indices[cellIdxOffset]];
@ -510,20 +510,4 @@ class Program
return strength; return strength;
} }
private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap, bool hdr)
{
for (var i = 0; i < lightmap.Pixels.Length; i++)
{
lightmap.Pixels[i] = 0;
}
for (var y = 0; y < lightmap.Height; y++)
{
for (var x = 0; x < lightmap.Width; x++)
{
lightmap.AddLight(0, x, y, ambientLight, 1.0f, hdr);
}
}
}
} }