bevyengine / bevyengine/bevy

CPU drawing into 2D texture is not updated to the GPU when using any 2D materials

Open
#20,269 2 comments 3 reactions 0 assignees View on GitHub
A-Rendering C-Bug S-Needs-Investigation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version

The release number or commit hash of the version you're using.
bevy = "0.16.1"

## \[Optional\] Relevant system information

```
AdapterInfo { name: "Apple M3", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }
```

It should reproduce on any other GPU

## What you did

### Create a sprite using any 2D material with custom texture, like ColorMaterial or something custom

```rust
let image = Image::new_fill(
// 2D image of size
Extent3d {
width: s as u32,
height: s as u32,
depth_or_array_layers: 1,
},
TextureDimension::D2,
// Initialize it with a beige color
&(color),
// Use the same encoding as the color we set
TextureFormat::Rgba8UnormSrgb,
RenderAssetUsages::RENDER_WORLD | RenderAssetUsages::MAIN_WORLD,
);
let handle = images.add(image);

let mat = ColorMaterial {
texture: handle.clone(),
};

let material_handle = materials.add(mat);

let mesh = meshes.add(Rectangle::new(
s as f32,
s as f32,
));

commands.spawn((
MeshMaterial2d(material_handle.clone()),
Mesh2d(mesh),
Transform::from_xyz(0.0, 0.0, 100000.0),
));
commands.insert_resource(LightOverlayTextureHandle(handle)); // my custom handle res
commands.insert_resource(LightOverlayMaterialHandle(material_handle));
```

### Draw to that texture in a system

```rust
pub fn draw_random_color_pixel(
light_texture_handle: Res,
light_material_handle: Res,
mut images: ResMut>,
mut materials: ResMut>,
) {
// Get mutable reference to the image
if let Some(image) = images.get_mut(&light_texture_handle.0) {
let width = image.size().x;
let height = image.size().y;

// Generate random coordinates and color
let mut rng = rand::rng();
let x = rng.gen_range(0..width);
let y = rng.gen_range(0..height);

let color = Color::srgb(
rng.gen_range(0.0..=1.0),
rng.gen_range(0.0..=1.0),
rng.gen_range(0.0..=1.0),
);

// Set the pixel
image.set_color_at(x, y, color).unwrap();
}
// placeholder for a hotfix
}
```

## What went wrong

If using FixedUpdate sheduler - no draws happen on the screen, texture is not updated
If using Update scheduler - only first update is visible on the screen, then texture is not updated

### Hot fix:

Add `materials.get_mut(&light_material_handle.0)` to the end of your system, that does literally nothing and does not actually mutate material, but it assumes that material has changed and updates the texture, this way it works perfectly.

I believe this is not how it is supposed to work.

## Additional information

When using example with sprite::from_image(), then it tracks texture changes correctly. It should work the same when Material2D is used.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.