diff --git a/LIGHTING.md b/LIGHTING.md
index 938ae2e6..7619dd2d 100644
--- a/LIGHTING.md
+++ b/LIGHTING.md
@@ -26,6 +26,7 @@ behind each constant.
| Volumetric fog | near-field haze that converges on the zone fog colour (clear within 10 yd, full by 150 yd; mistier at dawn and in bad weather, faint indoors) and sun/moon light shafts through gaps, sampled from the shadow map; own fullscreen pass after the main pass (`benilla-app/src/volumetric_fog.rs`) | Advanced Graphics → Volumetric Fog (Off/Low/High), cvar `volumetricFog`, env `WOW_VOLFOG=0\|1\|2` |
| Sky dithering | a faint screen-space dither in the FFXGlow combine so smooth sky and fog gradients do not band (MONKEY p0; was env-only) | Advanced Graphics → Sky Dithering, cvar `skyDither` 0/1 (default 0, Graphics preset High = 1), env `WOW_DITHER=1` still forces it on; bridge in `benilla-app/src/monkey_gfx.rs` |
| Modern fog | MONKEY (fog): distance fog in the style of the modern client. Radial distance; exponential from the zone's own start, fitted so 60 % survives mid-span and closed over the last stretch so the fog still ends where the zone authored it; a sun-fog lobe (the fog leans to the sun colour around the sun, fading out through dusk); the far fog shifts toward the sky's 1.8° ring so fogged land, the WDL hull and the sky dome's horizon meet in one colour; volumetric haze takes the same colour and no longer hazes sky pixels. The fog end stays the zone's up to farclip 777 and grows with farclip beyond it. Optional per-`LightParams` fields (height fog, sun/end fog, curve) from our `LightFogBand.dbc` (absent = derived from the 1.12 bands). Interior WMO fog stays classic | Advanced Graphics → Modern Fog, cvar `fogModel` 0 Classic (default, byte-identical) / 1 Modern (Graphics preset High = 1), env `WOW_FOGMODEL=0\|1`; `fog_hook.wgsl`, `benilla-world/src/lighting/fog_model.rs`, `benilla-formats/src/light/fog_band.rs` |
+| Lamp fog | MONKEY (lampfog): the fog fullscreen pass selects the nearest resolved exterior and interior point-table sources and analytically integrates their softened inverse-square light over the camera-to-scene-depth ray. A near-field haze floor makes lamps visible inside the ordinary volumetric haze's 10 yd clear zone; it is zero by day, stronger in rain/fog, and deliberately unshadowed. The table colour already includes intensity, flame flicker and `fireLightGain`. Halo output uses destination headroom and stays below 1.0, so a later bloom pass cannot blow it out | Advanced Graphics → Lamp Fog, cvar `lampFog` 0 Off (default, unchanged) / 1 Low (16 lamps) / 2 High (32 lamps; Graphics preset High = 2), env `WOW_LAMPFOG=0\|1\|2`; `benilla-app/src/volumetric_fog.rs` |
| Night and interior level | global dimming of the night sky term and of interior ambient | `nightGain`, `interiorGain`, `interiorBakeFloor` |
Players reach all of it from **Options -> Advanced Graphics** (a Lighting Quality preset Off / Low / Medium / High plus the individual rows; Off is the original client look). The dev build has a panel for all of it: **Ctrl+Shift+D → Lighting & shadows**, with Dim / Default /
@@ -81,6 +82,9 @@ is its own module, documented in `WATER.md`.
(`benilla-world/src/lighting/monkey_frame.rs`); `global_light::pack_monkey_frame` packs it after
the point table and fills `time_of_day` / `night` itself. All zero = no visual change.
- World lights use upstream's `WorldPointLight`, never Bevy's `PointLight`.
+- MONKEY (lampfog): `ResolvedPointLights` is a CPU-only read view of the live, truncated point table;
+ it does not add a row to the shared GPU buffer. Lamp selection is capped at 100 yd and ranks both
+ exterior and interior rows together before the 16/32 nearest limit is applied.
- WGSL only fails at pipeline creation, so a shader edit is verified by running a world scene, not
by `cargo check`.
- Exterior point lights are selected per draw unit (12 slots, ranked against the chunk's box); the
diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml
index bcc20ed7..d46381cd 100644
--- a/crates/benilla-app/assets/ui/OptionsFrame.xml
+++ b/crates/benilla-app/assets/ui/OptionsFrame.xml
@@ -523,6 +523,8 @@
skyDither = "Sky Dithering",
-- MONKEY (fog)
fogModel = "Modern Fog",
+ -- MONKEY (lampfog)
+ lampFog = "Lamp Fog",
yards = "%d yd",
tips = {
LIGHTING_QUALITY =
@@ -626,6 +628,12 @@
.. "sky's colour in the distance, so the land melts into the horizon. Each zone "
.. "keeps its own fog distance; above the original view-distance limit the fog "
.. "recedes with it.\n\nOff is the original client's fog. Practically free.",
+ -- MONKEY (lampfog)
+ LAMP_FOG =
+ "Makes nearby lamps and fires glow through the air after dark. Low uses the "
+ .. "nearest 16 lights; High uses 32. Rain and fog strengthen the halos. "
+ .. "The effect is unshadowed, but stops at visible scene depth.\n\n"
+ .. "Off is unchanged, and daylight is unchanged at every setting.",
},
},
ruRU = {
@@ -662,6 +670,8 @@
skyDither = "Дизеринг неба",
-- MONKEY (fog)
fogModel = "Современный туман",
+ -- MONKEY (lampfog)
+ lampFog = "Свечение фонарей в тумане",
yards = "%d ярд.",
tips = {
LIGHTING_QUALITY =
@@ -774,6 +784,12 @@
.. "так что земля растворяется в горизонте. Дальность тумана в каждой зоне "
.. "прежняя; за пределом дальности обзора оригинала туман отступает вместе с ней."
.. "\n\nВыключено — туман оригинального клиента. Почти ничего не стоит.",
+ -- MONKEY (lampfog)
+ LAMP_FOG =
+ "После заката ближайшие фонари и огни светятся сквозь воздух. Низкое "
+ .. "качество использует 16 ближайших источников, высокое — 32. Дождь и туман усиливают ореолы. "
+ .. "Эффект не рассчитывает тени, но обрывается на видимой глубине.\n\n"
+ .. "Выключено — без изменений; днём изображение не меняется при любом значении.",
},
},
}
@@ -836,6 +852,8 @@
"RowSkyDither",
-- MONKEY (fog)
"RowFogModel",
+ -- MONKEY (lampfog)
+ "RowLampFog",
},
-- Player Guild Names is a child of Player Names, as in 1.12 (l.702-708).
Nameplates = {
@@ -2886,6 +2904,22 @@
"BENILLA_TOOLTIP_FOG_MODEL")
+
+
+
+
+
+
+
+ OptionsRow_OnLoad(self, "lampFog", BENILLA_ADVGFX.lampFog,
+ "BENILLA_TOOLTIP_LAMP_FOG")
+ OptionsDropdownRow_Setup(self, {
+ { text = BENILLA_ADVGFX.fogOff, value = "0" },
+ { text = BENILLA_ADVGFX.qLow, value = "1" },
+ { text = BENILLA_ADVGFX.qHigh, value = "2" },
+ })
+
+