#Delayed mesh rendering

14 messages · Page 1 of 1 (latest)

frigid bridge
#

I am confused; I been making a little app and using Bevy out of laziness and for fun (not to mention I just enjoy coding the ECS for layout). it simply loads a mesh from file, waits for it to load then when fully loaded it takes a screenshot (camera to image rendering as no window) and even though all assets are loaded and even if I purposely wait several extra frames it only renders the mesh at an arbitrary time after and I cannot figure out what I am doing wrong?

#
#[derive(Component)]
struct CameraImage(Handle<Image>);

#[derive(Event, Clone, Debug)]
struct TakeScreenshot;

#[derive(Resource)]
struct WaitingForAsset(Vec<UntypedHandle>, u32);

#[derive(Component)]
struct TargetedMesh;

fn waits_for_loaded(
    mut commands: Commands,
    assets: Res<AssetServer>,
    mut awaiting_asset: ResMut<WaitingForAsset>,
    cameras: Query<&mut Transform, With<Camera>>,
    focused: Query<&Aabb, With<TargetedMesh>>,
    mut rot: Local<f32>,
) {
    if awaiting_asset
        .0
        .iter()
        .all(|asset| assets.is_loaded_with_dependencies(asset))
    {
        if let Ok(aabb) = focused.single() {
            let center: Vec3 = aabb.center.into();
            let mut camera_transform: Vec3 = aabb.center.into();
            let size = aabb.half_extents * 2.0;
            let max_dimension = size.x.max(size.y).max(size.z);
            let distance = max_dimension * 1.5;
            camera_transform.z = distance;
            let mut camera_transform =
                Transform::from_translation(camera_transform).looking_at(center, Vec3::Y);
            camera_transform.rotate_around(
                center,
                Quat::from_euler(EulerRot::XYZ, 0.0, *rot * 45.0, 0.0),
            );
            *rot += 1.0;
            for mut camera in cameras {
                *camera = camera_transform
            }
            commands.send_event(TakeScreenshot);
            commands.remove_resource::<WaitingForAsset>();
        }
    } else { println!("waiting..."); }
}

fn take_screenshot(
    mut commands: Commands,
    mut screenshot: EventReader<TakeScreenshot>,
    cameraimage: Single<&CameraImage>,
    mut image_num: Local<usize>,
) {
    for _ in screenshot.read() {
        *image_num += 1;
        let path = format!("screenshot-{}.webp", *image_num);
        commands
            .spawn(Screenshot::image(cameraimage.0.clone()))
            .observe(save_to_disk(path).pipe(close_app));
    }
}
#

pub fn save_to_disk(path: impl AsRef<Path>) -> impl FnMut(Trigger<ScreenshotCaptured>) {
    let path = path.as_ref().to_owned();
    move |trigger| {
        let img = trigger.event().0.clone();
        match img.try_into_dynamic() {
            Ok(dyn_img) => match image::ImageFormat::from_path(&path) {
                Ok(format) => {
                    let img = dyn_img.to_rgba8();
                    #[cfg(not(target_arch = "wasm32"))]
                    match img.save_with_format(&path, format) {
                        Ok(_) => info!("Screenshot saved to {}", path.display()),
                        Err(e) => error!("Cannot save screenshot, IO error: {e}"),
                    }

                    #[cfg(target_arch = "wasm32")]
                    {
                        let save_screenshot = || {
                            use image::EncodableLayout;
                            use wasm_bindgen::{JsCast, JsValue};

                            let mut image_buffer = std::io::Cursor::new(Vec::new());
                            img.write_to(&mut image_buffer, format)
                                .map_err(|e| JsValue::from_str(&format!("{e}")))?;
                            // SAFETY: `image_buffer` only exist in this closure, and is not used after this line
                            let parts = js_sys::Array::of1(&unsafe {
                                js_sys::Uint8Array::view(image_buffer.into_inner().as_bytes())
                                    .into()
                            });
                            let blob = web_sys::Blob::new_with_u8_array_sequence(&parts)?;
                            let url = web_sys::Url::create_object_url_with_blob(&blob)?;
                            let window = web_sys::window().unwrap();
                            let document = window.document().unwrap();
                            let link = document.create_element("a")?;
                            link.set_attribute("href", &url)?;
                            link.set_attribute(
                                "download",
                                path.file_name()
                                    .and_then(|filename| filename.to_str())
                                    .ok_or_else(|| JsValue::from_str("Invalid filename"))?,
                            )?;
                            let html_element = link.dyn_into::<web_sys::HtmlElement>()?;
                            html_element.click();
                            web_sys::Url::revoke_object_url(&url)?;
                            Ok::<(), JsValue>(())
                        };

                        match (save_screenshot)() {
                            Ok(_) => info!("Screenshot saved to {}", path.display()),
                            Err(e) => error!("Cannot save screenshot, error: {e:?}"),
                        };
                    }
                }
                Err(e) => error!("Cannot save screenshot, requested format not recognized: {e}"),
            },
            Err(e) => error!("Cannot save screenshot, screen format cannot be understood: {e}"),
        }
    }
}

fn close_app(mut commands: Commands) {
    commands.send_event(AppExit::Success);
}
``` is the functions for reference; I been on this for hours and no idea why the delay exists? I tried multiple things such as changing schedule order, checking all my loading code, etc, etc but alas nothing works other than purposely waiting a whole second~ (the save_to_disk function is copied from bevy as I need the alpha channel)
random quail
#

Shaders take some time to compile

frigid bridge
#

is there a way to wait for them? and be aware when done?

random quail
frigid bridge
#

you're a star <3

#

fixed instantly, thanks alot, I couldn't find anything about it anywhere but I am prob blind mb <3

random quail
#

Nw, it's obscure atm

rose violet
bitter glen
#

Because this seems simpler:

fn update_pipelines_ready(mut main_world: ResMut<MainWorld>, pipelines: Res<PipelineCache>) {
  if let Some(mut pipelines_ready) = main_world.get_resource_mut::<PipelinesReady>() {
    pipelines_ready.0 = pipelines.waiting_pipelines().count() == 0;
  }
}
random quail
languid ferry