112 lines
4.4 KiB
C#
112 lines
4.4 KiB
C#
using System;
|
|
using System.IO;
|
|
using Xunit;
|
|
|
|
namespace AcDream.App.Tests.Rendering.Sky;
|
|
|
|
/// <summary>
|
|
/// Source guards for the enhanced night sky (register IA-26, user-directed
|
|
/// 2026-08-23): a render-pack-gated replacement of the DAT star layer
|
|
/// (GfxObj 0x010015EF) with sky.frag's procedural view-direction starfield.
|
|
/// The retail look must stay the default: everything here is inert unless the
|
|
/// Atmospheric pack is the active runtime. The shader itself needs a GPU, so
|
|
/// these pin the wiring the way SkyFogRuleTests pins the fog rules.
|
|
/// </summary>
|
|
public sealed class EnhancedNightSkyRuleTests
|
|
{
|
|
[Fact]
|
|
public void SkyFragmentShaderGatesTheProceduralSkyOnParamA()
|
|
{
|
|
string frag = File.ReadAllText(Path.Combine(ShaderRoot(), "sky.frag"));
|
|
string code = StripLineComments(frag);
|
|
|
|
Assert.Contains("if (uParamA > 0.5)", code, StringComparison.Ordinal);
|
|
Assert.Contains("nightSky(normalize(vDir), uint(uParamB))", code, StringComparison.Ordinal);
|
|
// Screen-pixel star sizing is the reason this exists — the stretched
|
|
// texture flaw must not creep back in via a fixed-size grid, and the
|
|
// cube-face fwidth seams must not return (the 2026-08-23 gate's
|
|
// glowing "Y"): the crispness anchor is the seamless 3D-lattice
|
|
// tangent-plane solve on the direction derivatives.
|
|
Assert.Contains("dFdx(dir)", code, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("fwidth(g)", code, StringComparison.Ordinal);
|
|
// No diffraction spikes — user-directed: flare is photographic.
|
|
Assert.DoesNotContain("spike", code, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void SkyRendererSwapsExactlyTheStarLayerAndOnlyUnderTheProvider()
|
|
{
|
|
string source = File.ReadAllText(Path.Combine(
|
|
RepositoryRoot(), "src", "AcDream.App", "Rendering", "Sky", "SkyRenderer.cs"));
|
|
string code = StripLineComments(source);
|
|
|
|
Assert.Contains(
|
|
"private const uint StarLayerGfxObjId = 0x010015EFu;",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains(
|
|
"bool nightSky = gfxObjId == StarLayerGfxObjId",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains(
|
|
"(EnhancedNightSkyActive?.Invoke() ?? false)",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void NightSkyDrawForcesTheAdditivePipeline()
|
|
{
|
|
string source = File.ReadAllText(Path.Combine(
|
|
RepositoryRoot(), "src", "AcDream.App", "Rendering", "Sky", "SkyRenderer.Rhi.cs"));
|
|
string code = StripLineComments(source);
|
|
|
|
Assert.Contains(
|
|
"nightSky || sub.IsAdditive ? _additivePipeline! : _alphaPipeline!",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains("ParamA = nightSky ? 1f : 0f,", code, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void CompositionGatesTheNightSkyOnTheAtmosphericPackRuntime()
|
|
{
|
|
string source = File.ReadAllText(Path.Combine(
|
|
RepositoryRoot(), "src", "AcDream.App", "Composition", "FrameRootComposition.cs"));
|
|
string code = StripLineComments(source);
|
|
|
|
Assert.Contains("EnhancedNightSkyActive = () =>", code, StringComparison.Ordinal);
|
|
Assert.Contains(
|
|
"nightSkyController.ActiveRuntime?.Descriptor.Id",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains(
|
|
"BuiltInAtmosphericRenderPack.Id",
|
|
code,
|
|
StringComparison.Ordinal);
|
|
}
|
|
|
|
private static string StripLineComments(string source)
|
|
{
|
|
var lines = source.Split('\n');
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
int idx = lines[i].IndexOf("//", StringComparison.Ordinal);
|
|
if (idx >= 0)
|
|
lines[i] = lines[i][..idx];
|
|
}
|
|
return string.Join('\n', lines);
|
|
}
|
|
|
|
private static string ShaderRoot() =>
|
|
Path.Combine(RepositoryRoot(), "src", "AcDream.App", "Rendering", "Shaders");
|
|
|
|
private static string RepositoryRoot()
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
|
directory = directory.Parent;
|
|
return directory?.FullName
|
|
?? throw new InvalidOperationException("Could not locate repository root.");
|
|
}
|
|
}
|