mod common;
use bevy::diagnostic::{DiagnosticPath, DiagnosticsStore};
use bevy::prelude::*;
use bevy::render::diagnostic::RenderDiagnosticsPlugin;
use bevy::window::{PresentMode, WindowResolution};
use bevy_elements::*;
use common::{ExampleHarness, camera, test_scene};
const PASSES: [&str; 2] = ["elements_wind", "elements_fog"];
fn main() {
let (width, height) = std::env::var("ELEMENTS_RESOLUTION")
.ok()
.and_then(|r| {
let (w, h) = r.split_once('x')?;
Some((w.parse().ok()?, h.parse().ok()?))
})
.unwrap_or((1920, 1080));
let quality = match std::env::var("ELEMENTS_QUALITY").as_deref() {
Ok("low") => ElementsQuality::Low,
Ok("medium") => ElementsQuality::Medium,
Ok("ultra") => ElementsQuality::Ultra,
_ => ElementsQuality::High,
};
App::new()
.add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::new(width, height),
present_mode: PresentMode::AutoNoVsync,
..default()
}),
..default()
}),
RenderDiagnosticsPlugin,
ElementsPlugins,
ExampleHarness,
))
.insert_resource(quality)
.insert_resource(
WorldClock::new(CivilDate::new(2026, 6, 21))
.at_hour(16.0)
.with_time_scale(60.0),
)
.add_systems(Startup, setup)
.add_systems(Update, report)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut director: ResMut<WeatherDirector>,
) {
commands.spawn(camera(
Vec3::new(0.0, 12.0, 0.0),
Vec3::new(150.0, 10.0, 80.0),
));
test_scene(&mut commands, &mut meshes, &mut materials);
director.force(WeatherPreset::Fog, std::time::Duration::ZERO);
}
fn report(store: Res<DiagnosticsStore>, quality: Res<ElementsQuality>, mut frame: Local<u32>) {
*frame += 1;
if !(*frame).is_multiple_of(120) {
return;
}
let mut total = 0.0;
let mut line = format!("{:?}:", *quality);
for pass in PASSES {
let gpu = DiagnosticPath::new(format!("render/{pass}/elapsed_gpu"));
let cpu = DiagnosticPath::new(format!("render/{pass}/elapsed_cpu"));
match store.get(&gpu) {
Some(d) => {
let min = d.values().copied().fold(f64::INFINITY, f64::min);
let mean = d.average().unwrap_or(f64::NAN);
total += min;
line += &format!(" {pass} min {min:.3} / mean {mean:.3} ms GPU");
}
None => match store.get(&cpu).and_then(|d| d.smoothed()) {
Some(ms) => line += &format!(" {pass} {ms:.3} ms CPU (no GPU timestamps)"),
None => line += &format!(" {pass} -"),
},
}
}
println!("{line} | total min {total:.3} ms GPU");
}