bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Screenshots from any render target not just windows

Open torsteingrindvik opened this issue 1 year ago • 1 comments

What problem does this solve or what need does it fill?

Example use cases:

  1. If rendering to a non-window target we should be able to take screenshots of what's rendered.
  2. In cases such as 4-player split screen we should be able to take individual screenshots of each split (likely covered by 1. if the split screen is implemented via first off-screen rendering then composited into a window)

What solution would you like?

Allow taking screenshots of any render target: http://dev-docs.bevyengine.org/bevy/render/camera/enum.RenderTarget.html

What alternative(s) have you considered?

  1. Spawning a dedicated window showing my offscreen rendered texture then taking a screenshot of that
  2. Doing a manual texture-to-buffer copy then converting this to an image

Additional context

Just initial thoughts on how it might work

From a quick look it seems that currently extracted windows have a special field: https://github.com/bevyengine/bevy/blob/main/crates/bevy_render/src/view/window/mod.rs#L73

pub screenshot_memory: Option<ScreenshotPreparedState>

it seems to me that this shouldn't be necessary- perhaps a solution where something like

#[derive(..., Component)]
struct ScreenshotTarget {
  buf: Buffer
  ...
}

could be considered, and cameras (and windows?) with this component can have their screenshots taken.

This would also allow things like

// Screenshot with same width, height as camera target
commands.spawn((Camera3dBundle { ... }, ScreenshotTarget::default());

// Screenshot by sampling the camera no matter its size, then output to a FullHD sized image
commands.spawn((Camera3dBundle { ... }, ScreenshotTarget::with_size(1920, 1080));

// In both cases it doesn't matter if the cameras are 3D, 2D, if they render to separate windows, the same window, or not a window at all

There might be a loss of ergonomics if a user wants to take a screenshot of a window since they would have to add the ScreenshotTarget to the window entity (or entities), but an alternative could be to have windows spawn with this by default and rather have it opt-out.

torsteingrindvik avatar Mar 14 '24 14:03 torsteingrindvik

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 :)

alice-i-cecile avatar May 05 '24 19:05 alice-i-cecile