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

[Merged by Bors] - bevy_pbr2: Add support for configurable shadow map sizes #2700

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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: 3 additions & 1 deletion pipelined/bevy_pbr2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub struct PbrPlugin;
impl Plugin for PbrPlugin {
fn build(&self, app: &mut App) {
app.add_plugin(StandardMaterialPlugin)
.init_resource::<AmbientLight>();
.init_resource::<AmbientLight>()
.init_resource::<DirectionalLightShadowMap>()
.init_resource::<PointLightShadowMap>();

let render_app = app.sub_app(RenderApp);
render_app
Expand Down
22 changes: 22 additions & 0 deletions pipelined/bevy_pbr2/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ impl PointLight {
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.5;
}

#[derive(Clone, Debug)]
pub struct PointLightShadowMap {
pub size: usize,
}

impl Default for PointLightShadowMap {
fn default() -> Self {
Self { size: 1024 }
}
}

/// A Directional light.
///
/// Directional lights don't exist in reality but they are a good
Expand Down Expand Up @@ -113,6 +124,17 @@ impl DirectionalLight {
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.6;
}

#[derive(Clone, Debug)]
pub struct DirectionalLightShadowMap {
pub size: usize,
}

impl Default for DirectionalLightShadowMap {
fn default() -> Self {
Self { size: 4096 }
}
}

/// Ambient light.
#[derive(Debug)]
pub struct AmbientLight {
Expand Down
54 changes: 35 additions & 19 deletions pipelined/bevy_pbr2/src/render/light.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{AmbientLight, DirectionalLight, ExtractedMeshes, MeshMeta, PbrShaders, PointLight};
use crate::{
AmbientLight, DirectionalLight, DirectionalLightShadowMap, ExtractedMeshes, MeshMeta,
PbrShaders, PointLight, PointLightShadowMap,
};
use bevy_core_pipeline::Transparent3dPhase;
use bevy_ecs::{prelude::*, system::SystemState};
use bevy_math::{const_vec3, Mat4, Vec3, Vec4};
Expand Down Expand Up @@ -34,6 +37,8 @@ pub struct ExtractedPointLight {
shadow_normal_bias: f32,
}

pub type ExtractedPointLightShadowMap = PointLightShadowMap;

pub struct ExtractedDirectionalLight {
color: Color,
illuminance: f32,
Expand All @@ -43,6 +48,8 @@ pub struct ExtractedDirectionalLight {
shadow_normal_bias: f32,
}

pub type ExtractedDirectionalLightShadowMap = DirectionalLightShadowMap;

#[repr(C)]
#[derive(Copy, Clone, AsStd140, Default, Debug)]
pub struct GpuPointLight {
Expand Down Expand Up @@ -81,16 +88,8 @@ pub struct GpuLights {
// NOTE: this must be kept in sync with the same constants in pbr.frag
pub const MAX_POINT_LIGHTS: usize = 10;
pub const MAX_DIRECTIONAL_LIGHTS: usize = 1;
pub const POINT_SHADOW_SIZE: Extent3d = Extent3d {
width: 1024,
height: 1024,
depth_or_array_layers: (6 * MAX_POINT_LIGHTS) as u32,
};
pub const DIRECTIONAL_SHADOW_SIZE: Extent3d = Extent3d {
width: 4096,
height: 4096,
depth_or_array_layers: MAX_DIRECTIONAL_LIGHTS as u32,
};
pub const POINT_SHADOW_LAYERS: u32 = (6 * MAX_POINT_LIGHTS) as u32;
pub const DIRECTIONAL_SHADOW_LAYERS: u32 = MAX_DIRECTIONAL_LIGHTS as u32;
pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float;

pub struct ShadowShaders {
Expand Down Expand Up @@ -222,21 +221,27 @@ impl FromWorld for ShadowShaders {
pub fn extract_lights(
mut commands: Commands,
ambient_light: Res<AmbientLight>,
point_light_shadow_map: Res<PointLightShadowMap>,
directional_light_shadow_map: Res<DirectionalLightShadowMap>,
point_lights: Query<(Entity, &PointLight, &GlobalTransform)>,
directional_lights: Query<(Entity, &DirectionalLight, &GlobalTransform)>,
) {
commands.insert_resource(ExtractedAmbientLight {
color: ambient_light.color,
brightness: ambient_light.brightness,
});
commands.insert_resource::<ExtractedPointLightShadowMap>(point_light_shadow_map.clone());
commands.insert_resource::<ExtractedDirectionalLightShadowMap>(
directional_light_shadow_map.clone(),
);
// This is the point light shadow map texel size for one face of the cube as a distance of 1.0
// world unit from the light.
// point_light_texel_size = 2.0 * 1.0 * tan(PI / 4.0) / cube face width in texels
// PI / 4.0 is half the cube face fov, tan(PI / 4.0) = 1.0, so this simplifies to:
// point_light_texel_size = 2.0 / cube face width in texels
// NOTE: When using various PCF kernel sizes, this will need to be adjusted, according to:
// https://catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-shadows/
let point_light_texel_size = 2.0 / POINT_SHADOW_SIZE.width as f32;
let point_light_texel_size = 2.0 / point_light_shadow_map.size as f32;
for (entity, point_light, transform) in point_lights.iter() {
commands.get_or_spawn(entity).insert(ExtractedPointLight {
color: point_light.color,
Expand Down Expand Up @@ -265,7 +270,8 @@ pub fn extract_lights(
directional_light.shadow_projection.top
- directional_light.shadow_projection.bottom,
);
let directional_light_texel_size = largest_dimension / DIRECTIONAL_SHADOW_SIZE.width as f32;
let directional_light_texel_size =
largest_dimension / directional_light_shadow_map.size as f32;
commands
.get_or_spawn(entity)
.insert(ExtractedDirectionalLight {
Expand Down Expand Up @@ -366,6 +372,8 @@ pub fn prepare_lights(
mut light_meta: ResMut<LightMeta>,
views: Query<Entity, With<RenderPhase<Transparent3dPhase>>>,
ambient_light: Res<ExtractedAmbientLight>,
point_light_shadow_map: Res<ExtractedPointLightShadowMap>,
directional_light_shadow_map: Res<ExtractedDirectionalLightShadowMap>,
point_lights: Query<&ExtractedPointLight>,
directional_lights: Query<&ExtractedDirectionalLight>,
) {
Expand All @@ -380,7 +388,11 @@ pub fn prepare_lights(
let point_light_depth_texture = texture_cache.get(
&render_device,
TextureDescriptor {
size: POINT_SHADOW_SIZE,
size: Extent3d {
width: point_light_shadow_map.size as u32,
height: point_light_shadow_map.size as u32,
depth_or_array_layers: POINT_SHADOW_LAYERS,
},
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
Expand All @@ -392,7 +404,11 @@ pub fn prepare_lights(
let directional_light_depth_texture = texture_cache.get(
&render_device,
TextureDescriptor {
size: DIRECTIONAL_SHADOW_SIZE,
size: Extent3d {
width: directional_light_shadow_map.size as u32,
height: directional_light_shadow_map.size as u32,
depth_or_array_layers: DIRECTIONAL_SHADOW_LAYERS,
},
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
Expand Down Expand Up @@ -451,8 +467,8 @@ pub fn prepare_lights(
),
},
ExtractedView {
width: POINT_SHADOW_SIZE.width,
height: POINT_SHADOW_SIZE.height,
width: point_light_shadow_map.size as u32,
height: point_light_shadow_map.size as u32,
transform: view_translation * view_rotation,
projection,
},
Expand Down Expand Up @@ -537,8 +553,8 @@ pub fn prepare_lights(
pass_name: format!("shadow pass directional light {}", i),
},
ExtractedView {
width: DIRECTIONAL_SHADOW_SIZE.width,
height: DIRECTIONAL_SHADOW_SIZE.height,
width: directional_light_shadow_map.size as u32,
height: directional_light_shadow_map.size as u32,
transform: GlobalTransform::from_matrix(view.inverse()),
projection,
},
Expand Down