acdream/tests/AcDream.Core.Tests/Lighting/SceneLightingUboTests.cs
Erik a5debaca2b fix(overhaul): integrate reviewed room-light selection repair
Exact26 code/test/architecture/register blobs from621b41fa3; campaign ledger and lead verification included. Independent retail and production/lifetime/ABI reviews PASS. Lead69Core/176App/2actualshader pixels, viewer/clear/NaN negative controls fail as intended, exact restoration69PASS. AP68retired; AP16/35/85 residuals honest. Fresh campaign Release and graphical lighting proof still owed; temporary observer cleanup contract conditional. FPS deferred; no G4 or main merge.
2026-09-05 14:57:52 +02:00

123 lines
4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Numerics;
using System.Runtime.InteropServices;
using AcDream.Core.Lighting;
using AcDream.Core.World;
using Xunit;
namespace AcDream.Core.Tests.Lighting;
public sealed class SceneLightingUboTests
{
[Fact]
public void UboLight_StructSize_Is64Bytes()
{
// std140 mandates 4× vec4 = 64 bytes. If this drifts the shader
// will read garbage.
Assert.Equal(64, Marshal.SizeOf<UboLight>());
}
[Fact]
public void SceneLightingUbo_StructSize_MatchesConstant()
{
Assert.Equal(SceneLightingUbo.SizeInBytes, Marshal.SizeOf<SceneLightingUbo>());
}
[Fact]
public void Build_PacksActiveLightsIntoSlotsInOrder()
{
var lights = new LightManager();
lights.Register(new LightSource
{
Kind = LightKind.Point,
WorldPosition = new Vector3(1, 2, 3),
RankingOrigin = new Vector3(1, 2, 3),
ColorLinear = new Vector3(1f, 0.5f, 0.25f),
Intensity = 0.8f,
Range = 6f,
});
lights.Tick(Vector3.Zero);
var atmo = new AtmosphereSnapshot(
Kind: WeatherKind.Clear,
Intensity: 1f,
FogColor: new Vector3(0.7f, 0.8f, 0.9f),
FogStart: 100f,
FogEnd: 400f,
FogMode: FogMode.Linear,
LightningFlash: 0f,
Override: EnvironOverride.None);
var ubo = SceneLightingUbo.Build(lights, in atmo, new Vector3(10, 20, 30), 0.5f);
// Light 0 is the slot we populated.
Assert.Equal(1f, ubo.Light0.PosAndKind.X);
Assert.Equal(2f, ubo.Light0.PosAndKind.Y);
Assert.Equal(3f, ubo.Light0.PosAndKind.Z);
Assert.Equal((float)(int)LightKind.Point, ubo.Light0.PosAndKind.W);
Assert.Equal(6f, ubo.Light0.DirAndRange.W);
Assert.Equal(0.8f, ubo.Light0.ColorAndIntensity.W);
// Unused slots should be zero-packed.
Assert.Equal(0f, ubo.Light1.DirAndRange.W);
// Active count lives in uCellAmbient.w.
Assert.Equal(1f, ubo.CellAmbient.W);
// Fog params passed through.
Assert.Equal(100f, ubo.FogParams.X);
Assert.Equal(400f, ubo.FogParams.Y);
Assert.Equal(0f, ubo.FogParams.Z); // no flash
Assert.Equal((float)(int)FogMode.Linear, ubo.FogParams.W);
// Camera + day fraction.
Assert.Equal(10f, ubo.CameraAndTime.X);
Assert.Equal(0.5f, ubo.CameraAndTime.W);
}
[Fact]
public void Build_ClampsAtEightLights()
{
var lights = new LightManager();
// Register 20; the active list caps at 8.
for (int i = 0; i < 20; i++)
{
lights.Register(new LightSource
{
Kind = LightKind.Point,
WorldPosition = new Vector3(i, 0, 0),
RankingOrigin = new Vector3(i, 0, 0),
Range = 200f, // all in range
});
}
lights.Tick(Vector3.Zero);
var atmo = new AtmosphereSnapshot(
WeatherKind.Clear, 1f, Vector3.Zero, 0, 0, FogMode.Off, 0f, EnvironOverride.None);
var ubo = SceneLightingUbo.Build(lights, in atmo, Vector3.Zero, 0f);
// Slot 7 populated (8th light), active count = 8.
Assert.Equal(8f, ubo.CellAmbient.W);
Assert.NotEqual(0f, ubo.Light7.DirAndRange.W);
}
[Fact]
public void Build_WithSun_SlotZeroIsDirectional()
{
var lights = new LightManager();
lights.Sun = new LightSource
{
Kind = LightKind.Directional,
WorldForward = new Vector3(0, 0, -1),
ColorLinear = new Vector3(1f, 0.9f, 0.8f),
Intensity = 1.2f,
};
lights.Tick(Vector3.Zero);
var atmo = new AtmosphereSnapshot(
WeatherKind.Clear, 1f, Vector3.Zero, 0, 0, FogMode.Off, 0f, EnvironOverride.None);
var ubo = SceneLightingUbo.Build(lights, in atmo, Vector3.Zero, 0f);
Assert.Equal((float)(int)LightKind.Directional, ubo.Light0.PosAndKind.W);
Assert.Equal(1.2f, ubo.Light0.ColorAndIntensity.W);
}
}