summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/SceneDetailRender.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-29 16:17:02 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-29 16:17:02 +0800
commit012c66f7eef55e7ef98a3c09bba419b1b17c05ca (patch)
treeeaa3a0230e848d40d66418b3cfb29e898f7784ba /src/LivingVillage.Desktop/SceneDetailRender.fs
parentc4917adfd5dec391196a399aa53d57c680e462f4 (diff)
downloadliving-village-012c66f7eef55e7ef98a3c09bba419b1b17c05ca.tar.gz
p79: 夜帧炊烟增强与光晕去叠
- 炊烟:夜帧烟柱4段向上堆叠(整格32px, alpha 180+75)+暖色外发光(r30)+中性柔光团(r12); 烟柱强光像素(夜-昼贡献>=80) 181->1171 (x6.5),峰值112->173;白天帧逐像素不变。 - 光晕去叠:VillageArt.haloRingLayers 每光源<=2层(内芯+空心外环),芯环间确定暗隙,半径4->3 tile, 峰值150->118;光晕重叠面积(夜-昼贡献>=60)中央区 15184->9633 (-36.6%),全屏 15477->9926 (-35.9%)。 - 回归 P79NightPolishTests(3);analyze-p78.py 复跑仍 PASS;正午帧与 P78 完全一致=白天零回归。 - Desktop 367/367, Kernel 120/120, digest 953775FA...F7F6C 不变
Diffstat (limited to 'src/LivingVillage.Desktop/SceneDetailRender.fs')
-rw-r--r--src/LivingVillage.Desktop/SceneDetailRender.fs64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/SceneDetailRender.fs b/src/LivingVillage.Desktop/SceneDetailRender.fs
index df2fa10..8bda8a9 100644
--- a/src/LivingVillage.Desktop/SceneDetailRender.fs
+++ b/src/LivingVillage.Desktop/SceneDetailRender.fs
@@ -137,9 +137,71 @@ module SceneDetailRender =
for (rect, color) in VillageArt.lanternGlowLayers cx cy radius 5 255 214 150 peak do
spriteBatch.Draw(pixel, rect, color)
+ /// P79 夜帧炊烟增强:烟柱(3 段向上堆叠)+ 外发光。只在夜帧叠加绘制,白天帧不受影响。
+ let private drawNightSmoke
+ (spriteBatch: SpriteBatch)
+ (textures: VillageArt.ArtTextures)
+ (pixel: Texture2D)
+ (camera: Vector2)
+ (map: MapGen.Result)
+ (tick: int64)
+ (nightStrength: float32) =
+ let alpha = SceneDetail.nightSmokeAlphaAt nightStrength
+ let glowPeak = SceneDetail.nightSmokeGlowPeakAt nightStrength
+ let source = VillageArt.atlasTileRectangle (22 + SceneDetail.smokeFrame tick)
+ let cell = SceneDetail.smokeCellSize nightStrength
+ for (x, y) in SceneDetail.smokeSourceTiles map do
+ let seed = x * 29 + y * 11
+ let sway, rise = SceneDetail.smokeDrift tick seed
+ let baseX = tileX camera x + (Sim.tilePixels - cell) / 2
+ let baseY = tileY camera y + (Sim.tilePixels - cell) / 2
+ // 外发光:暖色径向柔光,让烟柱在夜色里浮起。
+ for (rect, glowColor) in
+ VillageArt.lanternGlowLayers
+ (baseX + cell / 2)
+ (baseY + rise)
+ SceneDetail.nightSmokeGlowRadius
+ 4
+ 255
+ 236
+ 200
+ glowPeak do
+ spriteBatch.Draw(pixel, rect, glowColor)
+ // 烟柱:自屋顶向上堆叠,越上越淡,并在每段叠一枚中性柔光团(外发光),
+ // 弥补烟精灵本身 alpha 很低的问题,使夜色里每一缕烟柱都清晰可辨。
+ for segment in 0 .. SceneDetail.nightSmokeSegments - 1 do
+ let segmentAlpha = max 1 (alpha * (SceneDetail.nightSmokeSegments - segment) / SceneDetail.nightSmokeSegments)
+ let segmentColor = VillageArt.premultiply 246 242 232 segmentAlpha
+ let sx = baseX + sway * (segment + 1) / 2
+ let sy = baseY + rise - segment * SceneDetail.nightSmokeSegmentLift
+ spriteBatch.Draw(textures.TileAtlas, Rectangle(sx, sy, cell, cell), source, segmentColor)
+ let puffPeak = max 1 (glowPeak * (SceneDetail.nightSmokeSegments - segment) / (SceneDetail.nightSmokeSegments + 1))
+ for (rect, puffColor) in
+ VillageArt.lanternGlowLayers (sx + cell / 2) (sy + cell / 2) 12 3 238 242 248 puffPeak do
+ spriteBatch.Draw(pixel, rect, puffColor)
+
+ /// P79 夜景光晕去叠:每个光源最多 2 层(内芯 + 外环)、层间暗隙、半径收紧到 3 tile。
+ let private drawNightHalos
+ (spriteBatch: SpriteBatch)
+ (pixel: Texture2D)
+ (camera: Vector2)
+ (map: MapGen.Result)
+ (includeRoadLanterns: bool)
+ (nightStrength: float32) =
+ let peak = SceneDetail.nightHaloPeakAlphaAt nightStrength
+ if peak > 0 then
+ let half = Sim.tilePixels / 2
+ let radius = SceneDetail.nightHaloRadiusTiles * Sim.tilePixels
+ for (lx, ly) in VillageArt.nightLightTilesWith includeRoadLanterns map do
+ let cx = tileX camera lx + half
+ let cy = tileY camera ly + half
+ for (rect, color) in VillageArt.haloRingLayers cx cy radius peak do
+ spriteBatch.Draw(pixel, rect, color)
+
/// P78 夜帧加成层(水面光斑 + 桥头窄光晕):在 veil 之后调用,故不被夜色乘暗、仍醒目。
let drawNight
(spriteBatch: SpriteBatch)
+ (textures: VillageArt.ArtTextures)
(pixel: Texture2D)
(camera: Vector2)
(map: MapGen.Result)
@@ -147,6 +209,8 @@ module SceneDetailRender =
(nightStrength: float32) =
drawNightWater spriteBatch pixel camera map tick nightStrength
drawBridgeHalos spriteBatch pixel camera map nightStrength
+ drawNightHalos spriteBatch pixel camera map textures.Cc0TileAtlas.IsSome nightStrength
+ drawNightSmoke spriteBatch textures pixel camera map tick nightStrength
/// 一次性绘制全部 P47 场景细节(倒影 → 岸边芦苇 → 漂浮元素 → 近景前景层 → P78 炊烟)。
let draw