Compare commits

..

3 Commits

2 changed files with 47 additions and 47 deletions

View File

@ -243,6 +243,32 @@ public class WorldRep : IChunk
Pixels[idx + 3] = 255; Pixels[idx + 3] = 255;
} }
public void AddLight(int layer, int x, int y, Vector3 color, float strength, bool hdr)
{
if (hdr)
{
strength /= 2.0f;
}
// We need to make sure we don't go over (255, 255, 255).
// If we just do Max(color, (255, 255, 255)) then we change
// the hue/saturation of coloured lights. Got to make sure we
// maintain the colour ratios.
var c = color * strength;
var ratio = 0.0f;
foreach (var e in new float[] { c.X, c.Y, c.Z })
{
ratio = Math.Max(ratio, e / 255.0f);
}
if (ratio > 1.0f)
{
c /= ratio;
}
AddLight(layer, x, y, (byte)c.X, (byte)c.Y, (byte)c.Z);
}
public readonly void Write(BinaryWriter writer) public readonly void Write(BinaryWriter writer)
{ {
writer.Write(Pixels); writer.Write(Pixels);

View File

@ -52,7 +52,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;
Timing.TimeStage("Light", () => CastScene(scene, worldRep, [.. lights], ambient)); Timing.TimeStage("Light", () => CastSceneParallel(scene, worldRep, [.. lights], ambient));
var dir = Path.GetDirectoryName(misPath); var dir = Path.GetDirectoryName(misPath);
var filename = Path.GetFileNameWithoutExtension(misPath); var filename = Path.GetFileNameWithoutExtension(misPath);
@ -214,16 +214,12 @@ class Program
return new TriangleMesh([.. vertices], [.. indices]); return new TriangleMesh([.. vertices], [.. indices]);
} }
private static void CastScene(Raytracer scene, WorldRep wr, Light[] lights, Vector3 ambientLight) private static void CastSceneParallel(Raytracer scene, WorldRep wr, Light[] lights, Vector3 ambientLight)
{ {
var hdr = wr.DataHeader.LightmapFormat == 2; var hdr = wr.DataHeader.LightmapFormat == 2;
var cells = wr.Cells; Parallel.ForEach(wr.Cells, cell =>
for (var cellIdx = 0; cellIdx < cells.Length; cellIdx++)
{ {
Console.Write($"\rLighting cell... {cellIdx + 1}/{cells.Length}");
var cell = cells[cellIdx];
var numPolys = cell.PolyCount; var numPolys = cell.PolyCount;
var numRenderPolys = cell.RenderPolyCount; var numRenderPolys = cell.RenderPolyCount;
var numPortalPolys = cell.PortalPolyCount; var numPortalPolys = cell.PortalPolyCount;
@ -232,7 +228,7 @@ class Program
// Portal polys can be render polys (e.g. water) but we're ignoring them for now // Portal polys can be render polys (e.g. water) but we're ignoring them for now
if (numRenderPolys == 0 || numPortalPolys >= numPolys) if (numRenderPolys == 0 || numPortalPolys >= numPolys)
{ {
continue; return;
} }
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys); var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
@ -339,36 +335,8 @@ class Program
var hit = hitResult && Math.Abs(hitResult.Distance - direction.Length()) < MathUtils.Epsilon; var hit = hitResult && Math.Abs(hitResult.Distance - direction.Length()) < MathUtils.Epsilon;
if (hit) if (hit)
{ {
// Calculate light strength at a given point. As far as I can tell var strength = CalculateLightStrengthAtPoint(light, pos, plane);
// this is exact to Dark (I'm a genius??). It's just an inverse distance lightmap.AddLight(0, x, y, light.color, strength, hdr);
// falloff with diffuse angle, except we have to scale the length.
var dir = light.position - pos;
var angle = Vector3.Dot(Vector3.Normalize(dir), plane.Normal);
var len = dir.Length();
var slen = len / 4.0f;
var strength = (angle + 1.0f) / slen;
if (hdr)
{
strength /= 2;
}
// We need to make sure we don't go over (255, 255, 255).
// If we just do Max(color, (255, 255, 255)) then we change
// the hue/saturation of coloured lights. Got to make sure we
// maintain the colour ratios.
var c = light.color * strength;
var ratio = 0.0f;
foreach (var e in new float[] { c.X, c.Y, c.Z })
{
ratio = Math.Max(ratio, e / 255.0f);
}
if (ratio > 1.0f)
{
c /= ratio;
}
lightmap.AddLight(0, x, y, (byte)c.X, (byte)c.Y, (byte)c.Z);
} }
} }
} }
@ -376,9 +344,21 @@ class Program
cellIdxOffset += poly.VertexCount; cellIdxOffset += poly.VertexCount;
} }
});
} }
Console.Write("\n"); private static float CalculateLightStrengthAtPoint(Light light, Vector3 point, Plane plane)
{
// Calculate light strength at a given point. As far as I can tell
// this is exact to Dark (I'm a genius??). It's just an inverse distance
// falloff with diffuse angle, except we have to scale the length.
var dir = light.position - point;
var angle = Vector3.Dot(Vector3.Normalize(dir), plane.Normal);
var len = dir.Length();
var slen = len / 4.0f;
var strength = (angle + 1.0f) / slen;
return strength;
} }
private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap, bool hdr) private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap, bool hdr)
@ -388,17 +368,11 @@ class Program
lightmap.Pixels[i] = 0; lightmap.Pixels[i] = 0;
} }
var c = ambientLight;
if (hdr)
{
c /= 2.0f;
}
for (var y = 0; y < lightmap.Height; y++) for (var y = 0; y < lightmap.Height; y++)
{ {
for (var x = 0; x < lightmap.Width; x++) for (var x = 0; x < lightmap.Width; x++)
{ {
lightmap.AddLight(0, x, y, (byte)c.X, (byte)c.Y, (byte)c.Z); lightmap.AddLight(0, x, y, ambientLight, 1.0f, hdr);
} }
} }
} }