From 3b684db0f19c29ca9e6798fa10b2e6308eba340d Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 10 May 2026 08:27:55 +0200 Subject: [PATCH] =?UTF-8?q?feat(A.5=20T22):=20fog=20wired=20from=20N?= =?UTF-8?q?=E2=82=81/N=E2=82=82=20+=20ACDREAM=5FFOG=5F*=5FMULT=20env=20var?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Phase A.5 spec §4.8: fog ramp is tuned to mask the N₁ scenery boundary. FogStart = N₁ × 192m × 0.7 ≈ 538m at default radii (4/12). FogEnd = N₂ × 192m × 0.95 ≈ 2188m. Multipliers exposed as env vars for fast iteration during visual gate. Override is injected into the UBO after SceneLightingUbo.Build() so fog color, lightning flash and mode still come from the sky keyframe. Adds ParseEnvFloat helper (InvariantCulture) for float env-var parsing. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index c879195..2938753 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -6344,6 +6344,28 @@ public sealed class GameWindow : IDisposable Lighting.Tick(camPos); var ubo = AcDream.Core.Lighting.SceneLightingUbo.Build( Lighting, in atmo, camPos, (float)WorldTime.DayFraction); + + // A.5 T22: override fog ramp with N₁/N₂-derived distances so the + // horizon fog masks the N₁ scenery boundary. Sky keyframe fog is + // retail-accurate at normal view distances but far too short for + // the extended N₂=12 (25×25 LB) streaming window. + // FogStart = N₁ × 192m × 0.7 ≈ 538m at defaults (4/12). + // FogEnd = N₂ × 192m × 0.95 ≈ 2188m at defaults. + // Multipliers exposed as env vars for fast iteration at visual gate. + { + const float LandblockSize = 192.0f; + float startMult = ParseEnvFloat("ACDREAM_FOG_START_MULT", 0.7f); + float endMult = ParseEnvFloat("ACDREAM_FOG_END_MULT", 0.95f); + float fogStart = _nearRadius * LandblockSize * startMult; + float fogEnd = _farRadius * LandblockSize * endMult; + // Preserve fog color (xyz), lightning flash (z), and mode (w). + ubo.FogParams = new System.Numerics.Vector4( + fogStart, + fogEnd, + ubo.FogParams.Z, // lightning flash — unchanged + ubo.FogParams.W); // fog mode — unchanged + } + _sceneLightingUbo?.Upload(ubo); // Never cull the landblock the player is currently on. @@ -8862,6 +8884,17 @@ public sealed class GameWindow : IDisposable return copy[copy.Length - 1 - offset]; } + /// A.5 T22: parse a float environment variable, returning + /// when the variable is absent or unparseable. + private static float ParseEnvFloat(string name, float defaultValue) + { + var s = System.Environment.GetEnvironmentVariable(name); + if (s is not null && float.TryParse(s, System.Globalization.NumberStyles.Float, + System.Globalization.CultureInfo.InvariantCulture, out var v)) + return v; + return defaultValue; + } + private void OnClosing() { // Phase A.1: join the streamer worker thread before tearing down GL