acdream/tests/AcDream.App.Tests/Rendering/DirectionalShadowEnvironmentGateTests.cs

214 lines
7.8 KiB
C#

using System.Numerics;
using AcDream.App.Rendering;
using AcDream.App.Rendering.Packs;
using AcDream.Core.World;
namespace AcDream.App.Tests.Rendering;
public sealed class DirectionalShadowEnvironmentGateTests
{
[Theory]
[InlineData(false, false, false, DirectionalShadowGateReason.PackDisabled)]
[InlineData(true, true, false, DirectionalShadowGateReason.PortalOrLoginCover)]
[InlineData(true, false, true, DirectionalShadowGateReason.Indoor)]
internal void NonWorldGates_DisableWithoutCreatingCelestialWork(
bool enabled,
bool cover,
bool indoor,
DirectionalShadowGateReason expected)
{
DirectionalShadowEnvironmentInput input = new(
enabled,
cover,
indoor,
Celestial(AuthoredCelestialShadowSourceKind.SecondaryMoon, 35f),
Atmosphere(WeatherKind.Clear));
DirectionalShadowEnvironmentState result =
DirectionalShadowEnvironmentGate.Evaluate(
in input,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.False(result.ShouldRender);
Assert.Equal(expected, result.Reason);
Assert.Equal(0f, result.Strength);
}
[Fact]
public void SelectedCelestialBelowHorizon_DisablesAndPreservesSourceIdentity()
{
AuthoredCelestialShadowSource source = Celestial(
AuthoredCelestialShadowSourceKind.SecondaryMoon,
-2f);
DirectionalShadowEnvironmentInput input = new(
true,
false,
false,
source,
Atmosphere(WeatherKind.Clear));
DirectionalShadowEnvironmentState result =
DirectionalShadowEnvironmentGate.Evaluate(
in input,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.False(result.ShouldRender);
Assert.Equal(
DirectionalShadowGateReason.SelectedLightBelowHorizon,
result.Reason);
Assert.Equal(source.SurfaceToLightDirection, result.SurfaceToLightDirection);
Assert.Equal(source.Kind, result.SourceKind);
Assert.Equal(source.ObjectIndex, result.SourceObjectIndex);
Assert.Equal(source.GfxObjId, result.SourceGfxObjId);
}
[Fact]
public void NoVisibleCelestial_DisablesBeforeAtmosphereMapping()
{
DirectionalShadowEnvironmentInput input = new(
true,
false,
false,
AuthoredCelestialShadowSource.None(authoredEnergy: 1f),
Atmosphere(WeatherKind.Clear));
DirectionalShadowEnvironmentState result =
DirectionalShadowEnvironmentGate.Evaluate(
in input,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.False(result.ShouldRender);
Assert.Equal(DirectionalShadowGateReason.NoVisibleCelestial, result.Reason);
Assert.Equal(AuthoredCelestialShadowSourceKind.None, result.SourceKind);
}
[Fact]
public void SelectedCelestialWithoutAuthoredEnergy_DisablesAndPreservesSourceIdentity()
{
AuthoredCelestialShadowSource source = Celestial(
AuthoredCelestialShadowSourceKind.DominantMoon,
35f,
energy: 0f);
DirectionalShadowEnvironmentInput input = new(
true,
false,
false,
source,
Atmosphere(WeatherKind.Clear));
DirectionalShadowEnvironmentState result =
DirectionalShadowEnvironmentGate.Evaluate(
in input,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.False(result.ShouldRender);
Assert.Equal(
DirectionalShadowGateReason.SelectedLightHasNoEnergy,
result.Reason);
Assert.Equal(source.SurfaceToLightDirection, result.SurfaceToLightDirection);
Assert.Equal(source.Kind, result.SourceKind);
Assert.Equal(source.ObjectIndex, result.SourceObjectIndex);
Assert.Equal(source.GfxObjId, result.SourceGfxObjId);
}
[Fact]
public void AuthoredWeatherAndDayGroup_SoftenAndReduceButDoNotReplaceSelectedCelestial()
{
AuthoredCelestialShadowSource source = Celestial(
AuthoredCelestialShadowSourceKind.DominantMoon,
35f);
DirectionalShadowEnvironmentInput clearInput = new(
true,
false,
false,
source,
Atmosphere(WeatherKind.Clear),
ActiveDayGroupMultiplier: 1f);
DirectionalShadowEnvironmentInput rainInput = clearInput with
{
Atmosphere = Atmosphere(WeatherKind.Rain),
ActiveDayGroupMultiplier = 0.8f,
};
DirectionalShadowEnvironmentState clear =
DirectionalShadowEnvironmentGate.Evaluate(
in clearInput,
DirectionalShadowAtmospherePolicy.BuiltIn);
DirectionalShadowEnvironmentState rain =
DirectionalShadowEnvironmentGate.Evaluate(
in rainInput,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.True(clear.ShouldRender);
Assert.True(rain.ShouldRender);
Assert.Equal(source.SurfaceToLightDirection, clear.SurfaceToLightDirection);
Assert.Equal(clear.SurfaceToLightDirection, rain.SurfaceToLightDirection);
Assert.Equal(AuthoredCelestialShadowSourceKind.DominantMoon, clear.SourceKind);
Assert.Equal(clear.SourceKind, rain.SourceKind);
Assert.Equal(source.ObjectIndex, rain.SourceObjectIndex);
Assert.Equal(source.GfxObjId, rain.SourceGfxObjId);
Assert.True(rain.Strength < clear.Strength);
Assert.True(rain.SoftnessMultiplier > clear.SoftnessMultiplier);
}
[Fact]
public void ZeroDayGroupPolicy_DisablesThroughExplicitAtmosphereMapping()
{
DirectionalShadowEnvironmentInput input = new(
true,
false,
false,
Celestial(AuthoredCelestialShadowSourceKind.Sun, 35f),
Atmosphere(WeatherKind.Clear),
ActiveDayGroupMultiplier: 0f);
DirectionalShadowEnvironmentState result =
DirectionalShadowEnvironmentGate.Evaluate(
in input,
DirectionalShadowAtmospherePolicy.BuiltIn);
Assert.Equal(DirectionalShadowGateReason.AtmosphereSuppressed, result.Reason);
Assert.False(result.ShouldRender);
}
private static AuthoredCelestialShadowSource Celestial(
AuthoredCelestialShadowSourceKind kind,
float elevationDegrees,
float energy = 1f)
{
float elevation = elevationDegrees * MathF.PI / 180f;
const float heading = 120f * MathF.PI / 180f;
float horizontal = MathF.Cos(elevation);
Vector3 direction = new(
horizontal * MathF.Cos(heading),
horizontal * MathF.Sin(heading),
MathF.Sin(elevation));
uint gfxObjId = kind switch
{
AuthoredCelestialShadowSourceKind.Sun =>
AuthoredCelestialShadowSourceResolver.SunGfxObjId,
AuthoredCelestialShadowSourceKind.DominantMoon =>
AuthoredCelestialShadowSourceResolver.DominantMoonGfxObjId,
AuthoredCelestialShadowSourceKind.SecondaryMoon =>
AuthoredCelestialShadowSourceResolver.SecondaryMoonGfxObjId,
_ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null),
};
return new AuthoredCelestialShadowSource(
Kind: kind,
ObjectIndex: 4,
GfxObjId: gfxObjId,
SurfaceToLightDirection: direction,
ElevationSin: direction.Z,
AuthoredEnergy: energy);
}
private static AtmosphereSnapshot Atmosphere(WeatherKind weather) => new(
weather,
Intensity: 1f,
FogColor: new Vector3(0.4f),
FogStart: 80f,
FogEnd: 350f,
FogMode.Linear,
LightningFlash: 0f,
EnvironOverride.None);
}