bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.36k stars 3.59k forks source link

Bevy struggles to render multiple simple objects at one #1643

Closed BrunoWallner closed 3 years ago

BrunoWallner commented 3 years ago

I am currently developing some sort of 3D voxel game, but I am struggling to maintain a stable performance.

At first I rendered 1600 cubes (19200 triangles) with 40 fps. Then I tried to optimize it by only drawing 1600 planes (3200 triangles), but with little to no performance improvement.

I came to the conclusion that it should be the engines fault and I dont know how to improve this situation.

I think that bevy should be capable of drawing multiple simple objects, without bottlenecking.

Here is the code I use to spawn those cubes:

fn spawn_chunk(
    commands: &mut Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    asset_server: Res<AssetServer>,
    seed: Res<Seed>,
) {
    let noise = OpenSimplex::new();
    let chunk_size = 8;

    for chunk_x in -2 .. 2 { 
    for chunk_z in -2 .. 2 {

        commands
            .spawn(PbrBundle {
                mesh: meshes.add(Mesh::from(shape::Plane{ size: 1.0 })),
                material: materials.add(Color::rgb(0.5, 0.5, 1.0).into()),
                transform: Transform::from_translation(Vec3::new((chunk_x * chunk_size) as f32, 0.0, (chunk_z * chunk_size) as f32)),
                ..Default::default()
            })
            .with(Chunk { x: chunk_x, z: chunk_z })
            .with_children(|parent| {

            let texture_handle = asset_server.load("textures/dirt.png");

            for x in -chunk_size .. chunk_size {
            for z in -chunk_size .. chunk_size {
                let y = (noise.get([
                    ( (x + chunk_x * chunk_size) as f32 / 20. ) as f64, 
                    ( (z + chunk_z * chunk_size) as f32 / 20. ) as f64,
                    seed.value,
                ]) * 15. + 16.0) as u32;

                parent
                    .spawn(PbrBundle {
                        mesh: meshes.add(Mesh::from(shape::Cube{ size: 1.0 })),
                        material: materials.add(StandardMaterial { albedo: Color::rgba(1.0, 1.0, 1.0, 1.0), albedo_texture: Some(texture_handle.clone()), ..Default::default() }),
                        transform: Transform::from_translation(Vec3::new(x as f32, y as f32, z as f32)),
                        ..Default::default()
                    })
                .with(Cube);
            }
            }
        });
    }}
}
alice-i-cecile commented 3 years ago

This is in fact the engine's fault: we don't have appropriate batching yet. This is at the very top of the priority list once 0.5 is released however.