mirror of
https://github.com/bevyengine/bevy.git
synced 2026-06-30 07:45:50 -04:00
9fd2637846
# Objective - Fixes #16751 ## Solution - `Assets::get_mut` now returns a wrapper `AssetMut` type instead of `&mut impl Asset`. - `AssetMut` implements `Deref` and `DerefMut`. - `DerefMut` marks assets as changed. - when dropped `AssetMut` will add `AssetEvent::Modified` event to a queue only in case asset was marked as changed. ## Testing - Did you test these changes? If so, how? - No unit tests were added, change is pretty straightforward. - Test project: https://github.com/MatrixDev/bevy-feature-16751-test. - With change: ~100 fps. - Without change: ~15 fps. - Are there any parts that need more testing? - I don't really see how this can break anything or add a measurable overhead. - `AssetEvent::Modified` will now be sent after the asset was modified instead of before. It should not affect anything but still worth noting. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Have a big amount of entities that constantly update their materials. - Properties of those materials should be animated in a stepped maned (like changing color every 0.1 seconds). - Update material only if value has actually changed: ```rust if material.base_color != new_color { material.base_color = new_color; } ``` - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? - tested on macos (Mackbook M1) - not a platform-specific issue PS: This is my first PR, so please don’t judge.
105 lines
3.1 KiB
Rust
105 lines
3.1 KiB
Rust
//! Benchmark to test rendering many animated materials
|
|
use argh::FromArgs;
|
|
use bevy::{
|
|
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
|
prelude::*,
|
|
window::{PresentMode, WindowResolution},
|
|
winit::WinitSettings,
|
|
};
|
|
use std::f32::consts::PI;
|
|
|
|
#[derive(FromArgs, Resource)]
|
|
/// Command-line arguments for the `many_materials` stress test.
|
|
struct Args {
|
|
/// the size of the grid of materials to render (n x n)
|
|
#[argh(option, short = 'n', default = "10")]
|
|
grid_size: usize,
|
|
}
|
|
|
|
fn main() {
|
|
// `from_env` panics on the web
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
let args: Args = argh::from_env();
|
|
#[cfg(target_arch = "wasm32")]
|
|
let args = Args::from_args(&[], &[]).unwrap();
|
|
|
|
App::new()
|
|
.add_plugins((
|
|
DefaultPlugins.set(WindowPlugin {
|
|
primary_window: Some(Window {
|
|
resolution: WindowResolution::new(1920, 1080).with_scale_factor_override(1.0),
|
|
title: "many_materials".into(),
|
|
present_mode: PresentMode::AutoNoVsync,
|
|
..default()
|
|
}),
|
|
..default()
|
|
}),
|
|
FrameTimeDiagnosticsPlugin::default(),
|
|
LogDiagnosticsPlugin::default(),
|
|
))
|
|
.insert_resource(WinitSettings::continuous())
|
|
.insert_resource(args)
|
|
.add_systems(Startup, setup)
|
|
.add_systems(Update, animate_materials)
|
|
.run();
|
|
}
|
|
|
|
fn setup(
|
|
mut commands: Commands,
|
|
args: Res<Args>,
|
|
mesh_assets: ResMut<Assets<Mesh>>,
|
|
material_assets: ResMut<Assets<StandardMaterial>>,
|
|
) {
|
|
let args = args.into_inner();
|
|
let material_assets = material_assets.into_inner();
|
|
let mesh_assets = mesh_assets.into_inner();
|
|
let n = args.grid_size;
|
|
|
|
// Camera
|
|
let w = n as f32;
|
|
commands.spawn((
|
|
Camera3d::default(),
|
|
Transform::from_xyz(w * 1.25, w + 1.0, w * 1.25)
|
|
.looking_at(Vec3::new(0.0, (w * -1.1) + 1.0, 0.0), Vec3::Y),
|
|
));
|
|
|
|
// Light
|
|
commands.spawn((
|
|
Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
|
|
DirectionalLight {
|
|
illuminance: 3000.0,
|
|
shadow_maps_enabled: true,
|
|
..default()
|
|
},
|
|
));
|
|
|
|
// Cubes
|
|
let mesh_handle = mesh_assets.add(Cuboid::from_size(Vec3::ONE));
|
|
for x in 0..n {
|
|
for z in 0..n {
|
|
commands.spawn((
|
|
Mesh3d(mesh_handle.clone()),
|
|
MeshMaterial3d(material_assets.add(Color::WHITE)),
|
|
Transform::from_translation(Vec3::new(x as f32, 0.0, z as f32)),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
fn animate_materials(
|
|
material_handles: Query<&MeshMaterial3d<StandardMaterial>>,
|
|
time: Res<Time>,
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
) {
|
|
for (i, material_handle) in material_handles.iter().enumerate() {
|
|
if let Some(mut material) = materials.get_mut(material_handle) {
|
|
let color = Color::hsl(
|
|
((i as f32 * 2.345 + time.elapsed_secs()) * 100.0) % 360.0,
|
|
1.0,
|
|
0.5,
|
|
);
|
|
material.base_color = color;
|
|
}
|
|
}
|
|
}
|