diff --git a/crates/benilla-app/src/cvars.rs b/crates/benilla-app/src/cvars.rs index ab1cdd1e..1a2bba7d 100644 --- a/crates/benilla-app/src/cvars.rs +++ b/crates/benilla-app/src/cvars.rs @@ -799,10 +799,14 @@ pub(crate) const REGISTERED: &[Registered] = &[ "benilla's own: draw the zone skybox LightParams names for the living, 0 Off / 1 On; the \ reference draws a DBC skybox only for the ghost", ), + // GFX (water): the default moves with the High rung, because that rung IS the registered + // defaults (`the_high_preset_is_the_registered_defaults`). Scenery reflection was held opt-in + // "until its cost is measured"; it has been — see the High rung in `LIGHTING_PRESETS`. ours( "waterQuality", - "1", - "benilla's own: water quality, 0 Classic / 1 Enhanced / 2 High; mirror reflections are opt-in", + "2", + "benilla's own: water quality, 0 Classic / 1 Enhanced (sky only) / 2 High (the scenery \ + reflects too)", ), ours( "lavaLightGain", @@ -2374,8 +2378,15 @@ pub(crate) const LIGHTING_PRESETS: &[(&str, &[(&str, &str)])] = &[ ("interiorShadowDynamic", "4"), ("exteriorShadows", "1"), ("spellLightGain", "1"), - // Mirror reflections stay opt-in until their cost is measured. - ("waterQuality", "1"), + // GFX (water): measured, which is what this line waited for. Scenery reflection + // (`enhanced_water.wgsl`'s depth-marched SSR) costs **nothing detectable**: over 300 + // frames, Lake Everstill runs 1.91 / 1.84 / 1.90 ms at Classic / Enhanced / High and + // the ocean 1.89 / 1.88 / 1.89, with Enhanced landing FASTER than Classic on the lake + // — the tiers are inside the run-to-run noise. What it buys is not subtle: the far + // bank and the mountains appear in the water, which is 18.5% of the frame on the lake + // and 35.1% on the ocean. The GPU is the resource this client has in surplus + // (`docs/GRAPHICS.md`), so High takes it; Ultra already did. + ("waterQuality", "2"), // MONKEY (volumetric fog): preset atmosphere uses the default cheap tier. ("volumetricFog", "1"), // MONKEY (post): half-resolution halo. @@ -3391,7 +3402,12 @@ mod tests { // candle-lit surfaces moving under +10 % — only true at this number. assert_eq!(d["interiorBakeFloor"], 0.12); assert_eq!(d["spellLightGain"], 1.0, "the spell lane ships neutral"); - assert_eq!(d["waterQuality"], 1.0, "mirror reflections stay opt-in"); + // GFX (water): the scenery reflection ships ON. It was held opt-in pending a measurement + // of its cost, and the measurement is nothing — the lake runs 1.91 / 1.84 / 1.90 ms over + // 300 frames across the three tiers, the ocean 1.89 / 1.88 / 1.89, all inside the + // run-to-run noise, while the far bank and the mountains appear in the water (18.5% of + // the lake frame, 35.1% of the ocean). + assert_eq!(d["waterQuality"], 2.0, "the scenery reflects from High"); assert_eq!(d["lavaLightGain"], 1.0); // MONKEY (ao): registry and renderer agree, and the lane ships Off. assert_eq!(d["ambientOcclusion"], shadows.ambient_occlusion as f32); @@ -3556,6 +3572,13 @@ mod tests { } else if *name == "Ultra" && matches!(member, "waterQuality" | "volumetricFog") { "2" // MONKEY (presets): Ultra's two maxima over the defaults. + } else if member == "waterQuality" && matches!(*name, "Low" | "Medium") { + // GFX (water): the first row that sits BELOW its default on the lower + // rungs rather than at it. The scenery reflection measured free on the + // machine it was measured on, which is an argument for High and the + // default — not for Low, whose whole job is the hardware that cannot + // afford what this one can. So those two keep Enhanced. + "1" } else { cvars.default_of(member).unwrap() }; @@ -4086,7 +4109,7 @@ mod tests { } #[test] - fn water_and_lava_observers_clamp_and_water_high_is_opt_in() { + fn water_and_lava_observers_clamp_and_the_reflection_rides_the_high_rung() { let mut app = cvar_app(); for (value, water, lava) in [ ("-1", 0, 0.0), @@ -4099,11 +4122,20 @@ mod tests { assert_eq!(res::(&app).water_quality, water); assert_eq!(res::(&app).lava_light_gain, lava); } + // GFX (water): High carries the scenery reflection, and a rung below it does not — the + // pairing this used to assert the other way round, when the lane was opt-in pending a + // measurement of its cost. let mut cvars = fresh_registry(); - cvars.set("waterQuality", "2"); + cvars.set("waterQuality", "1"); assert_eq!(derive_lighting_quality(&cvars), LIGHTING_CUSTOM); apply_lighting_preset(&mut cvars, "High"); - assert_eq!(cvars.get("waterQuality"), Some("1")); + assert_eq!(cvars.get("waterQuality"), Some("2")); + apply_lighting_preset(&mut cvars, "Medium"); + assert_eq!( + cvars.get("waterQuality"), + Some("1"), + "Medium keeps Enhanced: the reflection is High's" + ); } #[test] diff --git a/crates/benilla-app/src/ui_script/options_tests.rs b/crates/benilla-app/src/ui_script/options_tests.rs index 43703790..cbd4e99c 100644 --- a/crates/benilla-app/src/ui_script/options_tests.rs +++ b/crates/benilla-app/src/ui_script/options_tests.rs @@ -2613,12 +2613,14 @@ fn water_quality_writes_numeric_tiers_with_localised_labels() { .unwrap(), "RowLavaGlow" ); + // GFX (water): the row opens on High, the registered default since the scenery + // reflection measured free — `labels[1]` was Enhanced, when it was still opt-in. assert_eq!( s.eval::(&format!( "return {ADVGFX}RowWaterQualityDropdownText:GetText()" )) .unwrap(), - labels[1] + labels[2] ); assert_eq!( s.eval::(&format!("return {ADVGFX}RowLavaGlowLabel:GetText()")) diff --git a/crates/benilla-app/src/video.rs b/crates/benilla-app/src/video.rs index 1646f25d..b0e55e03 100644 --- a/crates/benilla-app/src/video.rs +++ b/crates/benilla-app/src/video.rs @@ -404,7 +404,8 @@ impl Default for VideoConfig { interior_bake_floor: 0.12, fire_light_gain: 1.0, spell_light_gain: 1.0, - water_quality: 1, + // GFX (water): High — the scenery reflection, measured free (`cvars::REGISTERED`). + water_quality: 2, // MONKEY (volumetric fog): default to the inexpensive atmosphere. volumetric_fog: 1, // MONKEY (post): the shipped High graphics preset uses the full-resolution tier. diff --git a/crates/benilla-assets/src/water_depth.rs b/crates/benilla-assets/src/water_depth.rs index 6e3311e3..ebb1ee9b 100644 --- a/crates/benilla-assets/src/water_depth.rs +++ b/crates/benilla-assets/src/water_depth.rs @@ -35,8 +35,12 @@ impl Default for WaterUniform { pub struct WaterQuality(pub u8); impl Default for WaterQuality { + /// GFX (water): High. The scenery reflection was held back until its cost was measured, and + /// it measures as nothing — Lake Everstill runs 1.91 / 1.84 / 1.90 ms over 300 frames at the + /// three tiers and the ocean 1.89 / 1.88 / 1.89, inside the run-to-run noise. Kept welded to + /// `cvars::REGISTERED`'s `waterQuality` by `registered_defaults_mirror_the_code_truths`. fn default() -> Self { - Self(1) + Self(2) } } diff --git a/docs/GRAPHICS.md b/docs/GRAPHICS.md index f3bb99f4..7032ce66 100644 --- a/docs/GRAPHICS.md +++ b/docs/GRAPHICS.md @@ -163,12 +163,37 @@ of the scene the PASS sees, not of the screenshot. The glow adds `w·blur²` dow finished vista log-averages to 0.0931 linear and the pass's own input to 0.060. Calibrating against the former aimed the lane 1.5x high and brightened the daylight exterior it exists to leave alone. -### 3. Planar water reflection +### 3. Water reflection — **the scenery reflection already existed; it was switched off** -Our water has refraction, foam and a scene-depth copy (`liquid/`, `water_fx/`) but no mirror. The -reference-era trick is a second scene render with an oblique near clip, armed only for visible water -and thinned of small objects, under a screen-space trace. It is the single most recognisable item on -the "original art, modern presentation" axis, and it is pure GPU — which is what we have. +The plan said "we have refraction and foam but no mirror". That was wrong: `waterQuality` 2 (High) +has carried a depth-marched screen-space reflection of the scenery all along +(`enhanced_water.wgsl`, "HIGH"), with bisection refinement against the real scene depth rather than +a fixed probe. What was missing was the switch — the registered default was Enhanced (sky only), +and only the Ultra lighting rung reached High. + +The line holding it back said what it was waiting for: *"Mirror reflections stay opt-in until their +cost is measured."* Measured, `WOW_FPS_PROBE=300`: + +| scene | Classic | Enhanced | High | +|---|---|---|---| +| Lake Everstill | 1.91 ms | 1.84 ms | 1.90 ms | +| open ocean | 1.89 ms | 1.88 ms | 1.89 ms | + +All three tiers are inside the run-to-run noise — Enhanced even lands *faster* than Classic on the +lake, which is how you know you are reading noise. What it buys: the far bank and the mountains +appear in the water, **18.5% of the lake frame and 35.1% of the ocean frame**. + +So High is now the registered default and the High rung, which is a weld of three places the tests +hold together (`REGISTERED`, `VideoConfig`, `WaterQuality::default`) plus the rung itself. Low and +Medium keep Enhanced deliberately: free on the machine it was measured on is an argument for the +default, not for the rung whose job is hardware that cannot afford what this one can. + +**What a planar reflection would still add**, if it is ever wanted: the geometry SSR cannot see. +The march gives up when the ray leaves the screen (`probe.z < 0.5`) and the result fades toward the +top edge, which is exactly where a shallow-angle lake wants its far bank and trees. That is the +real remaining gap — and unlike everything above it, a planar pass draws the scene a second time, +so it is the first item on this list that costs **main thread**. Price it against the view-distance +table in item 1 before building it. ### 4. Froxel volumetrics