feat(sky): the night sky wheels with the Dereth clock; uniform time fade with a scoped twilight band
Rotation (user-directed): the procedural starfield rotates once per Dereth day (~2 real hours - constellations visibly wheel through a night) about a celestial pole ~41 deg above the northern horizon, plus dayOfYear/360 of seasonal drift so the 360-day year changes the night sky. One SkyParams float (272-byte block, layout test re-pinned) carries dayFraction + dayOfYear/360 from the world clock; sky.frag applies a Rodrigues rotation to the sample direction so stars and mottle turn together. Impossible with retail's static stretched layer. Fade rework (the 2026-08-23 two-screenshot gate finding): the per-vertex vTint signal carried the sun-facing product and blanked stars across the entire twilight half of the sky. The fade now reads the UNIFORM ambient term - identical star visibility in every compass direction, same dusk-to-dawn schedule - with one deliberate exception: a thin suppression band hugging the low sky toward the sun's azimuth while the sun term is strong, so stars still wash out inside the actual twilight glow. Guards updated (rotation anchor, uniform-fade anchor, 272-byte layout); both sky SPIR-V hashes re-pinned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
91084b9a83
commit
0dac024cdb
10 changed files with 98 additions and 15 deletions
|
|
@ -52,8 +52,8 @@ public sealed class VulkanShaderManifestTests
|
|||
// override, retail's GameSky::Draw @0x00506FF0 rule (see
|
||||
// SkyFogRuleTests). A deliberate default-path change, reviewed
|
||||
// with the world-fog-range fix in the same commit.
|
||||
["sky.frag.spv"] = "e307a7f3cf84aada86db7c2859c55841a650b46732f12149986562cef0a90ca8",
|
||||
["sky.vert.spv"] = "3b51945fa4ff1be1604144df92866bdd47aade22f9dd90267591ef36adb28cde",
|
||||
["sky.frag.spv"] = "83a7b4e265f7df4726d716a812ebaa74ba31ea47036bc31005cd8dc1d8981967",
|
||||
["sky.vert.spv"] = "988eff4e106422ca483d665ba25818e8394737a247e9bae346db3220ac31fd28",
|
||||
["terrain_modern.frag.spv"] = "7b3cdb01b837ed77ee20559a81c1ce5c9d5395300efcc072560ab0be3c5a1af9",
|
||||
["terrain_modern.vert.spv"] = "9f4cb221ea6aed94a8d23af6cb8e3f3ed96c3cce6e50d135a72d3b55667b1557",
|
||||
["ui_text.frag.spv"] = "37a281bf80441cb425eaa3ad8e0b3a43cfa21b74b60973ed4201718b9dc102df",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ public sealed class EnhancedNightSkyRuleTests
|
|||
string code = StripLineComments(frag);
|
||||
|
||||
Assert.Contains("if (uParamA > 0.5)", code, StringComparison.Ordinal);
|
||||
Assert.Contains("nightSky(normalize(vDir), uint(uParamB))", code, StringComparison.Ordinal);
|
||||
Assert.Contains("nightSky(rdir, uint(uParamB))", code, StringComparison.Ordinal);
|
||||
// The fade must stay UNIFORM across the sky (the first gate's
|
||||
// per-vertex vTint signal blanked the whole twilight half) and the
|
||||
// starfield must wheel with the Dereth clock.
|
||||
Assert.Contains("dot(uAmbientColor, vec3(0.299, 0.587, 0.114))", code, StringComparison.Ordinal);
|
||||
Assert.Contains("fract(uNightSkyRotationTurns)", 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
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace AcDream.App.Tests.Rendering;
|
|||
/// <summary>
|
||||
/// Campaign V slice V6e: the sky's dozen loose uniforms became one std140
|
||||
/// uniform block, and this is the test that keeps the CPU struct and the GLSL
|
||||
/// block describing the same 256 bytes.
|
||||
/// block describing the same 272 bytes.
|
||||
///
|
||||
/// <para>It exists because the failure mode is silent. std140 gives a
|
||||
/// <c>vec3</c> 16-byte alignment while only using 12, so the block deliberately
|
||||
|
|
@ -45,6 +45,12 @@ public sealed class SkyParamsLayoutTests
|
|||
[InlineData("UvScroll", 240)]
|
||||
[InlineData("ApplyFog", 248)]
|
||||
[InlineData("SurfOpacity", 252)]
|
||||
// IA-26: the enhanced night sky's rotation turns plus its three pad
|
||||
// words, filling the seventeenth vec4 exactly.
|
||||
[InlineData("NightSkyRotationTurns", 256)]
|
||||
[InlineData("NsPadA", 260)]
|
||||
[InlineData("NsPadB", 264)]
|
||||
[InlineData("NsPadC", 268)]
|
||||
public void EveryMemberSitsWhereStd140PutsIt(string member, int expectedOffset)
|
||||
{
|
||||
Assert.Equal(
|
||||
|
|
@ -60,7 +66,7 @@ public sealed class SkyParamsLayoutTests
|
|||
?.GetRawConstantValue()
|
||||
?? throw new InvalidOperationException("SkyParams.SizeInBytes is missing."));
|
||||
|
||||
Assert.Equal(256, declared);
|
||||
Assert.Equal(272, declared);
|
||||
Assert.Equal(declared, Marshal.SizeOf(SkyParamsType));
|
||||
// std140 rounds a block up to its largest member's alignment (16).
|
||||
Assert.Equal(0, declared % 16);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue