Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/3d/anti_aliasing.rs
6592 views
1
//! Compares different anti-aliasing techniques supported by Bevy.
2
3
use std::{f32::consts::PI, fmt::Write};
4
5
use bevy::{
6
anti_alias::{
7
contrast_adaptive_sharpening::ContrastAdaptiveSharpening,
8
fxaa::{Fxaa, Sensitivity},
9
smaa::{Smaa, SmaaPreset},
10
taa::TemporalAntiAliasing,
11
},
12
asset::RenderAssetUsages,
13
core_pipeline::prepass::{DepthPrepass, MotionVectorPrepass},
14
image::{ImageSampler, ImageSamplerDescriptor},
15
light::CascadeShadowConfigBuilder,
16
prelude::*,
17
render::{
18
camera::{MipBias, TemporalJitter},
19
render_resource::{Extent3d, TextureDimension, TextureFormat},
20
view::Hdr,
21
},
22
};
23
24
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
25
use bevy::anti_alias::dlss::{
26
Dlss, DlssPerfQualityMode, DlssProjectId, DlssSuperResolutionSupported,
27
};
28
29
fn main() {
30
let mut app = App::new();
31
32
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
33
app.insert_resource(DlssProjectId(bevy_asset::uuid::uuid!(
34
"5417916c-0291-4e3f-8f65-326c1858ab96" // Don't copy paste this - generate your own UUID!
35
)));
36
37
app.add_plugins(DefaultPlugins)
38
.add_systems(Startup, setup)
39
.add_systems(Update, (modify_aa, modify_sharpening, update_ui));
40
41
app.run();
42
}
43
44
type TaaComponents = (
45
TemporalAntiAliasing,
46
TemporalJitter,
47
MipBias,
48
DepthPrepass,
49
MotionVectorPrepass,
50
);
51
52
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
53
type DlssComponents = (
54
Dlss,
55
TemporalJitter,
56
MipBias,
57
DepthPrepass,
58
MotionVectorPrepass,
59
);
60
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))]
61
type DlssComponents = ();
62
63
fn modify_aa(
64
keys: Res<ButtonInput<KeyCode>>,
65
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] camera: Single<
66
(
67
Entity,
68
Option<&mut Fxaa>,
69
Option<&mut Smaa>,
70
Option<&TemporalAntiAliasing>,
71
&mut Msaa,
72
Option<&mut Dlss>,
73
),
74
With<Camera>,
75
>,
76
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))] camera: Single<
77
(
78
Entity,
79
Option<&mut Fxaa>,
80
Option<&mut Smaa>,
81
Option<&TemporalAntiAliasing>,
82
&mut Msaa,
83
),
84
With<Camera>,
85
>,
86
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_supported: Option<
87
Res<DlssSuperResolutionSupported>,
88
>,
89
mut commands: Commands,
90
) {
91
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
92
let (camera_entity, fxaa, smaa, taa, mut msaa, dlss) = camera.into_inner();
93
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))]
94
let (camera_entity, fxaa, smaa, taa, mut msaa) = camera.into_inner();
95
let mut camera = commands.entity(camera_entity);
96
97
// No AA
98
if keys.just_pressed(KeyCode::Digit1) {
99
*msaa = Msaa::Off;
100
camera
101
.remove::<Fxaa>()
102
.remove::<Smaa>()
103
.remove::<TaaComponents>()
104
.remove::<DlssComponents>();
105
}
106
107
// MSAA
108
if keys.just_pressed(KeyCode::Digit2) && *msaa == Msaa::Off {
109
camera
110
.remove::<Fxaa>()
111
.remove::<Smaa>()
112
.remove::<TaaComponents>()
113
.remove::<DlssComponents>();
114
115
*msaa = Msaa::Sample4;
116
}
117
118
// MSAA Sample Count
119
if *msaa != Msaa::Off {
120
if keys.just_pressed(KeyCode::KeyQ) {
121
*msaa = Msaa::Sample2;
122
}
123
if keys.just_pressed(KeyCode::KeyW) {
124
*msaa = Msaa::Sample4;
125
}
126
if keys.just_pressed(KeyCode::KeyE) {
127
*msaa = Msaa::Sample8;
128
}
129
}
130
131
// FXAA
132
if keys.just_pressed(KeyCode::Digit3) && fxaa.is_none() {
133
*msaa = Msaa::Off;
134
camera
135
.remove::<Smaa>()
136
.remove::<TaaComponents>()
137
.remove::<DlssComponents>()
138
.insert(Fxaa::default());
139
}
140
141
// FXAA Settings
142
if let Some(mut fxaa) = fxaa {
143
if keys.just_pressed(KeyCode::KeyQ) {
144
fxaa.edge_threshold = Sensitivity::Low;
145
fxaa.edge_threshold_min = Sensitivity::Low;
146
}
147
if keys.just_pressed(KeyCode::KeyW) {
148
fxaa.edge_threshold = Sensitivity::Medium;
149
fxaa.edge_threshold_min = Sensitivity::Medium;
150
}
151
if keys.just_pressed(KeyCode::KeyE) {
152
fxaa.edge_threshold = Sensitivity::High;
153
fxaa.edge_threshold_min = Sensitivity::High;
154
}
155
if keys.just_pressed(KeyCode::KeyR) {
156
fxaa.edge_threshold = Sensitivity::Ultra;
157
fxaa.edge_threshold_min = Sensitivity::Ultra;
158
}
159
if keys.just_pressed(KeyCode::KeyT) {
160
fxaa.edge_threshold = Sensitivity::Extreme;
161
fxaa.edge_threshold_min = Sensitivity::Extreme;
162
}
163
}
164
165
// SMAA
166
if keys.just_pressed(KeyCode::Digit4) && smaa.is_none() {
167
*msaa = Msaa::Off;
168
camera
169
.remove::<Fxaa>()
170
.remove::<TaaComponents>()
171
.remove::<DlssComponents>()
172
.insert(Smaa::default());
173
}
174
175
// SMAA Settings
176
if let Some(mut smaa) = smaa {
177
if keys.just_pressed(KeyCode::KeyQ) {
178
smaa.preset = SmaaPreset::Low;
179
}
180
if keys.just_pressed(KeyCode::KeyW) {
181
smaa.preset = SmaaPreset::Medium;
182
}
183
if keys.just_pressed(KeyCode::KeyE) {
184
smaa.preset = SmaaPreset::High;
185
}
186
if keys.just_pressed(KeyCode::KeyR) {
187
smaa.preset = SmaaPreset::Ultra;
188
}
189
}
190
191
// TAA
192
if keys.just_pressed(KeyCode::Digit5) && taa.is_none() {
193
*msaa = Msaa::Off;
194
camera
195
.remove::<Fxaa>()
196
.remove::<Smaa>()
197
.remove::<DlssComponents>()
198
.insert(TemporalAntiAliasing::default());
199
}
200
201
// DLSS
202
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
203
if keys.just_pressed(KeyCode::Digit6) && dlss.is_none() && dlss_supported.is_some() {
204
*msaa = Msaa::Off;
205
camera
206
.remove::<Fxaa>()
207
.remove::<Smaa>()
208
.remove::<TaaComponents>()
209
.insert(Dlss::default());
210
}
211
212
// DLSS Settings
213
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
214
if let Some(mut dlss) = dlss {
215
if keys.just_pressed(KeyCode::KeyZ) {
216
dlss.perf_quality_mode = DlssPerfQualityMode::Auto;
217
}
218
if keys.just_pressed(KeyCode::KeyX) {
219
dlss.perf_quality_mode = DlssPerfQualityMode::UltraPerformance;
220
}
221
if keys.just_pressed(KeyCode::KeyC) {
222
dlss.perf_quality_mode = DlssPerfQualityMode::Performance;
223
}
224
if keys.just_pressed(KeyCode::KeyV) {
225
dlss.perf_quality_mode = DlssPerfQualityMode::Balanced;
226
}
227
if keys.just_pressed(KeyCode::KeyB) {
228
dlss.perf_quality_mode = DlssPerfQualityMode::Quality;
229
}
230
if keys.just_pressed(KeyCode::KeyN) {
231
dlss.perf_quality_mode = DlssPerfQualityMode::Dlaa;
232
}
233
}
234
}
235
236
fn modify_sharpening(
237
keys: Res<ButtonInput<KeyCode>>,
238
mut query: Query<&mut ContrastAdaptiveSharpening>,
239
) {
240
for mut cas in &mut query {
241
if keys.just_pressed(KeyCode::Digit0) {
242
cas.enabled = !cas.enabled;
243
}
244
if cas.enabled {
245
if keys.just_pressed(KeyCode::Minus) {
246
cas.sharpening_strength -= 0.1;
247
cas.sharpening_strength = cas.sharpening_strength.clamp(0.0, 1.0);
248
}
249
if keys.just_pressed(KeyCode::Equal) {
250
cas.sharpening_strength += 0.1;
251
cas.sharpening_strength = cas.sharpening_strength.clamp(0.0, 1.0);
252
}
253
if keys.just_pressed(KeyCode::KeyD) {
254
cas.denoise = !cas.denoise;
255
}
256
}
257
}
258
}
259
260
fn update_ui(
261
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] camera: Single<
262
(
263
Option<&Fxaa>,
264
Option<&Smaa>,
265
Option<&TemporalAntiAliasing>,
266
&ContrastAdaptiveSharpening,
267
&Msaa,
268
Option<&Dlss>,
269
),
270
With<Camera>,
271
>,
272
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))] camera: Single<
273
(
274
Option<&Fxaa>,
275
Option<&Smaa>,
276
Option<&TemporalAntiAliasing>,
277
&ContrastAdaptiveSharpening,
278
&Msaa,
279
),
280
With<Camera>,
281
>,
282
mut ui: Single<&mut Text>,
283
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_supported: Option<
284
Res<DlssSuperResolutionSupported>,
285
>,
286
) {
287
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
288
let (fxaa, smaa, taa, cas, msaa, dlss) = *camera;
289
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))]
290
let (fxaa, smaa, taa, cas, msaa) = *camera;
291
292
let ui = &mut ui.0;
293
*ui = "Antialias Method\n".to_string();
294
295
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
296
let dlss_none = dlss.is_none();
297
#[cfg(any(not(feature = "dlss"), feature = "force_disable_dlss"))]
298
let dlss_none = true;
299
300
draw_selectable_menu_item(
301
ui,
302
"No AA",
303
'1',
304
*msaa == Msaa::Off && fxaa.is_none() && taa.is_none() && smaa.is_none() && dlss_none,
305
);
306
draw_selectable_menu_item(ui, "MSAA", '2', *msaa != Msaa::Off);
307
draw_selectable_menu_item(ui, "FXAA", '3', fxaa.is_some());
308
draw_selectable_menu_item(ui, "SMAA", '4', smaa.is_some());
309
draw_selectable_menu_item(ui, "TAA", '5', taa.is_some());
310
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
311
if dlss_supported.is_some() {
312
draw_selectable_menu_item(ui, "DLSS", '6', dlss.is_some());
313
}
314
315
if *msaa != Msaa::Off {
316
ui.push_str("\n----------\n\nSample Count\n");
317
draw_selectable_menu_item(ui, "2", 'Q', *msaa == Msaa::Sample2);
318
draw_selectable_menu_item(ui, "4", 'W', *msaa == Msaa::Sample4);
319
draw_selectable_menu_item(ui, "8", 'E', *msaa == Msaa::Sample8);
320
}
321
322
if let Some(fxaa) = fxaa {
323
ui.push_str("\n----------\n\nSensitivity\n");
324
draw_selectable_menu_item(ui, "Low", 'Q', fxaa.edge_threshold == Sensitivity::Low);
325
draw_selectable_menu_item(
326
ui,
327
"Medium",
328
'W',
329
fxaa.edge_threshold == Sensitivity::Medium,
330
);
331
draw_selectable_menu_item(ui, "High", 'E', fxaa.edge_threshold == Sensitivity::High);
332
draw_selectable_menu_item(ui, "Ultra", 'R', fxaa.edge_threshold == Sensitivity::Ultra);
333
draw_selectable_menu_item(
334
ui,
335
"Extreme",
336
'T',
337
fxaa.edge_threshold == Sensitivity::Extreme,
338
);
339
}
340
341
if let Some(smaa) = smaa {
342
ui.push_str("\n----------\n\nQuality\n");
343
draw_selectable_menu_item(ui, "Low", 'Q', smaa.preset == SmaaPreset::Low);
344
draw_selectable_menu_item(ui, "Medium", 'W', smaa.preset == SmaaPreset::Medium);
345
draw_selectable_menu_item(ui, "High", 'E', smaa.preset == SmaaPreset::High);
346
draw_selectable_menu_item(ui, "Ultra", 'R', smaa.preset == SmaaPreset::Ultra);
347
}
348
349
#[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
350
if let Some(dlss) = dlss {
351
let pqm = dlss.perf_quality_mode;
352
ui.push_str("\n----------\n\nQuality\n");
353
draw_selectable_menu_item(ui, "Auto", 'Z', pqm == DlssPerfQualityMode::Auto);
354
draw_selectable_menu_item(
355
ui,
356
"UltraPerformance",
357
'X',
358
pqm == DlssPerfQualityMode::UltraPerformance,
359
);
360
draw_selectable_menu_item(
361
ui,
362
"Performance",
363
'C',
364
pqm == DlssPerfQualityMode::Performance,
365
);
366
draw_selectable_menu_item(ui, "Balanced", 'V', pqm == DlssPerfQualityMode::Balanced);
367
draw_selectable_menu_item(ui, "Quality", 'B', pqm == DlssPerfQualityMode::Quality);
368
draw_selectable_menu_item(ui, "DLAA", 'N', pqm == DlssPerfQualityMode::Dlaa);
369
}
370
371
ui.push_str("\n----------\n\n");
372
draw_selectable_menu_item(ui, "Sharpening", '0', cas.enabled);
373
374
if cas.enabled {
375
ui.push_str(&format!("(-/+) Strength: {:.1}\n", cas.sharpening_strength));
376
draw_selectable_menu_item(ui, "Denoising", 'D', cas.denoise);
377
}
378
}
379
380
/// Set up a simple 3D scene
381
fn setup(
382
mut commands: Commands,
383
mut meshes: ResMut<Assets<Mesh>>,
384
mut materials: ResMut<Assets<StandardMaterial>>,
385
mut images: ResMut<Assets<Image>>,
386
asset_server: Res<AssetServer>,
387
) {
388
// Plane
389
commands.spawn((
390
Mesh3d(meshes.add(Plane3d::default().mesh().size(20.0, 20.0))),
391
MeshMaterial3d(materials.add(Color::srgb(0.1, 0.2, 0.1))),
392
));
393
394
let cube_material = materials.add(StandardMaterial {
395
base_color_texture: Some(images.add(uv_debug_texture())),
396
..default()
397
});
398
399
// Cubes
400
for i in 0..5 {
401
commands.spawn((
402
Mesh3d(meshes.add(Cuboid::new(0.25, 0.25, 0.25))),
403
MeshMaterial3d(cube_material.clone()),
404
Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
405
));
406
}
407
408
// Flight Helmet
409
commands.spawn(SceneRoot(asset_server.load(
410
GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"),
411
)));
412
413
// Light
414
commands.spawn((
415
DirectionalLight {
416
illuminance: light_consts::lux::FULL_DAYLIGHT,
417
shadows_enabled: true,
418
..default()
419
},
420
Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, PI * -0.15, PI * -0.15)),
421
CascadeShadowConfigBuilder {
422
maximum_distance: 3.0,
423
first_cascade_far_bound: 0.9,
424
..default()
425
}
426
.build(),
427
));
428
429
// Camera
430
commands.spawn((
431
Camera3d::default(),
432
Hdr,
433
Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
434
ContrastAdaptiveSharpening {
435
enabled: false,
436
..default()
437
},
438
EnvironmentMapLight {
439
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
440
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
441
intensity: 150.0,
442
..default()
443
},
444
DistanceFog {
445
color: Color::srgba_u8(43, 44, 47, 255),
446
falloff: FogFalloff::Linear {
447
start: 1.0,
448
end: 4.0,
449
},
450
..default()
451
},
452
));
453
454
// example instructions
455
commands.spawn((
456
Text::default(),
457
Node {
458
position_type: PositionType::Absolute,
459
top: px(12),
460
left: px(12),
461
..default()
462
},
463
));
464
}
465
466
/// Writes a simple menu item that can be on or off.
467
fn draw_selectable_menu_item(ui: &mut String, label: &str, shortcut: char, enabled: bool) {
468
let star = if enabled { "*" } else { "" };
469
let _ = writeln!(*ui, "({shortcut}) {star}{label}{star}");
470
}
471
472
/// Creates a colorful test pattern
473
fn uv_debug_texture() -> Image {
474
const TEXTURE_SIZE: usize = 8;
475
476
let mut palette: [u8; 32] = [
477
255, 102, 159, 255, 255, 159, 102, 255, 236, 255, 102, 255, 121, 255, 102, 255, 102, 255,
478
198, 255, 102, 198, 255, 255, 121, 102, 255, 255, 236, 102, 255, 255,
479
];
480
481
let mut texture_data = [0; TEXTURE_SIZE * TEXTURE_SIZE * 4];
482
for y in 0..TEXTURE_SIZE {
483
let offset = TEXTURE_SIZE * y * 4;
484
texture_data[offset..(offset + TEXTURE_SIZE * 4)].copy_from_slice(&palette);
485
palette.rotate_right(4);
486
}
487
488
let mut img = Image::new_fill(
489
Extent3d {
490
width: TEXTURE_SIZE as u32,
491
height: TEXTURE_SIZE as u32,
492
depth_or_array_layers: 1,
493
},
494
TextureDimension::D2,
495
&texture_data,
496
TextureFormat::Rgba8UnormSrgb,
497
RenderAssetUsages::RENDER_WORLD,
498
);
499
img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default());
500
img
501
}
502
503