Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/stress_tests/many_gradients.rs
6849 views
1
//! Stress test demonstrating gradient performance improvements.
2
//!
3
//! This example creates many UI nodes with gradients to measure the performance
4
//! impact of pre-converting colors to the target color space on the CPU.
5
6
use argh::FromArgs;
7
use bevy::{
8
color::palettes::css::*,
9
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
10
math::ops::sin,
11
prelude::*,
12
ui::{
13
BackgroundGradient, ColorStop, Display, Gradient, InterpolationColorSpace, LinearGradient,
14
RepeatedGridTrack,
15
},
16
window::{PresentMode, WindowResolution},
17
winit::{UpdateMode, WinitSettings},
18
};
19
20
const COLS: usize = 30;
21
22
#[derive(FromArgs, Resource, Debug)]
23
/// Gradient stress test
24
struct Args {
25
/// how many gradients per group (default: 900)
26
#[argh(option, default = "900")]
27
gradient_count: usize,
28
29
/// whether to animate gradients by changing colors
30
#[argh(switch)]
31
animate: bool,
32
33
/// use sRGB interpolation
34
#[argh(switch)]
35
srgb: bool,
36
37
/// use HSL interpolation
38
#[argh(switch)]
39
hsl: bool,
40
}
41
42
fn main() {
43
let args: Args = argh::from_env();
44
let total_gradients = args.gradient_count;
45
46
println!("Gradient stress test with {total_gradients} gradients");
47
println!(
48
"Color space: {}",
49
if args.srgb {
50
"sRGB"
51
} else if args.hsl {
52
"HSL"
53
} else {
54
"OkLab (default)"
55
}
56
);
57
58
App::new()
59
.add_plugins((
60
LogDiagnosticsPlugin::default(),
61
FrameTimeDiagnosticsPlugin::default(),
62
DefaultPlugins.set(WindowPlugin {
63
primary_window: Some(Window {
64
title: "Gradient Stress Test".to_string(),
65
resolution: WindowResolution::new(1920, 1080).with_scale_factor_override(1.0),
66
present_mode: PresentMode::AutoNoVsync,
67
..default()
68
}),
69
..default()
70
}),
71
))
72
.insert_resource(WinitSettings {
73
focused_mode: UpdateMode::Continuous,
74
unfocused_mode: UpdateMode::Continuous,
75
})
76
.insert_resource(args)
77
.insert_resource(WinitSettings::continuous())
78
.add_systems(Startup, setup)
79
.add_systems(Update, animate_gradients)
80
.run();
81
}
82
83
fn setup(mut commands: Commands, args: Res<Args>) {
84
commands.spawn(Camera2d);
85
86
let rows_to_spawn = args.gradient_count.div_ceil(COLS);
87
88
// Create a grid of gradients
89
commands
90
.spawn(Node {
91
width: percent(100),
92
height: percent(100),
93
display: Display::Grid,
94
grid_template_columns: RepeatedGridTrack::flex(COLS as u16, 1.0),
95
grid_template_rows: RepeatedGridTrack::flex(rows_to_spawn as u16, 1.0),
96
..default()
97
})
98
.with_children(|parent| {
99
for i in 0..args.gradient_count {
100
let angle = (i as f32 * 10.0) % 360.0;
101
102
let mut gradient = LinearGradient::new(
103
angle,
104
vec![
105
ColorStop::new(RED, percent(0)),
106
ColorStop::new(BLUE, percent(100)),
107
ColorStop::new(GREEN, percent(20)),
108
ColorStop::new(YELLOW, percent(40)),
109
ColorStop::new(ORANGE, percent(60)),
110
ColorStop::new(LIME, percent(80)),
111
ColorStop::new(DARK_CYAN, percent(90)),
112
],
113
);
114
115
gradient.color_space = if args.srgb {
116
InterpolationColorSpace::Srgba
117
} else if args.hsl {
118
InterpolationColorSpace::Hsla
119
} else {
120
InterpolationColorSpace::Oklaba
121
};
122
123
parent.spawn((
124
Node {
125
width: percent(100),
126
height: percent(100),
127
..default()
128
},
129
BackgroundGradient(vec![Gradient::Linear(gradient)]),
130
GradientNode { index: i },
131
));
132
}
133
});
134
}
135
136
#[derive(Component)]
137
struct GradientNode {
138
index: usize,
139
}
140
141
fn animate_gradients(
142
mut gradients: Query<(&mut BackgroundGradient, &GradientNode)>,
143
args: Res<Args>,
144
time: Res<Time>,
145
) {
146
if !args.animate {
147
return;
148
}
149
150
let t = time.elapsed_secs();
151
152
for (mut bg_gradient, node) in &mut gradients {
153
let offset = node.index as f32 * 0.01;
154
let hue_shift = sin(t + offset) * 0.5 + 0.5;
155
156
if let Some(Gradient::Linear(gradient)) = bg_gradient.0.get_mut(0) {
157
let color1 = Color::hsl(hue_shift * 360.0, 1.0, 0.5);
158
let color2 = Color::hsl((hue_shift + 0.3) * 360.0 % 360.0, 1.0, 0.5);
159
160
gradient.stops = vec![
161
ColorStop::new(color1, percent(0)),
162
ColorStop::new(color2, percent(100)),
163
ColorStop::new(
164
Color::hsl((hue_shift + 0.1) * 360.0 % 360.0, 1.0, 0.5),
165
percent(20),
166
),
167
ColorStop::new(
168
Color::hsl((hue_shift + 0.15) * 360.0 % 360.0, 1.0, 0.5),
169
percent(40),
170
),
171
ColorStop::new(
172
Color::hsl((hue_shift + 0.2) * 360.0 % 360.0, 1.0, 0.5),
173
percent(60),
174
),
175
ColorStop::new(
176
Color::hsl((hue_shift + 0.25) * 360.0 % 360.0, 1.0, 0.5),
177
percent(80),
178
),
179
ColorStop::new(
180
Color::hsl((hue_shift + 0.28) * 360.0 % 360.0, 1.0, 0.5),
181
percent(90),
182
),
183
];
184
}
185
}
186
}
187
188