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 =