From 233b469b0116fa8b6cad86ace04138cd1574d6ac Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 6 Jul 2026 22:45:50 +0200 Subject: [PATCH] fix #176/#181 (A7 fix #2): stationary server-weenie fixtures take retail's STATIC light curve - isDynamic decided by motion, not origin The former #143 flag forced every server-object light onto the D3D dynamic path (1/d attenuation, range x1.5); retail's stationary fixtures use the static calc_point_light curve (0x0059c8b0, Ghidra-verified: f=(1-d/range)*intensity*wrap/d^3 beyond 1m, range=falloff*1.3, per-channel colour clamp) - the dynamic path burned every Facility Hub lamp ~10x hotter than retail at 3m, producing the saturated magenta wash that zebra-striped normal wall geometry into the #176 'stripes/triangles' pattern (VSync-on test + clean captures characterized it as STATIC over-bright content, not flicker/tearing/camera). The shader's static branch already implements the verified curve faithfully (mesh_modern.vert pointContribution - its wrap constants pin LIGHT_POINT_RANGE=0.75), so the whole fix is the registration decision. Site-A lights are all stationary today (AP-44); genuinely moving lights re-earn isDynamic when they exist. Suites green. Co-Authored-By: Claude Fable 5 --- src/AcDream.App/Rendering/GameWindow.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 6bb93d10..0995a872 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -3714,7 +3714,18 @@ public sealed class GameWindow : IDisposable ownerId: entity.Id, entityPosition: entity.Position, entityRotation: entity.Rotation, - isDynamic: true, // #143: server-object lights take the D3D dynamic path (1/d att, range×1.5) + // A7 fix #2 (#176/#181): isDynamic is decided by whether the light + // MOVES, not by weenie-vs-dat origin. Server-spawned FIXTURES + // (lanterns, braziers) are stationary — they take retail's STATIC + // curve (calc_point_light 0x0059c8b0: 1/d³ beyond 1 m, range×1.3, + // per-channel colour clamp), not the D3D dynamic path (1/d, + // range×1.5) the former #143 flag forced — which burned every + // fixture ~10× hotter than retail at 3 m: the magenta wash that + // zebra-striped the Facility Hub walls. Site-A lights are all + // stationary today (AP-44: they don't follow bearers); genuinely + // moving lights (projectiles, portal swirls) re-earn isDynamic + // when they exist. + isDynamic: false, cellId: entity.ParentCellId ?? 0u); // A7 #176/#177: scope to the owning cell's visibility foreach (var ls in loaded) _lightingSink.RegisterOwnedLight(ls);