From cb6150ff4a2f026a949d6efe89d213675c74a731 Mon Sep 17 00:00:00 2001
From: pkuzic
Date: Fri, 25 Sep 2026 02:53:02 +0100
Subject: [PATCH 1/4] MONKEY (sky): sky-* capture scenarios (dusk, night,
zenith night, overcast)
Co-Authored-By: Claude Opus 5.5
---
crates/benilla-app/src/capture/scenarios.rs | 35 +++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/crates/benilla-app/src/capture/scenarios.rs b/crates/benilla-app/src/capture/scenarios.rs
index d970a9fd..7da0b3fa 100644
--- a/crates/benilla-app/src/capture/scenarios.rs
+++ b/crates/benilla-app/src/capture/scenarios.rs
@@ -1379,6 +1379,41 @@ pub(super) const ON_DEMAND: &[Scenario] = &[
minute: 0,
ui: None,
},
+ // MONKEY (sky): the sky lane's fixtures. Dusk looks from the Goldshire lake toward the low sun
+ // (az 45°, elev ≈5° at 20:00); night looks away from the moon at 01:00 (stars at full curve);
+ // zenith is the high dome at night. Overcast is `sky-overcast` under `WOW_WEATHER=rain,0.6`.
+ Scenario {
+ name: "sky-elwynn-dusk",
+ map: Some(MAP_AZEROTH),
+ eye: WATER_EYE,
+ look: [-9315.0, -98.6, 102.3],
+ minute: 1200,
+ ui: None,
+ },
+ Scenario {
+ name: "sky-elwynn-night",
+ map: Some(MAP_AZEROTH),
+ eye: WATER_EYE,
+ look: [-9739.0, -522.6, 210.8],
+ minute: 60,
+ ui: None,
+ },
+ Scenario {
+ name: "sky-zenith-night",
+ map: Some(MAP_AZEROTH),
+ eye: SKY_EYE,
+ look: [-9050.7, -230.7, 387.0],
+ minute: 60,
+ ui: None,
+ },
+ Scenario {
+ name: "sky-overcast",
+ map: Some(MAP_AZEROTH),
+ eye: SKY_EYE,
+ look: [-8797.0, 23.0, 264.0],
+ minute: 1000,
+ ui: None,
+ },
];
/// The owner's reported vantage for the lava-glow report: `(-7048.8, -1000.6, 242.0)` facing
From f863e4640fb1c38766df7c3b4476c5e6498b53c5 Mon Sep 17 00:00:00 2001
From: pkuzic
Date: Fri, 25 Sep 2026 04:09:34 +0100
Subject: [PATCH 2/4] =?UTF-8?q?MONKEY=20(sky):=20skyQuality=20tier=20?=
=?UTF-8?q?=E2=80=94=20smooth=20gradient,=20sun=20glow,=20night=20sky,=20H?=
=?UTF-8?q?igh=20cloud=20detail=20+=20sun=20march?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
skyQuality 0 Classic (unchanged), 1 Enhanced, 2 High; Advanced Graphics row (EN+RU),
cvar bridge, sky-* scenarios above the canopy. Cloud technique ported from WarcraftXL
wxl-retail-clouds (THIRD-PARTY.md).
Co-Authored-By: Claude Opus 5.5
---
LIGHTING.md | 2 +
THIRD-PARTY.md | 13 +
crates/benilla-app/assets/ui/OptionsFrame.xml | 36 ++-
crates/benilla-app/src/capture/scenarios.rs | 33 ++-
crates/benilla-app/src/cvars.rs | 6 +
crates/benilla-app/src/game_plugins.rs | 2 +
crates/benilla-app/src/lib.rs | 2 +
crates/benilla-app/src/sky_quality.rs | 49 ++++
.../src/ui_script/options_tests.rs | 2 +
crates/benilla-app/src/video.rs | 6 +
crates/benilla-world/src/clouds/layer.rs | 52 ++++
crates/benilla-world/src/clouds/mod.rs | 2 +
crates/benilla-world/src/lib.rs | 2 +
crates/benilla-world/src/shaders.rs | 5 +-
crates/benilla-world/src/shaders/cloud.wgsl | 47 ++-
crates/benilla-world/src/shaders/sky.wgsl | 44 +++
crates/benilla-world/src/shaders/sky_fx.wgsl | 269 ++++++++++++++++++
crates/benilla-world/src/sky.rs | 58 +++-
crates/benilla-world/src/sky_fx.rs | 117 ++++++++
crates/benilla-world/src/world_plugins.rs | 2 +
20 files changed, 734 insertions(+), 15 deletions(-)
create mode 100644 THIRD-PARTY.md
create mode 100644 crates/benilla-app/src/sky_quality.rs
create mode 100644 crates/benilla-world/src/shaders/sky_fx.wgsl
create mode 100644 crates/benilla-world/src/sky_fx.rs
diff --git a/LIGHTING.md b/LIGHTING.md
index 2122d3df..d0a9c7cd 100644
--- a/LIGHTING.md
+++ b/LIGHTING.md
@@ -24,6 +24,7 @@ behind each constant.
| Moon shadows | at night the same shadow rig re-aims at the moon and casts a faint shadow; dims only the night sky term, never point lights | `moonShadowStrength` |
| Ground-effect spells | Flamestrike, Rain of Fire, Consecration, Flare and fire traps light the ground for their duration; frost and nature areas stay dark | `spellLightGain` |
| 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 quality | Enhanced: the five Light.dbc sky stops through a smooth monotone curve in linear light (no bands at the rings), a soft sun glow tinted by sun and fog colour (fades at night and under cloud), a procedural star field with twinkle and a faint Milky Way over the stock `Stars.m2`. High adds domain-warped cloud detail and sun-lit clouds (self-shadow, silver lining; technique from WarcraftXL, see `THIRD-PARTY.md`). Classic is the reference sky unchanged | Advanced Graphics → Sky Quality, cvar `skyQuality` 0 Classic / 1 Enhanced / 2 High, env `WOW_SKY_QUALITY` |
| 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 /
@@ -47,6 +48,7 @@ is its own module, documented in `WATER.md`.
`character_shadow.rs`, `world_shadow.rs`, `blob_shadow.rs`, `entities/carried_light.rs`,
`entities/spell_fx/lifecycle.rs`, `dynamic_interior.rs`, `debug_panel/lighting_controls.rs`, and
the cvars in `cvars.rs` / `video.rs`.
+- **Sky** (`crates/benilla-world/src`): `sky_fx.rs` (tier, clock, glow inputs), `shaders/sky_fx.wgsl` (gradient curve, glow, stars, cloud noise), the tier branches in `shaders/sky.wgsl` and `shaders/cloud.wgsl`, `clouds/layer.rs` (`update_cloud_fx`); the cvar bridge is `benilla-app/src/sky_quality.rs`.
- **Tools**: `benilla-extract wmolights [--verts ]`, `wmolamps`, `m2firescan`
print the inputs the system works from (groups, batch classes, portals, claims, flame emitters).
diff --git a/THIRD-PARTY.md b/THIRD-PARTY.md
new file mode 100644
index 00000000..d28892d1
--- /dev/null
+++ b/THIRD-PARTY.md
@@ -0,0 +1,13 @@
+# Third-party code and techniques
+
+## WarcraftXL
+
+[WarcraftXL](https://github.com/WarcraftXL) by **iThorgrim** is a 3.3.5 client extension. The files
+below port code or a technique from it; each carries the header line
+`Ported from WarcraftXL (https://github.com/WarcraftXL) by iThorgrim — module , .`
+
+| File | WarcraftXL module | Source files | What was taken |
+|---|---|---|---|
+| `crates/benilla-world/src/shaders/sky_fx.wgsl` | wxl-retail-clouds | `Clouds.cpp`, `Clouds.hpp` | Domain-warped billow fbm (quintic value noise, 0.6 cotton blend, 0.55 octave gain) for the cloud detail |
+| `crates/benilla-world/src/shaders/cloud.wgsl` | wxl-retail-clouds | `Clouds.cpp` | The 3-tap march toward the sun (self-shadow, ambient floor) and the one-tap silver lining |
+| `crates/benilla-world/src/clouds/layer.rs` (`update_cloud_fx`) | wxl-retail-clouds | `Clouds.cpp` | March direction = the sun projected on the sheet, strength folded by its flatness (noon clouds evenly lit) |
diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml
index 71e19e82..b1d74e0b 100644
--- a/crates/benilla-app/assets/ui/OptionsFrame.xml
+++ b/crates/benilla-app/assets/ui/OptionsFrame.xml
@@ -494,6 +494,8 @@
lightingQuality = "Lighting Quality",
-- MONKEY (volumetric fog): localised atmospheric quality row.
volumetricFog = "Volumetric Fog",
+ -- MONKEY (sky): the sky tier row.
+ skyQuality = "Sky Quality",
fogOff = "Off",
waterQuality = "Water Quality",
waterClassic = "Classic",
@@ -534,6 +536,12 @@
-- MONKEY (volumetric fog): explain cost and the shadow-map dependency.
VOLUMETRIC_FOG =
"Off disables volumetric fog. Low adds nearby haze and sun or moon shafts with fewer steps; High uses more steps for smoother shafts. Mist is heavier at dawn and in bad weather, and subtle indoors. Shafts require shadows; with shadows off only haze remains.",
+ -- MONKEY (sky): what each sky tier adds.
+ SKY_QUALITY =
+ "Classic is the original client's sky. Enhanced smooths the sky's colour "
+ .. "gradient, adds a soft glow around the sun and a starry night sky with the "
+ .. "Milky Way. High also gives the clouds finer detail and sunlit edges. "
+ .. "Costs very little.",
WATER_QUALITY =
"Classic is the original client's water. Enhanced adds soft shorelines, "
.. "animated foam around shores and objects, moving wave highlights, sky reflection "
@@ -618,6 +626,8 @@
lightingQuality = "Качество освещения",
-- MONKEY (volumetric fog): Russian atmospheric quality row.
volumetricFog = "Объёмный туман",
+ -- MONKEY (sky): the sky tier row.
+ skyQuality = "Качество неба",
fogOff = "Выкл",
waterQuality = "Качество воды",
waterClassic = "Классическое",
@@ -660,6 +670,12 @@
-- MONKEY (volumetric fog): localised effect and cost explanation.
VOLUMETRIC_FOG =
"Выкл отключает объёмный туман. Низкое добавляет дымку вблизи и лучи солнца или луны с меньшим числом шагов; Высокое использует больше шагов для более плавных лучей. Туман гуще на рассвете и в непогоду, а в помещениях слабее. Для лучей нужны тени; без теней остаётся только дымка.",
+ -- MONKEY (sky): what each sky tier adds.
+ SKY_QUALITY =
+ "«Классическое» — небо оригинального клиента. «Улучшенное» сглаживает "
+ .. "цветовой переход неба, добавляет мягкое сияние вокруг солнца и звёздное "
+ .. "ночное небо с Млечным Путём. «Высокое» также добавляет облакам мелкие "
+ .. "детали и освещённые солнцем края. Почти не влияет на производительность.",
WATER_QUALITY =
"«Классическое» — вода оригинального клиента. «Улучшенное» добавляет плавные переходы у берегов, "
.. "анимированную пену у берегов и вокруг объектов, подвижные блики на волнах, отражение неба "
@@ -796,6 +812,8 @@
AdvancedGraphics = {
-- MONKEY (volumetric fog): include in refresh, defaults and search.
"RowLightingQuality", "RowWaterQuality", "RowVolumetricFog",
+ -- MONKEY (sky): the sky tier row.
+ "RowSkyQuality",
"RowCharacterShadows", "RowWorldShadows", "RowShadowDistance",
"RowShadowResolution", "RowMoonShadows",
"RowInteriorLight", "RowInteriorShadows", "RowExteriorShadows", "RowTorchSoft",
@@ -2602,11 +2620,27 @@
})
-
+
+
+
+ OptionsRow_OnLoad(self, "skyQuality", BENILLA_ADVGFX.skyQuality,
+ "BENILLA_TOOLTIP_SKY_QUALITY")
+ OptionsDropdownRow_Setup(self, {
+ { text = BENILLA_ADVGFX.waterClassic, value = "0" },
+ { text = BENILLA_ADVGFX.waterEnhanced, value = "1" },
+ { text = BENILLA_ADVGFX.waterHigh, value = "2" },
+ })
+
+
+
+
+
+
+
OptionsRow_OnLoad(self, "characterShadows",
BENILLA_ADVGFX.characterShadows,
diff --git a/crates/benilla-app/src/capture/scenarios.rs b/crates/benilla-app/src/capture/scenarios.rs
index 7da0b3fa..2e1ef189 100644
--- a/crates/benilla-app/src/capture/scenarios.rs
+++ b/crates/benilla-app/src/capture/scenarios.rs
@@ -253,6 +253,8 @@ pub(super) enum SubjectKind {
pub(super) const GROUND_EYE: [f32; 3] = [-8980.0, -160.0, 110.0];
pub(super) const GROUND_LOOK: [f32; 3] = [-8949.95, -132.49, 84.0];
pub(super) const SKY_EYE: [f32; 3] = [-8980.0, -160.0, 112.0];
+/// MONKEY (sky): 80 yd over the Northshire sky eye, above every canopy.
+pub(super) const SKY_HIGH_EYE: [f32; 3] = [-8980.0, -160.0, 190.0];
pub(super) const SKY_LOOK: [f32; 3] = [-8740.0, 80.0, 168.0]; // up + out: horizon in the lower third, dome above
// Farmhouse viewpoints (decision 0071): compass looks from the human-start login spot. Kept
@@ -1379,41 +1381,50 @@ pub(super) const ON_DEMAND: &[Scenario] = &[
minute: 0,
ui: None,
},
- // MONKEY (sky): the sky lane's fixtures. Dusk looks from the Goldshire lake toward the low sun
- // (az 45°, elev ≈5° at 20:00); night looks away from the moon at 01:00 (stars at full curve);
- // zenith is the high dome at night. Overcast is `sky-overcast` under `WOW_WEATHER=rain,0.6`.
+ // MONKEY (sky): the sky lane's fixtures, from 80 yd above Northshire (clear of the canopy).
+ // Dusk faces the low sun (az 45°, elev ≈5° at 20:00); night faces away from the moon at 01:00
+ // (full star curve); zenith looks nearly straight up; overcast is meant for
+ // `WOW_WEATHER=1,0.5`; noon faces away from the sun.
Scenario {
name: "sky-elwynn-dusk",
map: Some(MAP_AZEROTH),
- eye: WATER_EYE,
- look: [-9315.0, -98.6, 102.3],
+ eye: SKY_HIGH_EYE,
+ look: [-8770.0, 50.0, 232.0],
minute: 1200,
ui: None,
},
Scenario {
name: "sky-elwynn-night",
map: Some(MAP_AZEROTH),
- eye: WATER_EYE,
- look: [-9739.0, -522.6, 210.8],
+ eye: SKY_HIGH_EYE,
+ look: [-9164.0, -344.0, 340.0],
minute: 60,
ui: None,
},
Scenario {
name: "sky-zenith-night",
map: Some(MAP_AZEROTH),
- eye: SKY_EYE,
- look: [-9050.7, -230.7, 387.0],
+ eye: SKY_HIGH_EYE,
+ look: [-9017.0, -197.0, 485.0],
minute: 60,
ui: None,
},
Scenario {
name: "sky-overcast",
map: Some(MAP_AZEROTH),
- eye: SKY_EYE,
- look: [-8797.0, 23.0, 264.0],
+ eye: SKY_HIGH_EYE,
+ look: [-9185.0, 45.0, 268.0],
minute: 1000,
ui: None,
},
+ Scenario {
+ name: "sky-noon",
+ map: Some(MAP_AZEROTH),
+ eye: SKY_HIGH_EYE,
+ look: [-9185.0, -365.0, 268.0],
+ minute: 720,
+ ui: None,
+ },
];
/// The owner's reported vantage for the lava-glow report: `(-7048.8, -1000.6, 242.0)` facing
diff --git a/crates/benilla-app/src/cvars.rs b/crates/benilla-app/src/cvars.rs
index 31a7eced..a72f81f4 100644
--- a/crates/benilla-app/src/cvars.rs
+++ b/crates/benilla-app/src/cvars.rs
@@ -921,6 +921,12 @@ pub(crate) const REGISTERED: &[Registered] = &[
),
// MONKEY (volumetric fog): saved live tier; capture override stays session-only.
ours("volumetricFog", "1", "benilla's own: near-field volumetric fog, 0 Off / 1 Low / 2 High"),
+ // MONKEY (sky): the sky tier; the High graphics preset sets 2.
+ ours(
+ "skyQuality",
+ "0",
+ "benilla's own: sky quality, 0 Classic / 1 Enhanced (smooth gradient, sun glow, stars) / \n 2 High (+ detailed sun-lit clouds)",
+ ),
ours(
"waterQuality",
"1",
diff --git a/crates/benilla-app/src/game_plugins.rs b/crates/benilla-app/src/game_plugins.rs
index adda66ec..2e3fe53b 100644
--- a/crates/benilla-app/src/game_plugins.rs
+++ b/crates/benilla-app/src/game_plugins.rs
@@ -245,6 +245,8 @@ impl PluginGroup for GamePlugins {
.add(crate::dynamic_interior::DynamicInteriorPlugin)
// MONKEY (volumetric fog): bridge the live setting to Bevy.
.add(crate::volumetric_fog::VolumetricFogPlugin)
+ // MONKEY (sky): the sky tier bridge.
+ .add(crate::sky_quality::SkyQualityPlugin)
// The realmlist (decision 1667) — the logon address the login screen edits. Same reason as
// VideoPlugin above: it is a CVar knob, so its resource has to exist before `load_config`.
.add(crate::realmlist::RealmlistPlugin)
diff --git a/crates/benilla-app/src/lib.rs b/crates/benilla-app/src/lib.rs
index a7f9ac23..2f38edc0 100644
--- a/crates/benilla-app/src/lib.rs
+++ b/crates/benilla-app/src/lib.rs
@@ -75,6 +75,8 @@ mod doodad_events;
// MONKEY (volumetric fog): optional near-field atmosphere plugin.
mod volumetric_fog;
mod dynamic_interior;
+// MONKEY (sky): the skyQuality cvar bridge.
+mod sky_quality;
mod entities;
mod fishing_line;
mod footprints;
diff --git a/crates/benilla-app/src/sky_quality.rs b/crates/benilla-app/src/sky_quality.rs
new file mode 100644
index 00000000..e56503e7
--- /dev/null
+++ b/crates/benilla-app/src/sky_quality.rs
@@ -0,0 +1,49 @@
+//! MONKEY (sky): the `skyQuality` cvar → [`benilla_world::sky_fx::SkyQuality`] bridge.
+//!
+//! 0 Classic (the reference's sky, unchanged), 1 Enhanced (smooth gradient, sun glow, night sky),
+//! 2 High (+ detailed, sun-lit clouds). `$WOW_SKY_QUALITY` pins the tier for the session, so
+//! captures stay independent of `config.toml`.
+
+use bevy::prelude::*;
+use benilla_world::sky_fx::SkyQuality;
+
+use crate::video::VideoConfig;
+
+pub(crate) struct SkyQualityPlugin;
+
+impl Plugin for SkyQualityPlugin {
+ fn build(&self, app: &mut App) {
+ app.init_resource::().add_systems(Update, bridge);
+ }
+}
+
+fn bridge(video: Res, mut out: ResMut, mut pinned: Local