From 72dd5a0ce8d317ebd3d5f402c94061ad19fc5c8a Mon Sep 17 00:00:00 2001 From: pkuzic Date: Sat, 26 Sep 2026 15:55:15 +0100 Subject: [PATCH] MONKEY (leftovers): LightSkybox flags 0x8/0x10 plumbing; 0x10 suppresses the Modern sun-fog lobe SKYBOX_FORCE_SUN_SHAFTS (0x8) and SKYBOX_NO_SUN_FOG (0x10) constants, CameraSkybox::flag_weight (heaviest main layer carrying a flag). update_fog_model scales sun_fog_strength by 1 - weight of a 0x10 sky. LIGHTING.md documents both flags (0x8 consumer lands in the next commit). Co-Authored-By: Claude Opus 5.5 --- LIGHTING.md | 2 +- crates/benilla-formats/src/lib.rs | 6 +++- crates/benilla-formats/src/light.rs | 6 +++- crates/benilla-formats/src/light/skybox.rs | 4 +++ .../benilla-world/src/lighting/fog_model.rs | 5 ++++ crates/benilla-world/src/skybox.rs | 28 +++++++++++++++++++ 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/LIGHTING.md b/LIGHTING.md index 651e4aa7..7a182968 100644 --- a/LIGHTING.md +++ b/LIGHTING.md @@ -35,7 +35,7 @@ behind each constant. | Ambient occlusion | soft contact shadows under props, in wall-floor corners and around feet; depth-only SSAO at half resolution (depth-reconstructed normals, 6/12 spiral taps, 4x4 depth-aware blur, bilateral upsample) multiplied into the opaque scene after the opaque pass and before the water copy, so water, particles and UI are untouched; fades out 45-90 yd (Low) / 60-120 yd (High), spares sky and bright pixels; on alpha-tested foliage (a dense window of two-sided depth spikes) the blur widens its depth tolerance and the AO drops 40 %, which removes the leaf grain while planes, silhouettes and contact creases keep full AO (`benilla-app/src/ssao.rs`, `benilla-app/src/shaders/ssao.wgsl`) | Advanced Graphics → Ambient Occlusion (Off/Low/High; default Off, High preset 2), cvar `ambientOcclusion`, env `WOW_AO=0\|1\|2`, `WOW_AO_DEBUG=1..5` diagnostic views (factor, protection, distance, raw occlusion, foliage mask), `WOW_AO_GAIN`/`_RADIUS`/`_BIAS`/`_STRENGTH` tuning | | 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` | | City window daylight | MONKEY (fix-daylight/integration): a district WMO's oversized window batch (e.g. the Cathedral of Light's stained-glass walls) is split into window-sized daylight apertures, so the nave takes daylight pane by pane. Applies to WMOs loaded after a change | Advanced Graphics → City Window Daylight, cvar `daylightWindowSplit` 0/1 (default 1, the merged behaviour); `benilla-world/src/lighting/daylight.rs` (`set_window_split`), bridge `benilla-app/src/dynamic_interior.rs` | -| Zone skyboxes | the painted sky a zone's `LightParams` names (clear-weather slot, storm slot lerped by the storm blend) for the living, fading in by the Light sphere falloff with the modern client's crossfade (ghost > WMO > zone); extended `LightSkybox.dbc` flags `0x1` day cycle, `0x2` keep sun/moon/stars/clouds, `0x4` fog-colour horizon cone, plus a celestial second model; every skybox now plays its bones, texture transforms, colour and alpha tracks (`benilla-world/src/skybox.rs`, `skybox_anim.rs`, `benilla-formats/src/light/skybox.rs`) | Advanced Graphics → Zone Skyboxes, cvar `zoneSkyboxes` (0 Off default, 1 On; High = 1), env `WOW_ZONE_SKYBOXES=0\|1` | +| Zone skyboxes | the painted sky a zone's `LightParams` names (clear-weather slot, storm slot lerped by the storm blend) for the living, fading in by the Light sphere falloff with the modern client's crossfade (ghost > WMO > zone); extended `LightSkybox.dbc` flags `0x1` day cycle, `0x2` keep sun/moon/stars/clouds, `0x4` fog-colour horizon cone, `0x8` forces the screen-space sun shafts through a low or just-set sun (the sky's weight lifts their daylight fade; `post/sun_shafts.rs`), `0x10` fades the Modern fog's sun-colour lobe out by the sky's weight (`lighting/fog_model.rs`), plus a celestial second model; every skybox now plays its bones, texture transforms, colour and alpha tracks (`benilla-world/src/skybox.rs`, `skybox_anim.rs`, `benilla-formats/src/light/skybox.rs`) | Advanced Graphics → Zone Skyboxes, cvar `zoneSkyboxes` (0 Off default, 1 On; High = 1), env `WOW_ZONE_SKYBOXES=0\|1` | | Night and interior level | global dimming of the night sky term and of interior ambient | `nightGain`, `interiorGain`, `interiorBakeFloor` | `zoneSkyboxes = 0` disables only the added living-player zone slot. WMO and ghost skyboxes are diff --git a/crates/benilla-formats/src/lib.rs b/crates/benilla-formats/src/lib.rs index c47b7f3b..39c7d54d 100644 --- a/crates/benilla-formats/src/lib.rs +++ b/crates/benilla-formats/src/lib.rs @@ -135,7 +135,11 @@ pub use light::{Atmosphere, LightCatalog, Submersion, ZERO_KEY_COLOR, ZERO_KEY_S // MONKEY (fog): `LightFogBand.dbc`. pub use light::{FogBand, FogBandCatalog, FOG_BANDS_PER_PARAM}; // MONKEY (skybox): the skybox row and the zone walk's entries. -pub use light::{SkyboxDef, ZoneSkybox, SKYBOX_FOG_BLEND, SKYBOX_FULL_DAY, SKYBOX_KEEP_CELESTIAL}; +// MONKEY (leftovers): + the 0x8 / 0x10 flags. +pub use light::{ + SkyboxDef, ZoneSkybox, SKYBOX_FOG_BLEND, SKYBOX_FORCE_SUN_SHAFTS, SKYBOX_FULL_DAY, + SKYBOX_KEEP_CELESTIAL, SKYBOX_NO_SUN_FOG, +}; mod loading_screen; pub use loading_screen::{load_loading_screens, LoadingScreenCatalog}; mod liquid; diff --git a/crates/benilla-formats/src/light.rs b/crates/benilla-formats/src/light.rs index c9a016f5..b07c4be6 100644 --- a/crates/benilla-formats/src/light.rs +++ b/crates/benilla-formats/src/light.rs @@ -19,7 +19,11 @@ mod tables; pub use atmosphere::Atmosphere; pub use fog_band::{FogBand, FogBandCatalog, FOG_BANDS_PER_PARAM}; -pub use skybox::{SkyboxDef, ZoneSkybox, SKYBOX_FOG_BLEND, SKYBOX_FULL_DAY, SKYBOX_KEEP_CELESTIAL}; +// MONKEY (leftovers): + the 0x8 / 0x10 flags. +pub use skybox::{ + SkyboxDef, ZoneSkybox, SKYBOX_FOG_BLEND, SKYBOX_FORCE_SUN_SHAFTS, SKYBOX_FULL_DAY, + SKYBOX_KEEP_CELESTIAL, SKYBOX_NO_SUN_FOG, +}; use atmosphere::{ FB_CLOUD_DENSITY, FB_FOG_END, FB_FOG_START_MULT, IB_AMBIENT, IB_CLOUD_GBASE, IB_CLOUD_SLOPE, IB_CLOUD_SUN, IB_DIFFUSE, IB_FOG_COLOR, IB_OCEAN_DEEP, IB_OCEAN_SHALLOW, IB_RIVER_DEEP, diff --git a/crates/benilla-formats/src/light/skybox.rs b/crates/benilla-formats/src/light/skybox.rs index ab6c319a..cca12efd 100644 --- a/crates/benilla-formats/src/light/skybox.rs +++ b/crates/benilla-formats/src/light/skybox.rs @@ -26,6 +26,10 @@ pub const SKYBOX_FULL_DAY: u32 = 0x1; pub const SKYBOX_KEEP_CELESTIAL: u32 = 0x2; /// Flag `0x4`: an alpha cone in the final fog colour draws over the model's horizon. pub const SKYBOX_FOG_BLEND: u32 = 0x4; +/// MONKEY (leftovers): flag `0x8`: sun shafts run under this sky even where they would fade. +pub const SKYBOX_FORCE_SUN_SHAFTS: u32 = 0x8; +/// MONKEY (leftovers): flag `0x10`: the fog's sun-colour lobe is off under this sky. +pub const SKYBOX_NO_SUN_FOG: u32 = 0x10; /// One `LightSkybox.dbc` row. #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/crates/benilla-world/src/lighting/fog_model.rs b/crates/benilla-world/src/lighting/fog_model.rs index 22a0d21b..4ff8249d 100644 --- a/crates/benilla-world/src/lighting/fog_model.rs +++ b/crates/benilla-world/src/lighting/fog_model.rs @@ -204,6 +204,8 @@ pub(super) fn update_fog_model( eye_liquid: crate::liquid::EyeLiquid, viewer: Res, weather: Option>, + // MONKEY (leftovers): LightSkybox flag 0x10 (last frame's backdrop; the skybox resolves later). + sky: Option>, mut frame: ResMut, ) { let derived = derived_band(&lighting); @@ -233,6 +235,9 @@ pub(super) fn update_fog_model( }; let mut next = *frame; fill_frame(&mut next, setting.0, &lighting, &band); + // MONKEY (leftovers): a `0x10` skybox fades the sun-fog lobe out by its weight. + let no_sun = sky.map_or(0.0, |s| s.flag_weight(benilla_formats::SKYBOX_NO_SUN_FOG)); + next.sun_fog_strength *= 1.0 - no_sun.clamp(0.0, 1.0); if *frame != next { *frame = next; } diff --git a/crates/benilla-world/src/skybox.rs b/crates/benilla-world/src/skybox.rs index 9df4635a..3029dc01 100644 --- a/crates/benilla-world/src/skybox.rs +++ b/crates/benilla-world/src/skybox.rs @@ -92,6 +92,15 @@ impl CameraSkybox { }) } + /// MONKEY (leftovers): the heaviest main layer's weight among those carrying `flag`, 0 if none. + pub fn flag_weight(&self, flag: u32) -> f32 { + self.0 + .iter() + .filter(|l| !l.celestial && l.flags & flag != 0) + .map(|l| l.weight) + .fold(0.0, f32::max) + } + fn layer(&self, path: &str) -> Option<&SkyboxLayer> { self.0.iter().find(|l| l.path == path) } @@ -1084,4 +1093,23 @@ mod tests { }); assert_eq!(sky.primary().map(|l| l.path.as_str()), Some("b")); } + + /// MONKEY (leftovers): a flag's weight is its heaviest main carrier; celestial layers and + /// layers without the flag do not count. + #[test] + fn flag_weight_is_the_heaviest_main_carrier() { + let with = |path, w, flags| SkyboxLayer { + flags, + ..layer(path, w) + }; + let mut sky = CameraSkybox(vec![with("a", 0.3, 0x8), with("b", 0.7, 0x1), with("c", 0.5, 0x18)]); + sky.0.push(SkyboxLayer { + celestial: true, + ..with("d", 1.0, 0x18) + }); + assert_eq!(sky.flag_weight(benilla_formats::SKYBOX_FORCE_SUN_SHAFTS), 0.5); + assert_eq!(sky.flag_weight(benilla_formats::SKYBOX_NO_SUN_FOG), 0.5); + assert_eq!(sky.flag_weight(benilla_formats::SKYBOX_FOG_BLEND), 0.0); + assert_eq!(CameraSkybox::default().flag_weight(0x8), 0.0); + } }