Updating a spawned mesh asset requires RenderAssetUsages::default() in 0.16.0-rc.5
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version
0.16.0-rc.5
## \[Optional\] Relevant system information
If you cannot get Bevy to build or run on your machine, please include:
- Rust 1.85.1
- SystemInfo { os: "Linux (Ubuntu 24.04)", kernel: "6.11.0-21-generic", cpu: "AMD Ryzen 7 5825U with Radeon Graphics", core_count: "8", memory: "28.3 GiB" }
If your bug is rendering-related, copy the adapter info that appears when you run Bevy.
```ignore
AdapterInfo { name: "AMD Radeon Graphics (RADV RENOIR)", vendor: 4098, device: 5607, device_type: IntegratedGpu, driver: "radv", driver_info: "Mesa 24.2.8-1ubuntu1~24.04.1", backend: Vulkan }
```
## What you did
I have a mesh generated procedurally on the CPU, that has been spawned, perhaps several instances. I want to update/ replace the mesh (again procedurally on the CPU), by calling `meshes.insert(handle, new_mesh)`. In 0.16, this only works if I set `RenderAssetUsages::default()` on the mesh asset. If instead I use `RenderAssetUsages::RENDER_WORLD`, spawned meshes update sporadically, after a few minutes.
MWE:
```rust
use bevy::{
asset::RenderAssetUsages,
input::keyboard::KeyboardInput,
prelude::*,
render::mesh::{Indices, PrimitiveTopology},
};
use rand::Rng;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, spawn_scene)
.add_systems(Update, update_mesh_asset.run_if(on_event::))
.run();
}
fn spawn_scene(
mut commands: Commands,
mut meshes: ResMut>,
mut materials: ResMut>,
) {
commands.spawn((
Camera3d::default(),
Transform::from_xyz(2.0, 2.0, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
));
let mesh = meshes.add(create_cube_mesh(Vec3::ONE));
commands.spawn((
Mesh3d(mesh),
MeshMaterial3d(materials.add(StandardMaterial::default())),
));
}
// Press any key to update the mesh
fn update_mesh_asset(
keys: Res>,
mut meshes: ResMut>,
query: Query<&Mesh3d>,
) {
if keys.get_just_pressed().next().is_none() {
return;
};
let Ok(mesh) = query.get_single() else { return };
let handle = mesh.id();//0.clone();
let mut rng = rand::rng();
let cube = create_cube_mesh(Vec3::new(
rng.random_range(0.5..1.5),
rng.random_range(0.5..1.5),
rng.random_range(0.5..1.5),
));
meshes.insert(handle, cube);
}
fn create_cube_mesh(size: Vec3) -> Mesh {
// Prior to 0.16, `RenderAssetUsages::RENDER_WORLD` works for every key press
// In 0.16.0-rc.5, you need to use `RenderAssetUsages::default()`
let mut mesh = Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::RENDER_WORLD,
);
mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
vec![
// top (facing towards +y)
[-0.5, 0.5, -0.5], // vertex with index 0
[0.5, 0.5, -0.5], // vertex with index 1
[0.5, 0.5, 0.5], // etc. until 23
[-0.5, 0.5, 0.5],
// bottom (-y)
[-0.5, -0.5, -0.5],
[0.5, -0.5, -0.5],
[0.5, -0.5, 0.5],
[-0.5, -0.5, 0.5],
// right (+x)
[0.5, -0.5, -0.5],
[0.5, -0.5, 0.5],
[0.5, 0.5, 0.5], // This vertex is at the same position as vertex with index 2, but they'll have different UV and normal
[0.5, 0.5, -0.5],
// left (-x)
[-0.5, -0.5, -0.5],
[-0.5, -0.5, 0.5],
[-0.5, 0.5, 0.5],
[-0.5, 0.5, -0.5],
// back (+z)
[-0.5, -0.5, 0.5],
[-0.5, 0.5, 0.5],
[0.5, 0.5, 0.5],
[0.5, -0.5, 0.5],
// forward (-z)
[-0.5, -0.5, -0.5],
[-0.5, 0.5, -0.5],
[0.5, 0.5, -0.5],
[0.5, -0.5, -0.5],
]
.iter()
.map(|v| [v[0] * size.x, v[1] * size.y, v[2] * size.z])
.collect::>(),
);
mesh.insert_attribute(
Mesh::ATTRIBUTE_UV_0,
vec![
// Assigning the UV coords for the top side.
[0.0, 0.2],
[0.0, 0.0],
[1.0, 0.0],
[1.0, 0.2],
// Assigning the UV coords for the bottom side.
[0.0, 0.45],
[0.0, 0.25],
[1.0, 0.25],
[1.0, 0.45],
// Assigning the UV coords for the right side.
[1.0, 0.45],
[0.0, 0.45],
[0.0, 0.2],
[1.0, 0.2],
// Assigning the UV coords for the left side.
[1.0, 0.45],
[0.0, 0.45],
[0.0, 0.2],
[1.0, 0.2],
// Assigning the UV coords for the back side.
[0.0, 0.45],
[0.0, 0.2],
[1.0, 0.2],
[1.0, 0.45],
// Assigning the UV coords for the forward side.
[0.0, 0.45],
[0.0, 0.2],
[1.0, 0.2],
[1.0, 0.45],
],
);
mesh.insert_attribute(
Mesh::ATTRIBUTE_NORMAL,
vec![
// Normals for the top side (towards +y)
[0.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
// Normals for the bottom side (towards -y)
[0.0, -1.0, 0.0],
[0.0, -1.0, 0.0],
[0.0, -1.0, 0.0],
[0.0, -1.0, 0.0],
// Normals for the right side (towards +x)
[1.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
// Normals for the left side (towards -x)
[-1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
// Normals for the back side (towards +z)
[0.0, 0.0, 1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 1.0],
// Normals for the forward side (towards -z)
[0.0, 0.0, -1.0],
[0.0, 0.0, -1.0],
[0.0, 0.0, -1.0],
[0.0, 0.0, -1.0],
],
);
mesh.insert_indices(Indices::U32(vec![
0, 3, 1, 1, 3, 2, // triangles making up the top (+y) facing side.
4, 5, 7, 5, 6, 7, // bottom (-y)
8, 11, 9, 9, 11, 10, // right (+x)
12, 13, 15, 13, 14, 15, // left (-x)
16, 19, 17, 17, 19, 18, // back (+z)
20, 21, 23, 21, 22, 23, // forward (-z)
]));
mesh
}
```
## What went wrong
If it's not clear, break this out into:
- what were you expecting?
In 0.16 I expect to be able to update a spawned mesh that has the usage `RenderAssetUsages::RENDER_WORLD` , as was possible prior to 0.16
- what actually happened?
The asset updates, but only sporadically, after a few minutes. To get the old behaviour back, I need to set `RenderAssetUsages::default()` on the mesh asset
Contributor guide
Research direction
Start by running the provided Rust MWE and inspect the update_mesh_asset and create_cube_mesh entry points, especially the RenderAssetUsages::RENDER_WORLD path. Compare repeated mesh replacement with RenderAssetUsages::default(); done means a spawned mesh updates reliably on every key press with RENDER_WORLD, as expected from the report.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100