mirror of
https://github.com/bevyengine/bevy
synced 2024-12-12 06:12:30 +00:00
b6a647cc01
Adds a `default()` shorthand for `Default::default()` ... because life is too short to constantly type `Default::default()`. ```rust use bevy::prelude::*; #[derive(Default)] struct Foo { bar: usize, baz: usize, } // Normally you would do this: let foo = Foo { bar: 10, ..Default::default() }; // But now you can do this: let foo = Foo { bar: 10, ..default() }; ``` The examples have been adapted to use `..default()`. I've left internal crates as-is for now because they don't pull in the bevy prelude, and the ergonomics of each case should be considered individually.
321 lines
9.8 KiB
Rust
321 lines
9.8 KiB
Rust
use bevy::{input::mouse::MouseMotion, prelude::*};
|
|
|
|
fn main() {
|
|
println!(
|
|
"Controls:
|
|
WSAD - forward/back/strafe left/right
|
|
LShift - 'run'
|
|
E - up
|
|
Q - down
|
|
L - switch between directional and point lights
|
|
1/2 - decrease/increase point light depth bias
|
|
3/4 - decrease/increase point light normal bias
|
|
5/6 - decrease/increase direction light depth bias
|
|
7/8 - decrease/increase direction light normal bias"
|
|
);
|
|
App::new()
|
|
.add_plugins(DefaultPlugins)
|
|
.add_startup_system(setup)
|
|
.add_system(adjust_point_light_biases)
|
|
.add_system(toggle_light)
|
|
.add_system(adjust_directional_light_biases)
|
|
.add_system(camera_controller)
|
|
.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()
|
|
});
|
|
let sphere_handle = meshes.add(Mesh::from(shape::Icosphere {
|
|
radius: sphere_radius,
|
|
..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,
|
|
shadow_depth_bias: 0.0,
|
|
shadow_normal_bias: 0.0,
|
|
shadows_enabled: true,
|
|
..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: -0.35,
|
|
right: 500.35,
|
|
bottom: -0.1,
|
|
top: 5.0,
|
|
near: -5.0,
|
|
far: 5.0,
|
|
..default()
|
|
},
|
|
shadow_depth_bias: 0.0,
|
|
shadow_normal_bias: 0.0,
|
|
shadows_enabled: true,
|
|
..default()
|
|
},
|
|
transform: Transform::from_matrix(light_transform),
|
|
..default()
|
|
});
|
|
|
|
// camera
|
|
commands
|
|
.spawn_bundle(PerspectiveCameraBundle {
|
|
transform: Transform::from_xyz(-1.0, 1.0, 1.0)
|
|
.looking_at(Vec3::new(-1.0, 1.0, 0.0), Vec3::Y),
|
|
..default()
|
|
})
|
|
.insert(CameraController::default());
|
|
|
|
for z_i32 in -spawn_plane_depth as i32..=0 {
|
|
commands.spawn_bundle(PbrBundle {
|
|
mesh: sphere_handle.clone(),
|
|
material: white_handle.clone(),
|
|
transform: Transform::from_xyz(0.0, spawn_height, z_i32 as f32),
|
|
..default()
|
|
});
|
|
}
|
|
|
|
// ground plane
|
|
commands.spawn_bundle(PbrBundle {
|
|
mesh: meshes.add(Mesh::from(shape::Plane {
|
|
size: 2.0 * spawn_plane_depth,
|
|
})),
|
|
material: white_handle,
|
|
..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 adjust_point_light_biases(input: Res<Input<KeyCode>>, mut query: Query<&mut PointLight>) {
|
|
let depth_bias_step_size = 0.01;
|
|
let normal_bias_step_size = 0.1;
|
|
for mut light in query.iter_mut() {
|
|
if input.just_pressed(KeyCode::Key1) {
|
|
light.shadow_depth_bias -= depth_bias_step_size;
|
|
println!("PointLight shadow_depth_bias: {}", light.shadow_depth_bias);
|
|
}
|
|
if input.just_pressed(KeyCode::Key2) {
|
|
light.shadow_depth_bias += depth_bias_step_size;
|
|
println!("PointLight shadow_depth_bias: {}", light.shadow_depth_bias);
|
|
}
|
|
if input.just_pressed(KeyCode::Key3) {
|
|
light.shadow_normal_bias -= normal_bias_step_size;
|
|
println!(
|
|
"PointLight shadow_normal_bias: {}",
|
|
light.shadow_normal_bias
|
|
);
|
|
}
|
|
if input.just_pressed(KeyCode::Key4) {
|
|
light.shadow_normal_bias += normal_bias_step_size;
|
|
println!(
|
|
"PointLight shadow_normal_bias: {}",
|
|
light.shadow_normal_bias
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn adjust_directional_light_biases(
|
|
input: Res<Input<KeyCode>>,
|
|
mut query: Query<&mut DirectionalLight>,
|
|
) {
|
|
let depth_bias_step_size = 0.01;
|
|
let normal_bias_step_size = 0.1;
|
|
for mut light in query.iter_mut() {
|
|
if input.just_pressed(KeyCode::Key5) {
|
|
light.shadow_depth_bias -= depth_bias_step_size;
|
|
println!(
|
|
"DirectionalLight shadow_depth_bias: {}",
|
|
light.shadow_depth_bias
|
|
);
|
|
}
|
|
if input.just_pressed(KeyCode::Key6) {
|
|
light.shadow_depth_bias += depth_bias_step_size;
|
|
println!(
|
|
"DirectionalLight shadow_depth_bias: {}",
|
|
light.shadow_depth_bias
|
|
);
|
|
}
|
|
if input.just_pressed(KeyCode::Key7) {
|
|
light.shadow_normal_bias -= normal_bias_step_size;
|
|
println!(
|
|
"DirectionalLight shadow_normal_bias: {}",
|
|
light.shadow_normal_bias
|
|
);
|
|
}
|
|
if input.just_pressed(KeyCode::Key8) {
|
|
light.shadow_normal_bias += normal_bias_step_size;
|
|
println!(
|
|
"DirectionalLight shadow_normal_bias: {}",
|
|
light.shadow_normal_bias
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
struct CameraController {
|
|
pub enabled: bool,
|
|
pub sensitivity: f32,
|
|
pub key_forward: KeyCode,
|
|
pub key_back: KeyCode,
|
|
pub key_left: KeyCode,
|
|
pub key_right: KeyCode,
|
|
pub key_up: KeyCode,
|
|
pub key_down: KeyCode,
|
|
pub key_run: KeyCode,
|
|
pub walk_speed: f32,
|
|
pub run_speed: f32,
|
|
pub friction: f32,
|
|
pub pitch: f32,
|
|
pub yaw: f32,
|
|
pub velocity: Vec3,
|
|
}
|
|
|
|
impl Default for CameraController {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
sensitivity: 0.5,
|
|
key_forward: KeyCode::W,
|
|
key_back: KeyCode::S,
|
|
key_left: KeyCode::A,
|
|
key_right: KeyCode::D,
|
|
key_up: KeyCode::E,
|
|
key_down: KeyCode::Q,
|
|
key_run: KeyCode::LShift,
|
|
walk_speed: 10.0,
|
|
run_speed: 30.0,
|
|
friction: 0.5,
|
|
pitch: 0.0,
|
|
yaw: 0.0,
|
|
velocity: Vec3::ZERO,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn camera_controller(
|
|
time: Res<Time>,
|
|
mut mouse_events: EventReader<MouseMotion>,
|
|
key_input: Res<Input<KeyCode>>,
|
|
mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
|
|
) {
|
|
let dt = time.delta_seconds();
|
|
|
|
// Handle mouse input
|
|
let mut mouse_delta = Vec2::ZERO;
|
|
for mouse_event in mouse_events.iter() {
|
|
mouse_delta += mouse_event.delta;
|
|
}
|
|
|
|
for (mut transform, mut options) in query.iter_mut() {
|
|
if !options.enabled {
|
|
continue;
|
|
}
|
|
|
|
// Handle key input
|
|
let mut axis_input = Vec3::ZERO;
|
|
if key_input.pressed(options.key_forward) {
|
|
axis_input.z += 1.0;
|
|
}
|
|
if key_input.pressed(options.key_back) {
|
|
axis_input.z -= 1.0;
|
|
}
|
|
if key_input.pressed(options.key_right) {
|
|
axis_input.x += 1.0;
|
|
}
|
|
if key_input.pressed(options.key_left) {
|
|
axis_input.x -= 1.0;
|
|
}
|
|
if key_input.pressed(options.key_up) {
|
|
axis_input.y += 1.0;
|
|
}
|
|
if key_input.pressed(options.key_down) {
|
|
axis_input.y -= 1.0;
|
|
}
|
|
|
|
// Apply movement update
|
|
if axis_input != Vec3::ZERO {
|
|
let max_speed = if key_input.pressed(options.key_run) {
|
|
options.run_speed
|
|
} else {
|
|
options.walk_speed
|
|
};
|
|
options.velocity = axis_input.normalize() * max_speed;
|
|
} else {
|
|
let friction = options.friction.clamp(0.0, 1.0);
|
|
options.velocity *= 1.0 - friction;
|
|
if options.velocity.length_squared() < 1e-6 {
|
|
options.velocity = Vec3::ZERO;
|
|
}
|
|
}
|
|
let forward = transform.forward();
|
|
let right = transform.right();
|
|
transform.translation += options.velocity.x * dt * right
|
|
+ options.velocity.y * dt * Vec3::Y
|
|
+ options.velocity.z * dt * forward;
|
|
|
|
if mouse_delta != Vec2::ZERO {
|
|
// Apply look update
|
|
let (pitch, yaw) = (
|
|
(options.pitch - mouse_delta.y * 0.5 * options.sensitivity * dt).clamp(
|
|
-0.99 * std::f32::consts::FRAC_PI_2,
|
|
0.99 * std::f32::consts::FRAC_PI_2,
|
|
),
|
|
options.yaw - mouse_delta.x * options.sensitivity * dt,
|
|
);
|
|
transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, yaw, pitch);
|
|
options.pitch = pitch;
|
|
options.yaw = yaw;
|
|
}
|
|
}
|
|
}
|