From 533b39f6ccc6a2608c43659430e79d996fe049e2 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Tue, 22 Sep 2026 11:31:13 +0800 Subject: feat(desktop): P28 整图夜景取证(真实 tint + 月光 veil) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LV_MAPGEN_NIGHT=1 时整图按 23:30 的 WorldTint 与 golden/moonlight veil 渲染 - RenderMapGen 参数化 tint/veil tick,与 DrawWorldView 共用同一套纯函数 --- src/LivingVillage.Desktop/Game.fs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs index 824c1c1..38d9e94 100644 --- a/src/LivingVillage.Desktop/Game.fs +++ b/src/LivingVillage.Desktop/Game.fs @@ -305,6 +305,9 @@ type LivingVillageGame() as this = match Environment.GetEnvironmentVariable("LV_MAPGEN_FIT_HEIGHT") with | null | "" -> 0 | v -> match Int32.TryParse v with (true, value) when value > 0 -> value | _ -> 0 + // P28 夜景取证:LV_MAPGEN_NIGHT=1 时整图按 23:30 的真实 tint + 月光 veil 渲染。 + let mapGenNight = Environment.GetEnvironmentVariable("LV_MAPGEN_NIGHT") = "1" + let mapGenNightTick = if mapGenNight then M6Presentation.resolveStartTick (Some 23.5) false else 0L let mutable mapGenResult = Unchecked.defaultof let mutable mapGenGenMs = 0.0 @@ -871,16 +874,28 @@ type LivingVillageGame() as this = this.Exit() /// P20 证据:把一次 MapGen 绘制渲染到指定尺寸离屏 target,返回绘制瓦片数与纹理。 - member private this.RenderMapGen (targetWidth: int) (targetHeight: int) (camX: int) (camY: int) (drawFitted: bool) : int * Texture2D = + /// P28:可传入世界 tint 与可选 veil tick(夜景取证用)。 + member private this.RenderMapGen (targetWidth: int) (targetHeight: int) (camX: int) (camY: int) (drawFitted: bool) (tint: Color) (veilTick: int64 option) : int * Texture2D = use target = new RenderTarget2D(this.GraphicsDevice, targetWidth, targetHeight) this.GraphicsDevice.SetRenderTarget target this.GraphicsDevice.Clear(Color(18, 26, 20)) spriteBatch.Begin() let drawn = if drawFitted then - VillageArt.drawMapFitted spriteBatch artTextures pixel targetWidth targetHeight mapGenResult Color.White + VillageArt.drawMapFitted spriteBatch artTextures pixel targetWidth targetHeight mapGenResult tint else - VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) targetWidth targetHeight mapGenResult 0L Color.White + VillageArt.drawMapViewport spriteBatch artTextures pixel (Vector2(float32 camX, float32 camY)) targetWidth targetHeight mapGenResult 0L tint + // 与 DrawWorldView 同一套纯函数 veil,保证取证夜景=真实渲染夜景。 + match veilTick with + | Some tick -> + let golden = M6Presentation.goldenVeilAlpha tick + if golden > 0 then + spriteBatch.Draw(pixel, Rectangle(0, 0, targetWidth, targetHeight), VillageArt.premultiply 255 150 70 golden) + let moon = M6Presentation.moonlightVeilAlpha tick + if moon > 0 then + let mr, mg, mb = M6Presentation.moonlightRgb + spriteBatch.Draw(pixel, Rectangle(0, 0, targetWidth, targetHeight), VillageArt.premultiply mr mg mb moon) + | None -> () spriteBatch.End() this.GraphicsDevice.SetRenderTarget null let data = Array.zeroCreate (targetWidth * targetHeight) @@ -894,25 +909,27 @@ type LivingVillageGame() as this = System.IO.Directory.CreateDirectory recordDirectory |> ignore let viewport = this.GraphicsDevice.Viewport let mapCell = 6 - let fittedDrawn, fittedTexture = this.RenderMapGen (mapGenResult.Width * mapCell) (mapGenResult.Height * mapCell) 0 0 true + let mapTint = if mapGenNight then (M6Presentation.profileAtTick mapGenNightTick).WorldTint else Color.White + let mapVeil = if mapGenNight then Some mapGenNightTick else None + let fittedDrawn, fittedTexture = this.RenderMapGen (mapGenResult.Width * mapCell) (mapGenResult.Height * mapCell) 0 0 true mapTint mapVeil use _fitted = fittedTexture use stream = System.IO.File.Create(sprintf "%s/p20b-map-%dx%d-seed%d.png" recordDirectory mapGenResult.Width mapGenResult.Height (int mapGenResult.Seed)) fittedTexture.SaveAsPng(stream, fittedTexture.Width, fittedTexture.Height) - printfn "mapgen-fitted drawn=%d png=%dx%d" fittedDrawn fittedTexture.Width fittedTexture.Height + printfn "mapgen-fitted drawn=%d png=%dx%d night=%b" fittedDrawn fittedTexture.Width fittedTexture.Height mapGenNight // P28:整图按指定像素目标再渲染一次(真实帧)。1024x768 -> 512x384 图恰为 2px/tile, // 用于证明两民居变体在「整图 1 tile≈2px」缩放下肉眼可分。 if mapGenFitWidth > 0 && mapGenFitHeight > 0 then - let fitDrawn, fitTexture = this.RenderMapGen mapGenFitWidth mapGenFitHeight 0 0 true + let fitDrawn, fitTexture = this.RenderMapGen mapGenFitWidth mapGenFitHeight 0 0 true mapTint mapVeil use _fit = fitTexture use fitStream = System.IO.File.Create(sprintf "%s/p28-fit-%dx%d-seed%d.png" recordDirectory mapGenFitWidth mapGenFitHeight (int mapGenResult.Seed)) fitTexture.SaveAsPng(fitStream, mapGenFitWidth, mapGenFitHeight) - printfn "mapgen-fit drawn=%d png=%dx%d" fitDrawn mapGenFitWidth mapGenFitHeight + printfn "mapgen-fit drawn=%d png=%dx%d night=%b" fitDrawn mapGenFitWidth mapGenFitHeight mapGenNight let clampRange maximum value = max 0 (min (max 0 maximum) value) let camX = clampRange (mapGenResult.Width * Sim.tilePixels - viewport.Width) ((mapGenResult.Width * Sim.tilePixels - viewport.Width) / 2) let camY = clampRange (mapGenResult.Height * Sim.tilePixels - viewport.Height) ((mapGenResult.Height * Sim.tilePixels - viewport.Height) / 2) - let culledDrawn, culledTexture = this.RenderMapGen viewport.Width viewport.Height camX camY false + let culledDrawn, culledTexture = this.RenderMapGen viewport.Width viewport.Height camX camY false Color.White None use _culled = culledTexture use culledStream = System.IO.File.Create(sprintf "%s/p20b-culled-%dx%d-seed%d.png" recordDirectory mapGenResult.Width mapGenResult.Height (int mapGenResult.Seed)) culledTexture.SaveAsPng(culledStream, viewport.Width, viewport.Height) @@ -924,7 +941,7 @@ type LivingVillageGame() as this = | (bx, by) :: _ -> let detailCamX = clampRange (mapGenResult.Width * Sim.tilePixels - viewport.Width) (bx * Sim.tilePixels - viewport.Width / 2) let detailCamY = clampRange (mapGenResult.Height * Sim.tilePixels - viewport.Height) (by * Sim.tilePixels - viewport.Height / 2) - let detailDrawn, detailTexture = this.RenderMapGen viewport.Width viewport.Height detailCamX detailCamY false + let detailDrawn, detailTexture = this.RenderMapGen viewport.Width viewport.Height detailCamX detailCamY false Color.White None use _detail = detailTexture use detailStream = System.IO.File.Create(sprintf "%s/p20b-detail-%dx%d-seed%d.png" recordDirectory mapGenResult.Width mapGenResult.Height (int mapGenResult.Seed)) detailTexture.SaveAsPng(detailStream, detailTexture.Width, detailTexture.Height) -- cgit v1.2.3