Files
benilla-octo/crates/benilla-world/src/shaders.rs
T
SamandClaude Fable 5 4510607e91 the static world gets a retained draw pass, dark behind a flag
- behind WOW_STATIC_GX=1, never-fade doodads leave the per-entity renderer for one cross-material draw per 133-yard cell, pixel-identical to the entity path at the 1/255 floor
- WMO group geometry joins the pass with the portal flood as CPU range selection — in Lower Blackrock Spire the entity lane's WMO draws drop 33 → 0, no leak
- the fading doodads ride it too: a doodad inside its feather band is punched out of the retained draw and respawned as an ordinary entity, so the fade is the current look by construction
- correctness banked, performance not yet: the first legs read +2.36 ms at the Stormwind gates and +7.27 parked at Goldshire — per-cell texture arrays rebuilt on every re-bake are the priced cost, WOW_GX_PERF=1 meters the lane

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 18:56:36 +07:00

86 lines
4.6 KiB
Rust

//! **The engine's WGSL, compiled into the binary** (decision 1175).
//!
//! The seven shaders under `src/shaders/` are the *engine's* — 1171's line, unchanged: the game's
//! five live in `benilla-app`, and `embedded_asset!` is per-crate by construction, so the seam
//! costs nothing to keep.
//!
//! Until 1175 these were served from a file asset root that `boot.rs` baked as
//! `concat!(env!("CARGO_MANIFEST_DIR"), "/assets")` — an absolute path into the *build* machine's
//! source tree. On any other machine it resolves to nothing and the world renders with no shaders
//! at all: the "silently-no-shaders trap" `capture/mod.rs`'s header already named. Embedding is
//! what makes the binary answer for its own content; `benilla-assets` has done it for its four
//! since it had them, and this is the same move for the other twelve.
//!
//! **Why these calls live in a file directly under `src/`.** `embedded_asset!` derives the served
//! path by stripping everything up to and including the crate's `src/` from `file!()`, then
//! re-prefixing the crate name — and it does **not** normalize the result. Called from
//! `src/sun/materials.rs` the shader would land at `embedded://benilla_world/sun/…`, and reaching
//! back out with `"../shaders/x.wgsl"` would bake a literal `..` component into the virtual
//! directory. One registration point at the root of `src/` is what keeps every path
//! `embedded://benilla_world/shaders/<name>.wgsl`.
use bevy::prelude::*;
/// Compile the engine's seven WGSL files in and register them under
/// `embedded://benilla_world/shaders/…`.
///
/// Added as the first member of [`crate::world_plugins::WorldPlugins`] rather than exposed as a
/// free function a composition root must remember to call: a shader that fails to register is
/// invisible until something tries to draw with it, which is the exact failure mode this record
/// closes. `Plugin::build` runs at `add_plugins` time, and both binaries add `DefaultPlugins`
/// (which creates the registry these calls fill) before `WorldPlugins`.
pub(crate) fn plugin(app: &mut App) {
bevy::asset::embedded_asset!(app, "shaders/sky.wgsl");
bevy::asset::embedded_asset!(app, "shaders/star.wgsl");
bevy::asset::embedded_asset!(app, "shaders/cloud.wgsl");
bevy::asset::embedded_asset!(app, "shaders/celestial.wgsl");
bevy::asset::embedded_asset!(app, "shaders/ffx_glow.wgsl");
bevy::asset::embedded_asset!(app, "shaders/wow_effect.wgsl");
bevy::asset::embedded_asset!(app, "shaders/static_gx.wgsl");
}
#[cfg(test)]
mod tests {
use bevy::asset::io::AssetSourceId;
use bevy::prelude::*;
/// Every `.wgsl` under `src/shaders/` answers at `embedded://benilla_world/shaders/<name>`.
///
/// `embedded_asset!` derives that path from `file!()` and does **not** normalize it, so it is
/// not something to reason about — this reads the bytes back through the same source a
/// material's `ShaderRef` goes through. Driving the loop off the *directory listing* is the
/// other half: a shader added without a registration line, or registered from a submodule
/// (which silently prefixes that module's directory), fails here instead of drawing nothing.
#[test]
fn every_engine_shader_answers_at_its_embedded_path() {
let mut app = App::new();
app.add_plugins(bevy::asset::AssetPlugin::default());
app.add_plugins(super::plugin);
let server = app.world().resource::<AssetServer>();
let source = server.get_source(AssetSourceId::from("embedded")).unwrap();
let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/src/shaders");
let mut found = 0;
for entry in std::fs::read_dir(dir).unwrap() {
let name = entry.unwrap().file_name().to_string_lossy().into_owned();
if !name.ends_with(".wgsl") {
continue;
}
found += 1;
let path = format!("benilla_world/shaders/{name}");
let read = bevy::tasks::block_on(async {
source.reader().read(std::path::Path::new(&path)).await
});
assert!(
read.is_ok(),
"embedded://{path} does not resolve — {name} is on disk but not registered in \
`shaders::plugin`, or was registered from a file that is not directly under src/"
);
}
// 6 since decision 1264 retired `wmo_skybox.wgsl` (a WMO skybox draws on the shared
// model lane, whose forced-far-depth branch lives in `benilla_assets`'
// `wow_model.wgsl`); 7 since 1429 added `static_gx.wgsl` (the B1 retained pass).
assert_eq!(found, 7, "the engine's shader set changed size");
}
}