This commit is contained in:
tigregalis 2025-07-18 12:37:46 -04:00 committed by GitHub
commit bf5f1f5a3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 52 deletions

View File

@ -843,6 +843,58 @@ impl Image {
Image::new(size, dimension, data, format, asset_usage)
}
/// Create a new zero-filled image with a given size, which can be rendered to.
/// Useful for mirrors, UI, or exporting images for example.
/// This is primarily for use as a render target for a [`Camera`].
/// See [`RenderTarget::Image`].
///
/// For Standard Dynamic Range (SDR) images you can use [`TextureFormat::Rgba8UnormSrgb`].
/// For High Dynamic Range (HDR) images you can use [`TextureFormat::Rgba16Float`].
///
/// The default [`TextureUsages`] are
/// [`TEXTURE_BINDING`](TextureUsages::TEXTURE_BINDING),
/// [`COPY_DST`](TextureUsages::COPY_DST),
/// [`RENDER_ATTACHMENT`](TextureUsages::RENDER_ATTACHMENT).
///
/// The default [`RenderAssetUsages`] is [`MAIN_WORLD | RENDER_WORLD`](RenderAssetUsages::default)
/// so that it is accessible from the CPU and GPU.
/// You can customize this by changing the [`asset_usage`](Image::asset_usage) field.
///
/// [`Camera`]: https://docs.rs/bevy/latest/bevy/render/camera/struct.Camera.html
/// [`RenderTarget::Image`]: https://docs.rs/bevy/latest/bevy/render/camera/enum.RenderTarget.html#variant.Image
pub fn new_target_texture(width: u32, height: u32, format: TextureFormat) -> Self {
let size = Extent3d {
width,
height,
..Default::default()
};
// You need to set these texture usage flags in order to use the image as a render target
let usage = TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT;
// Fill with zeroes
let data = vec![0; format.pixel_size() * size.volume()];
Image {
data: Some(data),
data_order: TextureDataOrder::default(),
texture_descriptor: TextureDescriptor {
size,
format,
dimension: TextureDimension::D2,
label: None,
mip_level_count: 1,
sample_count: 1,
usage,
view_formats: &[],
},
sampler: ImageSampler::Default,
texture_view_descriptor: None,
asset_usage: RenderAssetUsages::default(),
copy_on_resize: true,
}
}
/// Returns the width of a 2D image.
#[inline]
pub fn width(&self) -> u32 {

View File

@ -4,11 +4,7 @@ use std::f32::consts::PI;
use bevy::{
prelude::*,
render::{
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
view::RenderLayers,
},
render::{render_resource::TextureFormat, view::RenderLayers},
};
fn main() {
@ -33,23 +29,8 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
) {
let size = Extent3d {
width: 512,
height: 512,
..default()
};
// This is the texture that will be rendered to.
let mut image = Image::new_fill(
size,
TextureDimension::D2,
&[0, 0, 0, 0],
TextureFormat::Bgra8UnormSrgb,
RenderAssetUsages::default(),
);
// You need to set these texture usage flags in order to use the image as a render target
image.texture_descriptor.usage =
TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST | TextureUsages::RENDER_ATTACHMENT;
let image = Image::new_target_texture(512, 512, TextureFormat::bevy_default());
let image_handle = images.add(image);

View File

@ -19,16 +19,16 @@ use bevy::{
prelude::*,
render::{
camera::RenderTarget,
render_asset::{RenderAssetUsages, RenderAssets},
render_asset::RenderAssets,
render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel},
render_resource::{
Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, MapMode,
PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat,
TextureUsages,
PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureFormat, TextureUsages,
},
renderer::{RenderContext, RenderDevice, RenderQueue},
Extract, Render, RenderApp, RenderSystems,
},
window::ExitCondition,
winit::WinitPlugin,
};
use crossbeam_channel::{Receiver, Sender};
@ -92,7 +92,7 @@ fn main() {
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,
exit_condition: ExitCondition::DontExit,
..default()
})
// WinitPlugin will panic in environments without a display server.
@ -247,25 +247,14 @@ fn setup_render_target(
};
// This is the texture that will be rendered to.
let mut render_target_image = Image::new_fill(
size,
TextureDimension::D2,
&[0; 4],
TextureFormat::bevy_default(),
RenderAssetUsages::default(),
);
render_target_image.texture_descriptor.usage |=
TextureUsages::COPY_SRC | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING;
let mut render_target_image =
Image::new_target_texture(size.width, size.height, TextureFormat::bevy_default());
render_target_image.texture_descriptor.usage |= TextureUsages::COPY_SRC;
let render_target_image_handle = images.add(render_target_image);
// This is the texture that will be copied to.
let cpu_image = Image::new_fill(
size,
TextureDimension::D2,
&[0; 4],
TextureFormat::bevy_default(),
RenderAssetUsages::default(),
);
let cpu_image =
Image::new_target_texture(size.width, size.height, TextureFormat::bevy_default());
let cpu_image_handle = images.add(cpu_image);
commands.spawn(ImageCopier::new(

View File

@ -51,17 +51,8 @@ fn main() {
}
fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
let mut image = Image::new_fill(
Extent3d {
width: SIZE.0,
height: SIZE.1,
depth_or_array_layers: 1,
},
TextureDimension::D2,
&[0, 0, 0, 255],
TextureFormat::R32Float,
RenderAssetUsages::RENDER_WORLD,
);
let mut image = Image::new_target_texture(SIZE.0, SIZE.1, TextureFormat::R32Float);
image.asset_usage = RenderAssetUsages::RENDER_WORLD;
image.texture_descriptor.usage =
TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING;
let image0 = images.add(image.clone());