bevy_cube_marcher 0.5.0

A shader-based marching cubes implementation for Bevy
Documentation
use std::time::Instant;

use bevy::color::palettes::{css, tailwind};
use bevy::pbr::wireframe::{WireframeConfig, WireframePlugin};
use bevy::prelude::*;
use bevy::shader::ShaderRef;
use bevy::winit::WinitPlugin;
use bevy_cube_marcher::gpu::*;
use bevy_cube_marcher::*;

#[test]
fn main() {
    let start = Instant::now();
    App::new()
        .add_plugins((
            DefaultPlugins.set(WinitPlugin {
                run_on_any_thread: true,
            }),
            WireframePlugin::default(),
            bevy_panorbit_camera::PanOrbitCameraPlugin,
            GpuMarchingCubesPlugin::<MyComputeSampler, (), StandardMaterial>::default(),
        ))
        .insert_resource(WireframeConfig {
            global: true,
            default_color: css::WHITE.into(),
            ..default()
        })
        .insert_resource(ChunkGeneratorSettings::<MyComputeSampler>::new(32, 8.0))
        .init_resource::<ChunkCounter>()
        .add_systems(Startup, setup)
        .add_observer(count_chunks)
        .run();
    let end = Instant::now();
    let time = (end - start).as_nanos();
    let time_str = time
        .to_string()
        .chars()
        .rev()
        .collect::<Vec<_>>()
        .chunks(3)
        .map(|c| c.iter().collect::<String>())
        .collect::<Vec<_>>()
        .join(",")
        .chars()
        .rev()
        .collect::<String>();
    info!("Generation time (GPU): {time_str} nanoseconds");
    // Generation time (GPU): 30,917,620,255 nanoseconds
}

#[derive(TypePath)]
struct MyComputeSampler;

impl GpuChunkComputer for MyComputeSampler {
    fn shader() -> ShaderRef {
        "sample.wgsl".into()
    }
}

fn setup(mut commands: Commands, mut materials: ResMut<Assets<StandardMaterial>>) {
    commands.spawn((
        Name::new("Camera"),
        Camera3d::default(),
        Transform::from_xyz(4.0, 6.5, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
        bevy_panorbit_camera::PanOrbitCamera {
            button_orbit: MouseButton::Left,
            button_pan: MouseButton::Left,
            modifier_pan: Some(KeyCode::ShiftLeft),
            reversed_zoom: true,
            ..default()
        },
    ));

    commands.spawn((
        Name::new("Light"),
        DirectionalLight {
            illuminance: 4000.0,
            ..default()
        },
        Transform {
            rotation: Quat::from_euler(EulerRot::XYZ, -1.9, 0.8, 0.0),
            ..default()
        },
    ));

    commands.spawn(ChunkLoader::<MyComputeSampler>::new(5));

    commands.insert_resource(ChunkMaterial::<MyComputeSampler, StandardMaterial>::new(
        materials.add(Color::from(tailwind::EMERALD_500)),
    ));
}

fn count_chunks(
    _generated: On<ChunkGenerated>,
    mut counter: ResMut<ChunkCounter>,
    mut exit: MessageWriter<AppExit>,
) {
    counter.0 += 1;
    if counter.0 == 1331 {
        exit.write(AppExit::Success);
    }
}

#[derive(Resource, Default)]
struct ChunkCounter(u32);