Fix headless_renderer example and mention Screenshot. (#19598)

## Objective

- Makes `headless_renderer` example work instead of exiting without
effect.
- Guides users who actually just need
[`Screenshot`](https://docs.rs/bevy/0.16.1/bevy/render/view/window/screenshot/struct.Screenshot.html)
to use that instead.

This PR was inspired by my own efforts to do headless rendering, in
which the complexity of the `headless_renderer` example was a
distraction, and this comment from
https://github.com/bevyengine/bevy/issues/12478#issuecomment-2094925039
:

> The example added in https://github.com/bevyengine/bevy/pull/13006
would benefit from this change: be sure to clean it up when tackling
this work :)

That “cleanup” was not done, and I thought to do it, but it seems to me
that using `Screenshot` (in its current form) in the example would not
be correct, because — if I understand correctly — the example is trying
to, potentially, capture many *consecutive* frames, whereas `Screenshot`
by itself gives no means to capture multiple frames without gaps or
duplicates. But perhaps I am wrong (the code is complex and not clearly
documented), or perhaps that feature isn’t worth preserving. In that
case, let me know and I will revise this PR.

## Solution

- Added `exit_condition: bevy:🪟:ExitCondition::DontExit`
- Added a link to `Screenshot` in the crate documentation.

## Testing

- Ran the example and confirmed that it now writes an image file and
then exits.
This commit is contained in:
Kevin Reid 2025-06-12 13:06:08 -07:00 committed by GitHub
parent 8010185275
commit 1dfe83bb8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,11 +1,16 @@
//! This example illustrates how to make headless renderer
//! derived from: <https://sotrh.github.io/learn-wgpu/showcase/windowless/#a-triangle-without-a-window>
//! It follows this steps:
//! This example illustrates how to make a headless renderer.
//! Derived from: <https://sotrh.github.io/learn-wgpu/showcase/windowless/#a-triangle-without-a-window>
//! It follows these steps:
//!
//! 1. Render from camera to gpu-image render target
//! 2. Copy from gpu image to buffer using `ImageCopyDriver` node in `RenderGraph`
//! 3. Copy from buffer to channel using `receive_image_from_buffer` after `RenderSystems::Render`
//! 4. Save from channel to random named file using `scene::update` at `PostUpdate` in `MainWorld`
//! 5. Exit if `single_image` setting is set
//!
//! If your goal is to capture a single “screenshot” as opposed to every single rendered frame
//! without gaps, it is simpler to use [`bevy::render::view::window::screenshot::Screenshot`]
//! than this approach.
use bevy::{
app::{AppExit, ScheduleRunnerPlugin},
@ -86,6 +91,9 @@ fn main() {
// replaces the bevy_winit app runner and so a window is never created.
.set(WindowPlugin {
primary_window: None,
// Dont automatically exit due to having no windows.
// Instead, the code in `update()` will explicitly produce an `AppExit` event.
exit_condition: bevy::window::ExitCondition::DontExit,
..default()
})
// WinitPlugin will panic in environments without a display server.