-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bevy_pbr2: Add support for not casting/receiving shadows (#2726)
# Objective Allow marking meshes as not casting / receiving shadows. ## Solution - Added `NotShadowCaster` and `NotShadowReceiver` zero-sized type components. - Extract these components into `bool`s in `ExtractedMesh` - Only generate `DrawShadowMesh` `Drawable`s for meshes _without_ `NotShadowCaster` - Add a `u32` bit `flags` member to `MeshUniform` with one flag indicating whether the mesh is a shadow receiver - If a mesh does _not_ have the `NotShadowReceiver` component, then it is a shadow receiver, and so the bit in the `MeshUniform` is set, otherwise it is not set. - Added an example illustrating the functionality. NOTE: I wanted to have the default state of a mesh as being a shadow caster and shadow receiver, hence the `Not*` components. However, I am on the fence about this. I don't want to have a negative performance impact, nor have people wondering why their custom meshes don't have shadows because they forgot to add `ShadowCaster` and `ShadowReceiver` components, but I also really don't like the double negatives the `Not*` approach incurs. What do you think? Co-authored-by: Carter Anderson <[email protected]>
- Loading branch information
Showing
6 changed files
with
286 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
use bevy::{ | ||
ecs::prelude::*, | ||
input::Input, | ||
math::{EulerRot, Mat4, Vec3}, | ||
pbr2::{ | ||
DirectionalLight, DirectionalLightBundle, NotShadowCaster, NotShadowReceiver, PbrBundle, | ||
PointLight, PointLightBundle, StandardMaterial, | ||
}, | ||
prelude::{App, Assets, Handle, KeyCode, Transform}, | ||
render2::{ | ||
camera::{OrthographicProjection, PerspectiveCameraBundle}, | ||
color::Color, | ||
mesh::{shape, Mesh}, | ||
}, | ||
PipelinedDefaultPlugins, | ||
}; | ||
|
||
fn main() { | ||
println!( | ||
"Controls: | ||
C - toggle shadow casters (i.e. casters become not, and not casters become casters) | ||
R - toggle shadow receivers (i.e. receivers become not, and not receivers become receivers) | ||
L - switch between directional and point lights" | ||
); | ||
App::new() | ||
.add_plugins(PipelinedDefaultPlugins) | ||
.add_startup_system(setup) | ||
.add_system(toggle_light) | ||
.add_system(toggle_shadows) | ||
.run(); | ||
} | ||
|
||
/// set up a 3D scene to test shadow biases and perspective projections | ||
fn setup( | ||
mut commands: Commands, | ||
mut meshes: ResMut<Assets<Mesh>>, | ||
mut materials: ResMut<Assets<StandardMaterial>>, | ||
) { | ||
let spawn_plane_depth = 500.0f32; | ||
let spawn_height = 2.0; | ||
let sphere_radius = 0.25; | ||
|
||
let white_handle = materials.add(StandardMaterial { | ||
base_color: Color::WHITE, | ||
perceptual_roughness: 1.0, | ||
..Default::default() | ||
}); | ||
let sphere_handle = meshes.add(Mesh::from(shape::Icosphere { | ||
radius: sphere_radius, | ||
..Default::default() | ||
})); | ||
|
||
// sphere - initially a caster | ||
commands.spawn_bundle(PbrBundle { | ||
mesh: sphere_handle.clone(), | ||
material: materials.add(Color::RED.into()), | ||
transform: Transform::from_xyz(-1.0, spawn_height, 0.0), | ||
..Default::default() | ||
}); | ||
|
||
// sphere - initially not a caster | ||
commands | ||
.spawn_bundle(PbrBundle { | ||
mesh: sphere_handle, | ||
material: materials.add(Color::BLUE.into()), | ||
transform: Transform::from_xyz(1.0, spawn_height, 0.0), | ||
..Default::default() | ||
}) | ||
.insert(NotShadowCaster); | ||
|
||
// floating plane - initially not a shadow receiver and not a caster | ||
commands | ||
.spawn_bundle(PbrBundle { | ||
mesh: meshes.add(Mesh::from(shape::Plane { size: 20.0 })), | ||
material: materials.add(Color::GREEN.into()), | ||
transform: Transform::from_xyz(0.0, 1.0, -10.0), | ||
..Default::default() | ||
}) | ||
.insert_bundle((NotShadowCaster, NotShadowReceiver)); | ||
|
||
// lower ground plane - initially a shadow receiver | ||
commands.spawn_bundle(PbrBundle { | ||
mesh: meshes.add(Mesh::from(shape::Plane { size: 20.0 })), | ||
material: white_handle, | ||
..Default::default() | ||
}); | ||
|
||
println!("Using DirectionalLight"); | ||
|
||
commands.spawn_bundle(PointLightBundle { | ||
transform: Transform::from_xyz(5.0, 5.0, 0.0), | ||
point_light: PointLight { | ||
intensity: 0.0, | ||
range: spawn_plane_depth, | ||
color: Color::WHITE, | ||
..Default::default() | ||
}, | ||
..Default::default() | ||
}); | ||
|
||
let theta = std::f32::consts::FRAC_PI_4; | ||
let light_transform = Mat4::from_euler(EulerRot::ZYX, 0.0, std::f32::consts::FRAC_PI_2, -theta); | ||
commands.spawn_bundle(DirectionalLightBundle { | ||
directional_light: DirectionalLight { | ||
illuminance: 100000.0, | ||
shadow_projection: OrthographicProjection { | ||
left: -10.0, | ||
right: 10.0, | ||
bottom: -10.0, | ||
top: 10.0, | ||
near: -50.0, | ||
far: 50.0, | ||
..Default::default() | ||
}, | ||
..Default::default() | ||
}, | ||
transform: Transform::from_matrix(light_transform), | ||
..Default::default() | ||
}); | ||
|
||
// camera | ||
commands.spawn_bundle(PerspectiveCameraBundle { | ||
transform: Transform::from_xyz(-5.0, 5.0, 5.0) | ||
.looking_at(Vec3::new(-1.0, 1.0, 0.0), Vec3::Y), | ||
..Default::default() | ||
}); | ||
} | ||
|
||
fn toggle_light( | ||
input: Res<Input<KeyCode>>, | ||
mut point_lights: Query<&mut PointLight>, | ||
mut directional_lights: Query<&mut DirectionalLight>, | ||
) { | ||
if input.just_pressed(KeyCode::L) { | ||
for mut light in point_lights.iter_mut() { | ||
light.intensity = if light.intensity == 0.0 { | ||
println!("Using PointLight"); | ||
100000000.0 | ||
} else { | ||
0.0 | ||
}; | ||
} | ||
for mut light in directional_lights.iter_mut() { | ||
light.illuminance = if light.illuminance == 0.0 { | ||
println!("Using DirectionalLight"); | ||
100000.0 | ||
} else { | ||
0.0 | ||
}; | ||
} | ||
} | ||
} | ||
|
||
fn toggle_shadows( | ||
mut commands: Commands, | ||
input: Res<Input<KeyCode>>, | ||
queries: QuerySet<( | ||
Query<Entity, (With<Handle<Mesh>>, With<NotShadowCaster>)>, | ||
Query<Entity, (With<Handle<Mesh>>, With<NotShadowReceiver>)>, | ||
Query<Entity, (With<Handle<Mesh>>, Without<NotShadowCaster>)>, | ||
Query<Entity, (With<Handle<Mesh>>, Without<NotShadowReceiver>)>, | ||
)>, | ||
) { | ||
if input.just_pressed(KeyCode::C) { | ||
println!("Toggling casters"); | ||
for entity in queries.q0().iter() { | ||
commands.entity(entity).remove::<NotShadowCaster>(); | ||
} | ||
for entity in queries.q2().iter() { | ||
commands.entity(entity).insert(NotShadowCaster); | ||
} | ||
} | ||
if input.just_pressed(KeyCode::R) { | ||
println!("Toggling receivers"); | ||
for entity in queries.q1().iter() { | ||
commands.entity(entity).remove::<NotShadowReceiver>(); | ||
} | ||
for entity in queries.q3().iter() { | ||
commands.entity(entity).insert(NotShadowReceiver); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.