Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale normal bias by texel size #26

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
15cdcd0
3d_scene_pipelined: Use a shallower directional light angle to provok…
superdump Jul 10, 2021
f7ac34d
cornell_box_pipelined: Remove bias tweaks
superdump Jul 10, 2021
eb99286
bevy_pbr2: Simplify shadow biases by moving them to linear depth
superdump Jul 10, 2021
f97942e
bevy_pbr2: Do not use DepthBiasState
superdump Jul 13, 2021
f53baab
bevy_pbr2: Do not use bilinear filtering for sampling depth textures
superdump Jul 13, 2021
f7315cc
pbr.wgsl: Remove unnecessary comment
superdump Jul 13, 2021
7df1bab
bevy_pbr2: Do manual shadow map depth comparisons for more flexibility
superdump Jul 13, 2021
0779593
examples: Add shadow_biases_pipelined example
superdump Jul 14, 2021
45f2d49
bevy_pbr2: Scale the point light normal bias by the shadow map texel …
superdump Jul 14, 2021
70910af
shadow_biases_pipelined: Add support for toggling directional / point…
superdump Jul 14, 2021
c78ea04
shadow_biases_pipelined: Cleanup
superdump Jul 14, 2021
0199071
bevy_pbr2: Scale the directional light normal bias by the shadow map …
superdump Jul 14, 2021
3cbbbcf
shadow_biases_pipelined: Fit the orthographic projection around the s…
superdump Jul 14, 2021
de3ead4
bevy_pbr2: Directional lights should have no shadows outside their pr…
superdump Jul 14, 2021
86fb4d2
bevy_pbr2: Fix the default directional light normal bias
superdump Jul 14, 2021
de5ca1a
Revert "bevy_pbr2: Do manual shadow map depth comparisons for more fl…
superdump Jul 14, 2021
8d12b50
shadow_biases_pipelined: Adjust directional light normal bias in 0.1 …
superdump Jul 14, 2021
ab1ef41
pbr.wgsl: Add a couple of clarifying comments
superdump Jul 15, 2021
b934f7b
Revert "bevy_pbr2: Do not use bilinear filtering for sampling depth t…
superdump Jul 17, 2021
c5a7e76
Merge branch 'pipelined-rendering' into scale-normal-bias-by-texel-size
superdump Jul 17, 2021
17e96ed
shadow_biases_pipelined: Print usage to terminal
superdump Jul 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ path = "examples/3d/pbr_pipelined.rs"
name = "render_to_texture"
path = "examples/3d/render_to_texture.rs"

[[example]]
name = "shadow_biases_pipelined"
path = "examples/3d/shadow_biases_pipelined.rs"

[[example]]
name = "spawner"
path = "examples/3d/spawner.rs"
Expand Down
334 changes: 334 additions & 0 deletions examples/3d/shadow_biases_pipelined.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
use bevy::{
core::Time,
ecs::prelude::*,
input::{mouse::MouseMotion, Input},
math::{EulerRot, Mat4, Quat, Vec2, Vec3},
pbr2::{
DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
StandardMaterial,
},
prelude::{App, Assets, KeyCode, Transform},
render2::{
camera::{Camera, OrthographicProjection, PerspectiveCameraBundle},
color::Color,
mesh::{shape, Mesh},
},
PipelinedDefaultPlugins,
};

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(PipelinedDefaultPlugins)
.add_startup_system(setup.system())
.add_system(adjust_point_light_biases.system())
.add_system(toggle_light.system())
.add_system(adjust_directional_light_biases.system())
.add_system(camera_controller.system())
.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()
}));

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,
..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: -0.35,
right: 500.35,
bottom: -0.1,
top: 5.0,
near: -5.0,
far: 5.0,
..Default::default()
},
shadow_depth_bias: 0.0,
shadow_normal_bias: 0.0,
..Default::default()
},
transform: Transform::from_matrix(light_transform),
..Default::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::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::default()
});
}

// ground plane
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane {
size: 2.0 * spawn_plane_depth,
})),
material: white_handle.clone(),
..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 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
);
}
}
}

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;
}
}
}
9 changes: 7 additions & 2 deletions pipelined/bevy_pbr2/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ pub struct PointLight {
pub range: f32,
pub radius: f32,
pub shadow_depth_bias: f32,
/// A bias applied along the direction of the fragment's surface normal. It is scaled to the
/// shadow map's texel size so that it can be small close to the camera and gets larger further
/// away.
pub shadow_normal_bias: f32,
}

Expand All @@ -26,7 +29,7 @@ impl Default for PointLight {

impl PointLight {
pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.02;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.02;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.5;
}

/// A Directional light.
Expand Down Expand Up @@ -61,6 +64,8 @@ pub struct DirectionalLight {
pub illuminance: f32,
pub shadow_projection: OrthographicProjection,
pub shadow_depth_bias: f32,
/// A bias applied along the direction of the fragment's surface normal. It is scaled to the
/// shadow map's texel size so that it is automatically adjusted to the orthographic projection.
pub shadow_normal_bias: f32,
}

Expand All @@ -87,7 +92,7 @@ impl Default for DirectionalLight {

impl DirectionalLight {
pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.02;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.02;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.6;
}

// Ambient light color.
Expand Down
Loading