mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
c3a46822e1
Co-authored-by: Robert Swain <robert.swain@gmail.com> # Objective Implements cascaded shadow maps for directional lights, which produces better quality shadows without needing excessively large shadow maps. Fixes #3629 Before ![image](https://user-images.githubusercontent.com/1222141/210061203-bbd965a4-8d11-4cec-9a88-67fc59d0819f.png) After ![image](https://user-images.githubusercontent.com/1222141/210061334-2ff15334-e6d7-4a31-9314-f34a7805cac6.png) ## Solution Rather than rendering a single shadow map for directional light, the view frustum is divided into a series of cascades, each of which gets its own shadow map. The correct cascade is then sampled for shadow determination. --- ## Changelog Directional lights now use cascaded shadow maps for improved shadow quality. ## Migration Guide You no longer have to manually specify a `shadow_projection` for a directional light, and these settings should be removed. If customization of how cascaded shadow maps work is desired, modify the `CascadeShadowConfig` component instead.
178 lines
5.4 KiB
Rust
178 lines
5.4 KiB
Rust
//! This examples compares MSAA (Multi-Sample Anti-Aliasing) and FXAA (Fast Approximate Anti-Aliasing).
|
|
|
|
use std::f32::consts::PI;
|
|
|
|
use bevy::{
|
|
core_pipeline::fxaa::{Fxaa, Sensitivity},
|
|
prelude::*,
|
|
render::{
|
|
render_resource::{Extent3d, SamplerDescriptor, TextureDimension, TextureFormat},
|
|
texture::ImageSampler,
|
|
},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
// Disable MSAA by default
|
|
.insert_resource(Msaa::Off)
|
|
.add_plugins(DefaultPlugins)
|
|
.add_startup_system(setup)
|
|
.add_system(toggle_fxaa)
|
|
.run();
|
|
}
|
|
|
|
/// set up a simple 3D scene
|
|
fn setup(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
mut images: ResMut<Assets<Image>>,
|
|
asset_server: Res<AssetServer>,
|
|
) {
|
|
println!("Toggle with:");
|
|
println!("1 - NO AA");
|
|
println!("2 - MSAA 4");
|
|
println!("3 - FXAA (default)");
|
|
|
|
println!("Threshold:");
|
|
println!("6 - LOW");
|
|
println!("7 - MEDIUM");
|
|
println!("8 - HIGH (default)");
|
|
println!("9 - ULTRA");
|
|
println!("0 - EXTREME");
|
|
|
|
// plane
|
|
commands.spawn(PbrBundle {
|
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
|
..default()
|
|
});
|
|
|
|
let cube_material = materials.add(StandardMaterial {
|
|
base_color_texture: Some(images.add(uv_debug_texture())),
|
|
..default()
|
|
});
|
|
|
|
// cubes
|
|
for i in 0..5 {
|
|
commands.spawn(PbrBundle {
|
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.25 })),
|
|
material: cube_material.clone(),
|
|
transform: Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
|
|
..default()
|
|
});
|
|
}
|
|
|
|
// Flight Helmet
|
|
commands.spawn(SceneBundle {
|
|
scene: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"),
|
|
..default()
|
|
});
|
|
|
|
// light
|
|
commands.spawn(DirectionalLightBundle {
|
|
directional_light: DirectionalLight {
|
|
shadows_enabled: true,
|
|
..default()
|
|
},
|
|
transform: Transform::from_rotation(Quat::from_euler(
|
|
EulerRot::ZYX,
|
|
0.0,
|
|
PI * -0.15,
|
|
PI * -0.15,
|
|
)),
|
|
..default()
|
|
});
|
|
|
|
// camera
|
|
commands
|
|
.spawn(Camera3dBundle {
|
|
camera: Camera {
|
|
hdr: false, // Works with and without hdr
|
|
..default()
|
|
},
|
|
transform: Transform::from_xyz(0.7, 0.7, 1.0)
|
|
.looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
|
|
..default()
|
|
})
|
|
.insert(Fxaa::default());
|
|
}
|
|
|
|
fn toggle_fxaa(keys: Res<Input<KeyCode>>, mut query: Query<&mut Fxaa>, mut msaa: ResMut<Msaa>) {
|
|
let set_no_aa = keys.just_pressed(KeyCode::Key1);
|
|
let set_msaa = keys.just_pressed(KeyCode::Key2);
|
|
let set_fxaa = keys.just_pressed(KeyCode::Key3);
|
|
let fxaa_low = keys.just_pressed(KeyCode::Key6);
|
|
let fxaa_med = keys.just_pressed(KeyCode::Key7);
|
|
let fxaa_high = keys.just_pressed(KeyCode::Key8);
|
|
let fxaa_ultra = keys.just_pressed(KeyCode::Key9);
|
|
let fxaa_extreme = keys.just_pressed(KeyCode::Key0);
|
|
let set_fxaa = set_fxaa | fxaa_low | fxaa_med | fxaa_high | fxaa_ultra | fxaa_extreme;
|
|
|
|
for mut fxaa in &mut query {
|
|
if set_msaa {
|
|
fxaa.enabled = false;
|
|
*msaa = Msaa::Sample4;
|
|
info!("MSAA 4x");
|
|
}
|
|
if set_no_aa {
|
|
fxaa.enabled = false;
|
|
*msaa = Msaa::Off;
|
|
info!("NO AA");
|
|
}
|
|
if set_no_aa | set_fxaa {
|
|
*msaa = Msaa::Off;
|
|
}
|
|
if fxaa_low {
|
|
fxaa.edge_threshold = Sensitivity::Low;
|
|
fxaa.edge_threshold_min = Sensitivity::Low;
|
|
} else if fxaa_med {
|
|
fxaa.edge_threshold = Sensitivity::Medium;
|
|
fxaa.edge_threshold_min = Sensitivity::Medium;
|
|
} else if fxaa_high {
|
|
fxaa.edge_threshold = Sensitivity::High;
|
|
fxaa.edge_threshold_min = Sensitivity::High;
|
|
} else if fxaa_ultra {
|
|
fxaa.edge_threshold = Sensitivity::Ultra;
|
|
fxaa.edge_threshold_min = Sensitivity::Ultra;
|
|
} else if fxaa_extreme {
|
|
fxaa.edge_threshold = Sensitivity::Extreme;
|
|
fxaa.edge_threshold_min = Sensitivity::Extreme;
|
|
}
|
|
if set_fxaa {
|
|
fxaa.enabled = true;
|
|
*msaa = Msaa::Off;
|
|
info!("FXAA {}", fxaa.edge_threshold.get_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Creates a colorful test pattern
|
|
fn uv_debug_texture() -> Image {
|
|
const TEXTURE_SIZE: usize = 8;
|
|
|
|
let mut palette: [u8; 32] = [
|
|
255, 102, 159, 255, 255, 159, 102, 255, 236, 255, 102, 255, 121, 255, 102, 255, 102, 255,
|
|
198, 255, 102, 198, 255, 255, 121, 102, 255, 255, 236, 102, 255, 255,
|
|
];
|
|
|
|
let mut texture_data = [0; TEXTURE_SIZE * TEXTURE_SIZE * 4];
|
|
for y in 0..TEXTURE_SIZE {
|
|
let offset = TEXTURE_SIZE * y * 4;
|
|
texture_data[offset..(offset + TEXTURE_SIZE * 4)].copy_from_slice(&palette);
|
|
palette.rotate_right(4);
|
|
}
|
|
|
|
let mut img = Image::new_fill(
|
|
Extent3d {
|
|
width: TEXTURE_SIZE as u32,
|
|
height: TEXTURE_SIZE as u32,
|
|
depth_or_array_layers: 1,
|
|
},
|
|
TextureDimension::D2,
|
|
&texture_data,
|
|
TextureFormat::Rgba8UnormSrgb,
|
|
);
|
|
img.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor::default());
|
|
img
|
|
}
|