mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
bevy_pbr2: Add support for configurable shadow map sizes (#2700)
# Objective Add support for configurable shadow map sizes ## Solution - Add `DirectionalLightShadowMap` and `PointLightShadowMap` resources, which just have size members, to the app world, and add `Extracted*` counterparts to the render world - Use the configured sizes when rendering shadow maps - Default sizes remain the same - 4096 for directional light shadow maps, 1024 for point light shadow maps (which are cube maps so 6 faces at 1024x1024 per light)
This commit is contained in:
parent
9898469e9e
commit
f368bf7fc7
3 changed files with 60 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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};
|
||||
|
@ -34,6 +37,8 @@ pub struct ExtractedPointLight {
|
|||
shadow_normal_bias: f32,
|
||||
}
|
||||
|
||||
pub type ExtractedPointLightShadowMap = PointLightShadowMap;
|
||||
|
||||
pub struct ExtractedDirectionalLight {
|
||||
color: Color,
|
||||
illuminance: f32,
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -222,6 +221,8 @@ 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)>,
|
||||
) {
|
||||
|
@ -229,6 +230,10 @@ pub fn extract_lights(
|
|||
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
|
||||
|
@ -236,7 +241,7 @@ pub fn extract_lights(
|
|||
// 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,
|
||||
|
@ -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 {
|
||||
|
@ -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>,
|
||||
) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue