From 9e809bc66117cbac4faf07e6d91a41da7f8c108a Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 13 Jun 2026 20:55:14 +0200 Subject: [PATCH] =?UTF-8?q?diag:=20ACDREAM=5FPROBE=5FLIGHT=20[light-detail?= =?UTF-8?q?]=20=E2=80=94=20per-light=20range/intensity/cone=20(#133=20A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 3 +- .../Rendering/RenderingDiagnostics.cs | 47 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 24472020..b3e5efa0 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -7641,7 +7641,8 @@ public sealed class GameWindow : IDisposable sunIntensity: Lighting.Sun?.Intensity ?? 0f, registeredLights: Lighting.RegisteredCount, activeLights: (int)ubo.CellAmbient.W, - playerCellId: playerRoot?.CellId ?? 0u); + playerCellId: playerRoot?.CellId ?? 0u, + lights: Lighting); // Never cull the landblock the player is currently on. uint? playerLb = null; diff --git a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs index a070fe54..872285e4 100644 --- a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs +++ b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs @@ -372,12 +372,25 @@ public static class RenderingDiagnostics /// /// #133 A7 — emit ONE rate-limited [light] line describing the - /// current scene-lighting state. Cheap no-op when + /// current scene-lighting state, followed (when + /// is supplied) by up to three [light-detail] lines for the nearest + /// ACTIVE point/spot lights. Cheap no-op when /// is false; otherwise fires at most /// once per second. Pull the values from the spot where /// GameWindow.UpdateSunFromSky set Lighting.CurrentAmbient /// / Lighting.Sun and where SceneLightingUbo.Build computed /// the active-slot count. + /// + /// The [light-detail] lines are the answer to the "candle-spotlight" + /// question — they expose each torch's REAL dat-derived runtime values + /// (range= Falloff metres, intensity=, cone= radians, + /// color=, distToViewer=) so it is visible in launch.log + /// whether dungeon torches are tiny-range points or wide cones and at what + /// intensity — without a screenshot: + /// + /// [light-detail] kind=Point range=<Falloff m> intensity=<I> cone=<rad> color=(r,g,b) distToViewer=<m> + /// + /// /// /// The playerInsideCell value driving the indoor branch. /// Cell ambient red (xyz of uCellAmbient). @@ -387,12 +400,16 @@ public static class RenderingDiagnostics /// Total point/spot lights registered with the LightManager. /// uCellAmbient.w — shader active-slot count (includes the zeroed sun slot indoors). /// The player's current cell id (0 if unresolved → outside). + /// The ticked LightManager (its Active list, sorted nearest-first by the + /// just-completed Tick). When non-null, drives the [light-detail] lines. Optional so existing call + /// sites / tests that only want the aggregate line keep compiling. public static void EmitLight(bool insideCell, float ambientR, float ambientG, float ambientB, float sunIntensity, int registeredLights, int activeLights, - uint playerCellId) + uint playerCellId, + AcDream.Core.Lighting.LightManager? lights = null) { if (!ProbeLightEnabled) return; @@ -406,6 +423,32 @@ public static class RenderingDiagnostics "[light] insideCell={0} ambient=({1:0.###},{2:0.###},{3:0.###}) sun={4:0.###} registeredLights={5} activeLights={6} playerCell=0x{7:X8}", insideCell, ambientR, ambientG, ambientB, sunIntensity, registeredLights, activeLights, playerCellId)); + + // #133 A7 (2026-06-13) — per-light detail for the "spotlight bubble" + // question. Dump the actual runtime dat-derived values of the nearest + // ~3 ACTIVE point/spot lights so the real Falloff/Intensity/ConeAngle + // are visible in launch.log (are torch ranges 1m or 10m? points or + // spots? what intensity?). The sun (Directional, slot 0) is skipped — + // it carries no Range/cone meaning. DistSq is already cached by + // LightManager.Tick this frame, so the active list is sorted nearest- + // first; we just take the first few non-directional entries. + if (lights is null) return; + var active = lights.Active; + int shown = 0; + const int MaxDetail = 3; + for (int i = 0; i < active.Length && shown < MaxDetail; i++) + { + var ls = active[i]; + if (ls is null) continue; + if (ls.Kind == AcDream.Core.Lighting.LightKind.Directional) continue; + + float dist = ls.DistSq >= 0f ? MathF.Sqrt(ls.DistSq) : 0f; + Console.WriteLine(string.Format(ci, + "[light-detail] kind={0} range={1:0.###} intensity={2:0.###} cone={3:0.####} color=({4:0.###},{5:0.###},{6:0.###}) distToViewer={7:0.###}", + ls.Kind, ls.Range, ls.Intensity, ls.ConeAngle, + ls.ColorLinear.X, ls.ColorLinear.Y, ls.ColorLinear.Z, dist)); + shown++; + } } private static bool _probeEnvCellEnabled =