78 lines
2.5 KiB
C#
78 lines
2.5 KiB
C#
using System.Collections.Generic;
|
||
using System.Numerics;
|
||
using AcDream.Core.Lighting;
|
||
using Xunit;
|
||
|
||
namespace AcDream.Core.Tests.Lighting;
|
||
|
||
/// <summary>
|
||
/// Golden conformance for the retail bake (calc_point_light + the [0,1] clamp),
|
||
/// driven by the live-cdb-captured Holtburg wall torches. Pins the contract that
|
||
/// mesh_modern.vert's pointContribution + the new pointAcc clamp (A7 Fix D, D-1)
|
||
/// must mirror line-for-line. See docs/research/2026-06-18-lighting-a7-fixABC-shipped-fixD-handoff.md.
|
||
/// </summary>
|
||
public class LightBakeConformanceTests
|
||
{
|
||
private static LightSource OrangeTorch(Vector3 pos) => new()
|
||
{
|
||
Kind = LightKind.Point,
|
||
WorldPosition = pos,
|
||
ColorLinear = new Vector3(1.0f, 0.588f, 0.314f), // captured orange
|
||
Intensity = 100f,
|
||
Range = 4f * 1.3f, // falloff 4 × static_light_factor
|
||
IsLit = true,
|
||
};
|
||
|
||
[Theory]
|
||
[InlineData(1f)]
|
||
[InlineData(2f)]
|
||
[InlineData(3f)]
|
||
[InlineData(4f)]
|
||
[InlineData(5f)]
|
||
public void SingleOrangeTorch_IsWarmAndBounded_NeverWhite(float dist)
|
||
{
|
||
var vtx = Vector3.Zero;
|
||
var normal = Vector3.UnitX;
|
||
var torch = OrangeTorch(new Vector3(dist, 0f, 0f));
|
||
|
||
var c = LightBake.ComputeVertexColor(vtx, normal, new[] { torch });
|
||
|
||
Assert.InRange(c.X, 0f, 1f);
|
||
Assert.InRange(c.Y, 0f, 1f);
|
||
Assert.InRange(c.Z, 0f, 1f);
|
||
if (c.X > 0f)
|
||
{
|
||
Assert.True(c.X >= c.Y, $"R({c.X}) >= G({c.Y}) at d={dist}");
|
||
Assert.True(c.Y >= c.Z, $"G({c.Y}) >= B({c.Z}) at d={dist}");
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public void BeyondRange_ContributesNothing()
|
||
{
|
||
var torch = OrangeTorch(new Vector3(100f, 0f, 0f));
|
||
var c = LightBake.ComputeVertexColor(Vector3.Zero, Vector3.UnitX, new[] { torch });
|
||
Assert.Equal(Vector3.Zero, c);
|
||
}
|
||
|
||
[Fact]
|
||
public void ManyOverlappingIntenseTorches_StillClampToOne()
|
||
{
|
||
var lights = new List<LightSource>();
|
||
for (int i = 0; i < 8; i++)
|
||
lights.Add(new LightSource
|
||
{
|
||
Kind = LightKind.Point,
|
||
WorldPosition = new Vector3(1.5f, 0.1f * i, 0f),
|
||
ColorLinear = new Vector3(0.98f, 0.95f, 0.9f),
|
||
Intensity = 100f,
|
||
Range = 5.2f,
|
||
IsLit = true,
|
||
});
|
||
|
||
var c = LightBake.ComputeVertexColor(Vector3.Zero, Vector3.UnitX, lights);
|
||
Assert.InRange(c.X, 0f, 1f);
|
||
Assert.InRange(c.Y, 0f, 1f);
|
||
Assert.InRange(c.Z, 0f, 1f);
|
||
}
|
||
}
|