Merge gfx/p0 into integration

# Conflicts:
#	crates/benilla-app/src/capture/scenarios.rs
#	crates/benilla-assets/src/shaders/enhanced_water.wgsl
This commit is contained in:
pkuzic
2026-09-25 11:40:30 +01:00
6 changed files with 113 additions and 32 deletions
+7 -7
View File
@@ -67,13 +67,13 @@ is its own module, documented in `WATER.md`.
| row | x | y | z | w |
|---|---|---|---|---|
| `fog0` | height_fog_density | height_fog_height | height_fog_falloff | curve_blend |
| `fog1` | sun_fog r | g | b | sun_fog_strength |
| `fog2` | end_fog r | g | b | end_fog_distance |
| `fog3` | fog_model (0 classic, 1 modern) | sun_fog_angle | 0 | 0 |
| `wind0` | dir_x | dir_y | speed | gust |
| `wind1` | time_s | sway_strength | grass_strength | tree_strength |
| `wet0` | rain_rate | wetness | ripple_time_s | snow |
| `fog_a` | height_fog_density | height_fog_height | height_fog_falloff | curve_blend |
| `fog_b` | sun_fog r | g | b | sun_fog_strength |
| `fog_c` | end_fog r | g | b | end_fog_distance |
| `fog_d` | fog_model (0 classic, 1 modern) | sun_fog_angle | 0 | 0 |
| `wind_a` | dir_x | dir_y | speed | gust |
| `wind_b` | time_s | sway_strength | grass_strength | tree_strength |
| `wet_a` | rain_rate | wetness | ripple_time_s | snow |
| `misc` | bender_count | time_of_day 0..1 | night 0..1 | 0 |
| `benders[8]` | world x | world y | world z | radius |
@@ -1413,8 +1413,87 @@ pub(super) const ON_DEMAND: &[Scenario] = &[
minute: 1260,
ui: None,
},
// ---- MONKEY (p0 baseline): the graphics programme's baseline set ----
// Every lane diffs its work against captures of these (plus the water-*, volfog-* and canal
// scenes above). Raw WoW coords, map per scenario; noon = 720, dusk = 1170, night = 0.
// Elwynn from the Goldshire road toward the lake and the forest: sky, fog and trees.
Scenario {
name: "elwynn-noon", map: Some(MAP_AZEROTH),
eye: GFX_ELWYNN_EYE, look: GFX_ELWYNN_LOOK, minute: 720, ui: None,
},
Scenario {
name: "elwynn-dusk", map: Some(MAP_AZEROTH),
eye: GFX_ELWYNN_EYE, look: GFX_ELWYNN_LOOK, minute: 1170, ui: None,
},
Scenario {
name: "elwynn-night", map: Some(MAP_AZEROTH),
eye: GFX_ELWYNN_EYE, look: GFX_ELWYNN_LOOK, minute: 0, ui: None,
},
// The same Elwynn view for rain. Capture has no weather field: run it with
// `WOW_WEATHER=1,0.8` (kind 1 rain, grade 0.8; `weather::parse_env_script`).
Scenario {
name: "elwynn-rain", map: Some(MAP_AZEROTH),
eye: GFX_ELWYNN_EYE, look: GFX_ELWYNN_LOOK, minute: 720, ui: None,
},
// Westfall: a farmstead, fields and the dry palette.
Scenario {
name: "westfall-farm", map: Some(MAP_AZEROTH),
eye: [-10080.0, 1000.0, 58.0], look: [-10140.0, 1070.0, 38.0], minute: 720, ui: None,
},
// Redridge: Lake Everstill from above Lakeshire, a wider frame than `water-lake`.
Scenario {
name: "redridge-lake", map: Some(MAP_AZEROTH),
eye: [-9350.0, -2340.0, 82.0], look: [-9500.0, -2650.0, 50.0], minute: 720, ui: None,
},
// Duskwood: the road into Darkshire, the zone's short dark fog.
Scenario {
name: "duskwood-road", map: Some(MAP_AZEROTH),
eye: [-10560.0, -1000.0, 50.0], look: [-10570.0, -1200.0, 32.0], minute: 720, ui: None,
},
// Burning Steppes: the ash plain and the sky a skybox would replace.
Scenario {
name: "burning-steppes", map: Some(MAP_AZEROTH),
eye: [-7700.0, -2100.0, 200.0], look: [-7900.0, -1700.0, 150.0], minute: 720, ui: None,
},
// Blasted Lands: the Dark Portal from the north.
Scenario {
name: "blasted-lands-portal", map: Some(MAP_AZEROTH),
eye: [-11700.0, -3200.0, 20.0], look: [-11900.0, -3208.0, 0.0], minute: 720, ui: None,
},
// Mount Hyjal (Kalimdor), inside Light.dbc sphere 270.
Scenario {
name: "hyjal-mount", map: Some(MAP_KALIMDOR),
eye: GFX_HYJAL_EYE, look: GFX_HYJAL_LOOK, minute: 720, ui: None,
},
// Stormwind: the Cathedral of Light's nave (interior WMO lighting).
Scenario {
name: "stormwind-cathedral-interior", map: Some(MAP_AZEROTH),
eye: GFX_CATHEDRAL_EYE, look: GFX_CATHEDRAL_LOOK, minute: 720, ui: None,
},
// Ironforge: the Great Forge (lava, fire light, a huge interior).
Scenario {
name: "ironforge-forge", map: Some(MAP_AZEROTH),
eye: GFX_FORGE_EYE, look: GFX_FORGE_LOOK, minute: 720, ui: None,
},
];
/// MONKEY (p0 baseline): the Elwynn programme view, above the canopy east of Goldshire looking
/// south-west over the forest to the river and the hills (framed with the `vista` instrument).
pub(super) const GFX_ELWYNN_EYE: [f32; 3] = [-9400.0, -100.0, 122.0];
pub(super) const GFX_ELWYNN_LOOK: [f32; 3] = [-9477.6, -160.6, 104.6];
/// MONKEY (p0 baseline): Mount Hyjal, over Light.dbc sphere 270's centre (world yards; the
/// sphere's own z 873 is below the terrain), pitched a little up: its params-269 fog (end 278 yd,
/// orange) fills the frame today, which is the subject the skybox and fog lanes change.
pub(super) const GFX_HYJAL_EYE: [f32; 3] = [4636.0, -4461.0, 1152.0];
pub(super) const GFX_HYJAL_LOOK: [f32; 3] = [4724.2, -4416.0, 1165.9];
/// MONKEY (p0 baseline): the Cathedral of Light nave, standing over the floor.
pub(super) const GFX_CATHEDRAL_EYE: [f32; 3] = [-8530.0, 845.0, 112.0];
pub(super) const GFX_CATHEDRAL_LOOK: [f32; 3] = [-8500.0, 880.0, 110.0];
/// MONKEY (p0 baseline): Ironforge's interior by the Great Forge ring (a lit WMO interior; the
/// camera must stand over a floor face or the portal cull hides the city).
pub(super) const GFX_FORGE_EYE: [f32; 3] = [-4880.0, -1000.0, 506.0];
pub(super) const GFX_FORGE_LOOK: [f32; 3] = [-4950.4, -929.6, 497.3];
/// The owner's reported vantage for the lava-glow report: `(-7048.8, -1000.6, 242.0)` facing
/// 1.53 rad, Searing Gorge, map 0. The eye takes the standard [`VISTA_EYE_HEIGHT`]-ish lift off
/// the pin (a `.go` lands at the feet) and the look runs 60 yd down the reported facing,
@@ -54,13 +54,13 @@ struct WaterParams {
const MONKEY_ROW: u32 = 533u;
fn water_monkey() -> monkey_frame::MonkeyFrame {
var m: monkey_frame::MonkeyFrame;
m.fog0 = water_light[MONKEY_ROW + 0u];
m.fog1 = water_light[MONKEY_ROW + 1u];
m.fog2 = water_light[MONKEY_ROW + 2u];
m.fog3 = water_light[MONKEY_ROW + 3u];
m.wind0 = water_light[MONKEY_ROW + 4u];
m.wind1 = water_light[MONKEY_ROW + 5u];
m.wet0 = water_light[MONKEY_ROW + 6u];
m.fog_a = water_light[MONKEY_ROW + 0u];
m.fog_b = water_light[MONKEY_ROW + 1u];
m.fog_c = water_light[MONKEY_ROW + 2u];
m.fog_d = water_light[MONKEY_ROW + 3u];
m.wind_a = water_light[MONKEY_ROW + 4u];
m.wind_b = water_light[MONKEY_ROW + 5u];
m.wet_a = water_light[MONKEY_ROW + 6u];
m.misc = water_light[MONKEY_ROW + 7u];
for (var i = 0u; i < 8u; i++) { m.benders[i] = water_light[MONKEY_ROW + 8u + i]; }
return m;
@@ -13,7 +13,7 @@
// `mix(fog_rgb, rgb, factor)`. The expressions below are the ones the receivers carried, in the
// same order, so the classic result is bit-identical.
//
// Extension point for the FOG lane: `fog_sample` branches on `mf.fog3.x` (`MonkeyFrame.fog_model`,
// Extension point for the FOG lane: `fog_sample` branches on `mf.fog_d.x` (`MonkeyFrame.fog_model`,
// 0 classic / 1 modern). The modern arm currently returns the classic result.
#import benilla::monkey_frame::MonkeyFrame
@@ -39,9 +39,9 @@ fn fog_sample(
mf: MonkeyFrame,
) -> vec4<f32> {
let classic = vec4<f32>(fog_rgb, fog_linear(eye_z, span));
if (mf.fog3.x > 0.5) {
if (mf.fog_d.x > 0.5) {
// FOG lane: the modern model (height / sun / end-colour / curve fog) goes here, reading
// mf.fog0..fog3. Until it lands, the modern arm is the classic law.
// mf.fog_a..fog_d. Until it lands, the modern arm is the classic law.
return classic;
}
return classic;
@@ -8,14 +8,16 @@
//
// Coordinates are Bevy world space (Y up, 1 unit = 1 yd), the space of the receivers'
// `world_position`: WoW `(x, y, z)` is Bevy `(-y, z, -x)` (`benilla_assets::coords::wow_to_bevy`).
// Member names carry no trailing digit: naga_oil refuses a composable-module identifier that
// naga's namer would rewrite (`fog0` -> `fog0_`), so the rows are `fog_a..fog_d`, `wind_a/b`, `wet_a`.
struct MonkeyFrame {
fog0: vec4<f32>, // height_fog_density, height_fog_height (world Y, yd), height_fog_falloff, curve_blend
fog1: vec4<f32>, // sun_fog_rgb (gamma 0..1), sun_fog_strength
fog2: vec4<f32>, // end_fog_rgb (gamma 0..1), end_fog_distance (yd)
fog3: vec4<f32>, // fog_model (0 classic, 1 modern), sun_fog_angle (cos), 0, 0
wind0: vec4<f32>, // dir_x, dir_y (unit, world XZ: .x = world x, .y = world z), speed (yd/s), gust 0..1
wind1: vec4<f32>, // time_s, sway_strength, grass_strength, tree_strength
wet0: vec4<f32>, // rain_rate 0..1, wetness 0..1, ripple_time_s, snow 0..1
fog_a: vec4<f32>, // height_fog_density, height_fog_height (world Y, yd), height_fog_falloff, curve_blend
fog_b: vec4<f32>, // sun_fog_rgb (gamma 0..1), sun_fog_strength
fog_c: vec4<f32>, // end_fog_rgb (gamma 0..1), end_fog_distance (yd)
fog_d: vec4<f32>, // fog_model (0 classic, 1 modern), sun_fog_angle (cos), 0, 0
wind_a: vec4<f32>, // dir_x, dir_y (unit, world XZ: .x = world x, .y = world z), speed (yd/s), gust 0..1
wind_b: vec4<f32>, // time_s, sway_strength, grass_strength, tree_strength
wet_a: vec4<f32>, // rain_rate 0..1, wetness 0..1, ripple_time_s, snow 0..1
misc: vec4<f32>, // bender_count, time_of_day 0..1 (packer), night 0..1 (packer), 0
benders: array<vec4<f32>, 8>, // world xyz (Bevy space) + radius (yd); the first bender_count are live
}
@@ -14,13 +14,13 @@
//!
//! | row | xyz / x,y,z | w |
//! |---|---|---|
//! | 0 `fog0` | height_fog_density, height_fog_height, height_fog_falloff | curve_blend |
//! | 1 `fog1` | sun_fog_rgb | sun_fog_strength |
//! | 2 `fog2` | end_fog_rgb | end_fog_distance |
//! | 3 `fog3` | fog_model (0 classic, 1 modern), sun_fog_angle, 0 | 0 |
//! | 4 `wind0` | dir_x, dir_y, speed | gust |
//! | 5 `wind1` | time_s, sway_strength, grass_strength | tree_strength |
//! | 6 `wet0` | rain_rate, wetness, ripple_time_s | snow |
//! | 0 `fog_a` | height_fog_density, height_fog_height, height_fog_falloff | curve_blend |
//! | 1 `fog_b` | sun_fog_rgb | sun_fog_strength |
//! | 2 `fog_c` | end_fog_rgb | end_fog_distance |
//! | 3 `fog_d` | fog_model (0 classic, 1 modern), sun_fog_angle, 0 | 0 |
//! | 4 `wind_a` | dir_x, dir_y, speed | gust |
//! | 5 `wind_b` | time_s, sway_strength, grass_strength | tree_strength |
//! | 6 `wet_a` | rain_rate, wetness, ripple_time_s | snow |
//! | 7 `misc` | bender_count, time_of_day 0..1, night 0..1 | 0 |
//! | 8-15 `benders` | world x, y, z | radius |
//!
@@ -38,7 +38,7 @@ pub const MONKEY_FRAME_ROWS: usize = 16;
/// How many benders (grass/foliage pushers: the player and nearby units) the block carries.
pub const MAX_BENDERS: usize = 8;
/// The fog model selector, `fog3.x`.
/// The fog model selector, `fog_d.x`.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum FogModel {
/// Today's linear 1.12 fog, byte-identical.