Stress Tests / Many Gizmos

Back to examples View in GitHub

Support Warning

WebGPU is currently only supported on Chrome starting with version 113, and only on desktop. If they don't work on your configuration, you can check the WebGL2 examples here.

//! Test rendering of many gizmos.

use std::f32::consts::TAU;

use bevy::{
    diagnostic::{Diagnostic, DiagnosticsStore, FrameTimeDiagnosticsPlugin},
    prelude::*,
    window::{PresentMode, WindowResolution},
    winit::{UpdateMode, WinitSettings},
};

const SYSTEM_COUNT: u32 = 10;

fn main() {
    let mut app = App::new();
    app.add_plugins((
        DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                title: "Many Debug Lines".to_string(),
                present_mode: PresentMode::AutoNoVsync,
                resolution: WindowResolution::new(1920.0, 1080.0).with_scale_factor_override(1.0),
                ..default()
            }),
            ..default()
        }),
        FrameTimeDiagnosticsPlugin,
    ))
    .insert_resource(WinitSettings {
        focused_mode: UpdateMode::Continuous,
        unfocused_mode: UpdateMode::Continuous,
    })
    .insert_resource(Config {
        line_count: 50_000,
        fancy: false,
    })
    .add_systems(Startup, setup)
    .add_systems(Update, (input, ui_system));

    for _ in 0..SYSTEM_COUNT {
        app.add_systems(Update, system);
    }

    app.run();
}

#[derive(Resource, Debug)]
struct Config {
    line_count: u32,
    fancy: bool,
}

fn input(mut config: ResMut<Config>, input: Res<ButtonInput<KeyCode>>) {
    if input.just_pressed(KeyCode::ArrowUp) {
        config.line_count += 10_000;
    }
    if input.just_pressed(KeyCode::ArrowDown) {
        config.line_count = config.line_count.saturating_sub(10_000);
    }
    if input.just_pressed(KeyCode::Space) {
        config.fancy = !config.fancy;
    }
}

fn system(config: Res<Config>, time: Res<Time>, mut draw: Gizmos) {
    if !config.fancy {
        for _ in 0..(config.line_count / SYSTEM_COUNT) {
            draw.line(Vec3::NEG_Y, Vec3::Y, Color::BLACK);
        }
    } else {
        for i in 0..(config.line_count / SYSTEM_COUNT) {
            let angle = i as f32 / (config.line_count / SYSTEM_COUNT) as f32 * TAU;

            let vector = Vec2::from(ops::sin_cos(angle)).extend(ops::sin(time.elapsed_secs()));
            let start_color = LinearRgba::rgb(vector.x, vector.z, 0.5);
            let end_color = LinearRgba::rgb(-vector.z, -vector.y, 0.5);

            draw.line_gradient(vector, -vector, start_color, end_color);
        }
    }
}

fn setup(mut commands: Commands) {
    warn!(include_str!("warning_string.txt"));

    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(3., 1., 5.).looking_at(Vec3::ZERO, Vec3::Y),
    ));

    commands.spawn((
        Text::default(),
        Node {
            position_type: PositionType::Absolute,
            top: Val::Px(12.0),
            left: Val::Px(12.0),
            ..default()
        },
    ));
}

fn ui_system(mut text: Single<&mut Text>, config: Res<Config>, diag: Res<DiagnosticsStore>) {
    let Some(fps) = diag
        .get(&FrameTimeDiagnosticsPlugin::FPS)
        .and_then(Diagnostic::smoothed)
    else {
        return;
    };

    text.0 = format!(
        "Line count: {}\n\
        FPS: {:.0}\n\n\
        Controls:\n\
        Up/Down: Raise or lower the line count.\n\
        Spacebar: Toggle fancy mode.",
        config.line_count, fps,
    );
}