diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 13:11:52 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 13:11:52 +0800 |
| commit | 76a6850bb88546fc21f5f78a53fbda04e77c8b52 (patch) | |
| tree | 45e492b623ef820d452201421b85a0b642d349bd /src/LivingVillage.Desktop/M6Presentation.fs | |
| parent | 000a0b00384806ce85d54dfcd2646cb340a26f01 (diff) | |
| download | living-village-76a6850bb88546fc21f5f78a53fbda04e77c8b52.tar.gz | |
feat(desktop): 确定性昼夜光照过渡与夜灯暖光
新增 lightingBlend 纯函数(黎明明 4:00-6:00、暮色 20:00-22:00 线性过渡,边界与 isNightTick 对齐),天空底色/世界 tint 按混合插值渲染,夜晚灯笼暖光晕强度=LanternGlow(纯叠加矩形、无每帧分配风险);回归测试含锚点/单调斜坡/确定性/光晕开关。
Diffstat (limited to 'src/LivingVillage.Desktop/M6Presentation.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/M6Presentation.fs | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/src/LivingVillage.Desktop/M6Presentation.fs b/src/LivingVillage.Desktop/M6Presentation.fs index 8e13183..ea8fd2f 100644 --- a/src/LivingVillage.Desktop/M6Presentation.fs +++ b/src/LivingVillage.Desktop/M6Presentation.fs @@ -11,7 +11,9 @@ type M6DayNight = type M6RenderProfile = { Mode: M6DayNight Background: Color - WorldTint: Color } + WorldTint: Color + Blend: float32 + LanternGlow: float32 } module M6Presentation = @@ -20,15 +22,38 @@ module M6Presentation = | Day -> "白天" | Night -> "夜晚" - let profileAtTick (tick: int64) : M6RenderProfile = - if Sim.isNightTick tick then - { Mode = Night - Background = Color(18, 25, 55) - WorldTint = Color(118, 136, 184) } - else - { Mode = Day - Background = Color(100, 160, 210) - WorldTint = Color(255, 248, 224) } + /// Continuous light blend: 0 = full day, 1 = full night. Ramps are deterministic + /// pure functions of the simulation tick (dawn 4:00-6:00, dusk 20:00-22:00), so the + /// boundaries agree with Sim.isNightTick (night >= 22:00 or < 6:00). + let lightingBlend (tick: int64) : float32 = + let hourTicks = Sim.ticksPerDay / 24L + let hour = float32 (tick / hourTicks) + let clamp01 v = if v < 0.0f then 0.0f elif v > 1.0f then 1.0f else v + if hour >= 6.0f && hour < 20.0f then 0.0f + elif hour >= 22.0f then 1.0f + elif hour < 4.0f then 1.0f + elif hour < 6.0f then clamp01 (1.0f - (hour - 4.0f) / 2.0f) + else clamp01 ((hour - 20.0f) / 2.0f) + + let private lerp (a: int) (b: int) (blend: float32) : int = + a + int (float32 (b - a) * blend) + + let backgroundAtBlend (blend: float32) : Color = + Color(lerp 100 18 blend, lerp 160 25 blend, lerp 210 55 blend) + + let worldTintAtBlend (blend: float32) : Color = + Color(lerp 255 118 blend, lerp 248 136 blend, lerp 224 184 blend) + + /// Pure day-phase lighting: deterministic tint/background plus lantern warm-glow boost. + let lightingAtTick (tick: int64) : M6RenderProfile = + let blend = lightingBlend tick + { Mode = if blend < 0.5f then Day else Night + Background = backgroundAtBlend blend + Blend = blend + WorldTint = worldTintAtBlend blend + LanternGlow = blend } + + let profileAtTick (tick: int64) : M6RenderProfile = lightingAtTick tick let clockLabel (control: SimulationControl) : string = if control.Paused then |
