namespace IslaApocalypse.Tools { /// /// The presentation dials — everything about how a heightmap is SHOWN, and nothing about how it /// is MADE. → `Design - Rendering - Roughness Is Presentation.md`. /// /// ⚠ Config-gated for the same reason every shaping change is: a look decision should be an A/B /// pair, not a memory of last week's render, and a rejected look should cost a flipped default /// rather than a reverted commit. → `Design - Tooling - Iteration and Batching.md`. /// /// ⚠ Kept DELIBERATELY SMALL. This is a taste gate, and iteration fatigue on a subjective gate /// is a real failure mode — a handful of variants the eye can actually judge beats a wall of /// near-duplicates. Three named looks, chosen so each pair isolates one question. /// public sealed class LookConfig { /// Short label, used in output filenames. public string Name = "atlas"; /// Which hypsometric palette. → . public ReliefPalette.Kind Palette = ReliefPalette.Kind.Atlas; /// /// Vertical exaggeration for the relief normal. ⚠ A LOOK DIAL, NOT A PHYSICAL CLAIM — the /// raw height units are not metres. See for the measured slope /// table this was chosen from. /// public float ZExaggeration = 75f; /// Compass degrees clockwise from north. 315° (NW) is the cartographic standard. public float LightAzimuth = 315f; /// Degrees above the horizon. 45° standard; lower = longer, more dramatic shadows. public float LightAltitude = 45f; /// /// How much the relief moves the tint. 0 = flat hypsometric tint, no shading at all; /// 1 = full relief. Above ~0.85 the tint starts washing out and the map reads as a /// greyscale DEM wearing colour. /// public float HillshadeStrength = 0.55f; /// /// Relief multiplier BELOW sea level. /// /// ⚠ Deliberately much weaker than on land, and the reason is the deferral: the seabed is /// RAW — no coast shelf, no islets, both Phase-2 items — so it is steep and noisy in a way /// the finished terrain will not be. Shading it at full strength drags the eye to the one /// part of the map that is knowingly unfinished. Cartographic bathymetry is conventionally /// shown flat or lightly shaded anyway, so the convention and the deferral agree. /// public float SeaHillshadeFactor = 0.35f; /// /// How much of the lit side is allowed to lift toward white. Highlights SCREEN rather than /// multiply, so sunlit slopes brighten without blowing out to paper. /// public float HighlightGain = 0.5f; /// The colour boundary. NOT a water surface — no water is modelled (Phase 2). public float SeaLevel = 0.15f; /// /// The three looks offered to the taste gate. Each pair isolates one question: /// atlas vs relief → how strong should the relief be? (same palette and light) /// atlas vs dusk → which palette, and how low a sun? (comparable relief) /// public static LookConfig[] Variants() => new[] { // Classic physical-atlas plate: tint-forward, relief present but polite. new LookConfig { Name = "atlas", Palette = ReliefPalette.Kind.Atlas, ZExaggeration = 75f, LightAzimuth = 315f, LightAltitude = 45f, HillshadeStrength = 0.55f, }, // Shape-forward: the same palette and light, harder relief. Isolates the relief dial. new LookConfig { Name = "relief", Palette = ReliefPalette.Kind.Atlas, ZExaggeration = 120f, LightAzimuth = 315f, LightAltitude = 45f, HillshadeStrength = 0.80f, }, // Warmer palette, lower sun, longer shadows. Isolates palette + light. new LookConfig { Name = "dusk", Palette = ReliefPalette.Kind.Dusk, ZExaggeration = 100f, LightAzimuth = 300f, LightAltitude = 35f, HillshadeStrength = 0.70f, }, }; public override string ToString() => $"{Name}: palette={Palette} zex={ZExaggeration:F0} light={LightAzimuth:F0}°/{LightAltitude:F0}° " + $"strength={HillshadeStrength:F2} sea×{SeaHillshadeFactor:F2}"; } }