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

Add Image constructor specialised for rendering to a texture #17209

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
46 changes: 45 additions & 1 deletion crates/bevy_image/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ pub trait BevyDefault {

impl BevyDefault for TextureFormat {
fn bevy_default() -> Self {
TextureFormat::Rgba8UnormSrgb
TEXTURE_FORMAT_SDR
}
}

pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float;
pub const TEXTURE_FORMAT_SDR: TextureFormat = TextureFormat::Rgba8UnormSrgb;

pub const TEXTURE_ASSET_INDEX: u64 = 0;
pub const SAMPLER_ASSET_INDEX: u64 = 1;

Expand Down Expand Up @@ -761,6 +764,47 @@ impl Image {
value
}

/// Create a new zero-filled image with a given size, which can be rendered to. This is primarily
/// for use as a render target for a [`Camera`]. See [`RenderTarget::Image`].
///
/// [`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, hdr: bool) -> Self {
let format = if hdr {
TEXTURE_FORMAT_HDR
} else {
TEXTURE_FORMAT_SDR
};
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,
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(),
}
}

/// Returns the width of a 2D image.
#[inline]
pub fn width(&self) -> u32 {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use bevy_app::{App, Plugin};
use bevy_color::LinearRgba;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::prelude::*;
use bevy_image::BevyDefault as _;
use bevy_image::{BevyDefault as _, TEXTURE_FORMAT_HDR};
use bevy_math::{mat3, vec2, vec3, Mat3, Mat4, UVec4, Vec2, Vec3, Vec4, Vec4Swizzles};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render_macros::ExtractComponent;
Expand Down Expand Up @@ -638,7 +638,7 @@ pub struct NoIndirectDrawing;
pub struct NoCpuCulling;

impl ViewTarget {
pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float;
pub const TEXTURE_FORMAT_HDR: TextureFormat = TEXTURE_FORMAT_HDR;

/// Retrieve this target's main texture's color attachment.
pub fn get_color_attachment(&self) -> RenderPassColorAttachment {
Expand Down
26 changes: 2 additions & 24 deletions examples/3d/render_to_texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@

use std::f32::consts::PI;

use bevy::{
prelude::*,
render::{
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
view::RenderLayers,
},
};
use bevy::{prelude::*, render::view::RenderLayers};

fn main() {
App::new()
Expand All @@ -33,23 +26,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, false);

let image_handle = images.add(image);

Expand Down
26 changes: 7 additions & 19 deletions examples/app/headless_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,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,
ImageCopyBuffer, ImageDataLayout, Maintain, MapMode, TextureDimension, TextureFormat,
TextureUsages,
ImageCopyBuffer, ImageDataLayout, Maintain, MapMode, TextureUsages,
},
renderer::{RenderContext, RenderDevice, RenderQueue},
Extract, Render, RenderApp, RenderSet,
},
window::ExitCondition,
winit::WinitPlugin,
};
use crossbeam_channel::{Receiver, Sender};
Expand Down Expand Up @@ -86,6 +86,7 @@ fn main() {
// replaces the bevy_winit app runner and so a window is never created.
.set(WindowPlugin {
primary_window: None,
exit_condition: ExitCondition::DontExit,
..default()
})
// WinitPlugin will panic in environments without a display server.
Expand Down Expand Up @@ -237,25 +238,12 @@ 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, false);
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, false);
let cpu_image_handle = images.add(cpu_image);

commands.spawn(ImageCopier::new(
Expand Down
14 changes: 3 additions & 11 deletions examples/shader/compute_shader_game_of_life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,9 @@ 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, false);
image.asset_usage = RenderAssetUsages::RENDER_WORLD;
image.texture_descriptor.format = TextureFormat::R32Float;
image.texture_descriptor.usage =
TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING;
let image0 = images.add(image.clone());
Expand Down
15 changes: 3 additions & 12 deletions examples/shader/gpu_readback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,9 @@ fn setup(
let buffer = buffers.add(buffer);

// Create a storage texture with some data
let size = Extent3d {
width: BUFFER_LEN as u32,
height: 1,
..default()
};
let mut image = Image::new_fill(
size,
TextureDimension::D2,
&[0, 0, 0, 0],
TextureFormat::R32Uint,
RenderAssetUsages::RENDER_WORLD,
);
let mut image = Image::new_target_texture(BUFFER_LEN as u32, 1, false);
image.asset_usage = RenderAssetUsages::RENDER_WORLD;
image.texture_descriptor.format = TextureFormat::R32Uint;
// We also need to enable the COPY_SRC, as well as STORAGE_BINDING so we can use it in the
// compute shader
image.texture_descriptor.usage |= TextureUsages::COPY_SRC | TextureUsages::STORAGE_BINDING;
Expand Down
Loading