Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to capture 1 frame? #2

Closed
Youdiie opened this issue Aug 2, 2023 · 7 comments
Closed

How to capture 1 frame? #2

Youdiie opened this issue Aug 2, 2023 · 7 comments

Comments

@Youdiie
Copy link

Youdiie commented Aug 2, 2023

Hello, I want to render just one particular frame using bevy_image_export.
However, in this issue(#1) there is only a way to start and stop capturing.
Any hint is welcome!

@paulkre
Copy link
Owner

paulkre commented Aug 2, 2023

Hi, if you just want to export a single frame you might be better of using Bevy’s internal ScreenshotManager. Otherwise you would have to spawn an ImageExportBundle and then immediately despawn it in the subsequent frame.

@Youdiie
Copy link
Author

Youdiie commented Aug 2, 2023

Thanks for replying!
I used Bevy's ScreenshotManager, but I couldn't resize the result :(
Also I wrote the code to an ImageExportBundle and then immediately despawn it in the subsequent frame, but save_buffer_to_disk() didn't stop. Is there any way?

@paulkre
Copy link
Owner

paulkre commented Aug 2, 2023

So you’re saying, ImageExportBundle kept on exporting frames, even after you despawned the entity? Could you please send me the code of the systems you used?

@Youdiie
Copy link
Author

Youdiie commented Aug 2, 2023

Oh, I'm sorry. I made a mistake.
After I despawned, it crashed like this:

thread 'Compute Task Pool (1)' panicked at 'called `Result::unwrap()` on an `Err` value: NoEntities("bevy_ecs::query::state::QueryState<bevy_ecs::entity::Entity, bevy_ecs::query::filter::With<...::render::ExportBundleMarker>>")'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `...::render::save_image`!
thread '<unnamed>' panicked at 'The TimeSender channel should always be empty during render. You might need to add the bevy::core::time_system to your app.: "Disconnected(..)"', ./.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_render-0.11.0/src/renderer/mod.rs:91:44
Encountered a panic in exclusive system `bevy_render::renderer::render_system`!

My code is here:

#[derive(Component)]
pub struct ExportBundleMarker;

pub fn save_image(
    mut commands: Commands,
    mut export_sources: ResMut<Assets<ImageExportSource>>,
    output_texture: ResMut<TextureHandle>,
    input: Res<Input<KeyCode>>,
    export_bundles: Query<Entity, With<ExportBundleMarker>>,
) {
    if input.just_pressed(KeyCode::Space) {
        commands.spawn((ImageExportBundle {
            source: export_sources.add(output_texture.texture.clone().into()),
            settings: ImageExportSettings {
                extension: "exr".into(),
                ..default()
            },
        },));

        // after render
        commands.entity(export_bundles.single()).despawn();
    }
}

So I tried to use resource to change state after spawn, but save_buffer_to_disk() is on sub_app so it can't use world resource 🥲

@paulkre
Copy link
Owner

paulkre commented Aug 2, 2023

The issue is that you are attempting to despawn the entity on the same frame you are spawning it on. You have to wait one iteration for Bevy to add the entity to the Query object (export_bundles). To address this, I made modifications to your code. Now, all entities with the ExportBundleMarker will be despawned on every frame. Consequently, the ImageExportBundle will exist for exactly one frame:

#[derive(Component)]
pub struct ExportBundleMarker;

pub fn save_image(
    mut commands: Commands,
    mut export_sources: ResMut<Assets<ImageExportSource>>,
    output_texture: ResMut<TextureHandle>,
    input: Res<Input<KeyCode>>,
    export_bundles: Query<Entity, With<ExportBundleMarker>>,
) {
    if input.just_pressed(KeyCode::Space) {
        commands.spawn((
            ImageExportBundle {
                source: export_sources.add(output_texture.texture.clone().into()),
                settings: ImageExportSettings {
                    extension: "exr".into(),
                    ..default()
                },
            },
            ExportBundleMarker,
        ));
    }

    for bundle in &export_bundles {
        commands.entity(bundle).despawn();
    }
}

You are currently exporting an HDR image (EXR), so please make sure to use TextureFormat::Rgba32Float as the format in your output texture’s image properties.

@paulkre
Copy link
Owner

paulkre commented Aug 2, 2023

On top of that, you forgot to add the ExportBundleMarker to the entity holding the ImageExportBundle.

@Youdiie
Copy link
Author

Youdiie commented Aug 3, 2023

Wow it works! Thank you for your kind explanation :)
And yes, I forgot to add ExportBundleMarker 😂

@Youdiie Youdiie closed this as completed Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants