Compare commits
2 Commits
8c1738334c
...
8545e7e27d
Author | SHA1 | Date |
---|---|---|
SeanOMik | 8545e7e27d | |
SeanOMik | a85178eeea |
|
@ -5,7 +5,7 @@ use lyra_engine::{
|
||||||
Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource,
|
Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource,
|
||||||
InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput,
|
InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput,
|
||||||
},
|
},
|
||||||
math::{self, Angle, Quat, Transform, Vec3},
|
math::{self, Quat, Transform, Vec3},
|
||||||
render::{
|
render::{
|
||||||
graph::{ShadowCasterSettings, ShadowFilteringMode},
|
graph::{ShadowCasterSettings, ShadowFilteringMode},
|
||||||
light::{directional::DirectionalLight, PointLight, SpotLight},
|
light::{directional::DirectionalLight, PointLight, SpotLight},
|
||||||
|
@ -184,6 +184,9 @@ fn setup_scene_plugin(game: &mut Game) {
|
||||||
},
|
},
|
||||||
ShadowCasterSettings {
|
ShadowCasterSettings {
|
||||||
filtering_mode: ShadowFilteringMode::Pcss,
|
filtering_mode: ShadowFilteringMode::Pcss,
|
||||||
|
pcf_samples_num: 64,
|
||||||
|
pcss_blocker_search_samples: 36,
|
||||||
|
constant_depth_bias_scale: 5.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
light_tran,
|
light_tran,
|
||||||
|
@ -235,29 +238,12 @@ fn setup_scene_plugin(game: &mut Game) {
|
||||||
t,
|
t,
|
||||||
//cube_mesh.clone(),
|
//cube_mesh.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
/* world.spawn((
|
|
||||||
//cube_mesh.clone(),
|
|
||||||
PointLight {
|
|
||||||
enabled: true,
|
|
||||||
color: Vec3::new(0.278, 0.984, 0.0),
|
|
||||||
intensity: 2.0,
|
|
||||||
range: 9.0,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Transform::from_xyz(-0.5, 2.0, -5.0),
|
|
||||||
)); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut camera = CameraComponent::new_3d();
|
let mut camera = CameraComponent::new_3d();
|
||||||
//camera.transform.translation += math::Vec3::new(0.0, 2.0, 10.5);
|
|
||||||
camera.transform.translation = math::Vec3::new(-1.0, -10.0, -1.5);
|
camera.transform.translation = math::Vec3::new(-1.0, -10.0, -1.5);
|
||||||
camera.transform.rotate_x(math::Angle::Degrees(-27.0));
|
camera.transform.rotate_x(math::Angle::Degrees(-27.0));
|
||||||
camera.transform.rotate_y(math::Angle::Degrees(-90.0));
|
camera.transform.rotate_y(math::Angle::Degrees(-90.0));
|
||||||
|
|
||||||
/* camera.transform.translation = math::Vec3::new(15.0, -8.0, 1.0);
|
|
||||||
camera.transform.rotate_x(math::Angle::Degrees(-27.0));
|
|
||||||
camera.transform.rotate_y(math::Angle::Degrees(90.0)); */
|
|
||||||
|
|
||||||
world.spawn((camera, FreeFlyCamera::default()));
|
world.spawn((camera, FreeFlyCamera::default()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,17 @@ impl ShadowMapsPass {
|
||||||
let has_shadow_settings = if are_settings_custom {
|
let has_shadow_settings = if are_settings_custom {
|
||||||
1
|
1
|
||||||
} else { 0 };
|
} else { 0 };
|
||||||
|
/* let (has_shadow_settings, pcf_samples_num, pcss_samples_num) = if are_settings_custom {
|
||||||
|
|
||||||
|
(1, u.pcf_samples_num, u.pcss_blocker_search_samples)
|
||||||
|
} else {
|
||||||
|
(0, , 0)
|
||||||
|
}; */
|
||||||
|
|
||||||
|
/* shadow_settings.map(|ss| {
|
||||||
|
let u = ShadowSettingsUniform::new(ss.filtering_mode, ss.pcf_samples_num, ss.pcss_blocker_search_samples);
|
||||||
|
(1, u.pcf_samples_num, u.pcss_blocker_search_samples)
|
||||||
|
}).unwrap_or((0, 0, 0)); */
|
||||||
|
|
||||||
let (start_atlas_idx, uniform_indices) = match light_type {
|
let (start_atlas_idx, uniform_indices) = match light_type {
|
||||||
LightType::Directional => {
|
LightType::Directional => {
|
||||||
|
@ -256,27 +267,36 @@ impl ShadowMapsPass {
|
||||||
(atlas_index, indices)
|
(atlas_index, indices)
|
||||||
}
|
}
|
||||||
LightType::Spotlight => {
|
LightType::Spotlight => {
|
||||||
// allocate a single frame in the shadow map atlas
|
let directional_size = SHADOW_SIZE * 4;
|
||||||
|
// directional lights require a single map, so allocate that in the atlas.
|
||||||
let atlas_index = atlas
|
let atlas_index = atlas
|
||||||
.pack(SHADOW_SIZE.x as _, SHADOW_SIZE.y as _)
|
.pack(directional_size.x as _, directional_size.y as _)
|
||||||
.expect("failed to pack new shadow map into texture atlas");
|
.expect("failed to pack new shadow map into texture atlas");
|
||||||
let atlas_frame = atlas.texture_frame(atlas_index).expect("Frame missing");
|
let atlas_frame = atlas.texture_frame(atlas_index).expect("Frame missing");
|
||||||
|
|
||||||
let aspect = SHADOW_SIZE.x as f32 / SHADOW_SIZE.y as f32;
|
let aspect = SHADOW_SIZE.x as f32 / SHADOW_SIZE.y as f32;
|
||||||
let projection = glam::Mat4::perspective_rh(
|
let projection = glam::Mat4::perspective_rh(
|
||||||
//Angle::Degrees(90.0).to_radians(),
|
|
||||||
(light_half_outer_angle.unwrap() * 2.0).to_radians(),
|
(light_half_outer_angle.unwrap() * 2.0).to_radians(),
|
||||||
aspect,
|
aspect,
|
||||||
shadow_settings.near_plane,
|
shadow_settings.near_plane,
|
||||||
shadow_settings.far_plane,
|
shadow_settings.far_plane,
|
||||||
);
|
);
|
||||||
|
|
||||||
let light_trans = light_pos.translation;
|
// honestly no clue why this works, but I got it from here and the results are good
|
||||||
let forward = light_pos.forward();
|
// https://github.com/asylum2010/Asylum_Tutorials/blob/423e5edfaee7b5ea450a450e65f2eabf641b2482/ShaderTutors/43_ShadowMapFiltering/main.cpp#L323
|
||||||
let up = light_pos.up();
|
/* let frustum_size = Vec2::new(0.5 * projection.col(0).x, 0.5 * projection.col(1).y);
|
||||||
let view = glam::Mat4::look_to_rh(light_trans, forward, up);
|
// maybe its better to make this a vec2 on the gpu?
|
||||||
|
let size_avg = (frustum_size.x + frustum_size.y) / 2.0;
|
||||||
|
let light_size_uv = 0.2 * size_avg; */
|
||||||
|
|
||||||
let light_proj = projection * view;
|
let light_trans = light_pos.translation;
|
||||||
|
let look_view = glam::Mat4::look_at_rh(
|
||||||
|
light_trans,
|
||||||
|
light_trans + glam::vec3(1.0, 0.0, 0.0),
|
||||||
|
glam::vec3(0.0, -1.0, 0.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
let light_proj = projection * look_view;
|
||||||
|
|
||||||
let u = LightShadowUniform {
|
let u = LightShadowUniform {
|
||||||
space_mat: light_proj,
|
space_mat: light_proj,
|
||||||
|
@ -666,30 +686,6 @@ impl Node for ShadowMapsPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (entity, pos, shadow_settings, spot) in world.view_iter::<(
|
|
||||||
Entities,
|
|
||||||
&Transform,
|
|
||||||
Option<&ShadowCasterSettings>,
|
|
||||||
&SpotLight,
|
|
||||||
)>() {
|
|
||||||
if !self.depth_maps.contains_key(&entity) {
|
|
||||||
let (custom_settings, shadow_settings) = shadow_settings
|
|
||||||
.map(|ss| (true, ss.clone()))
|
|
||||||
.unwrap_or((false, settings));
|
|
||||||
|
|
||||||
let atlas_index = self.create_depth_map(
|
|
||||||
&context.queue,
|
|
||||||
LightType::Spotlight,
|
|
||||||
entity,
|
|
||||||
*pos,
|
|
||||||
Some(spot.outer_cutoff),
|
|
||||||
custom_settings,
|
|
||||||
shadow_settings,
|
|
||||||
);
|
|
||||||
index_components_queue.push_back((entity, atlas_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (entity, pos, shadow_settings, _) in world.view_iter::<(
|
for (entity, pos, shadow_settings, _) in world.view_iter::<(
|
||||||
Entities,
|
Entities,
|
||||||
&Transform,
|
&Transform,
|
||||||
|
@ -714,6 +710,30 @@ impl Node for ShadowMapsPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (entity, pos, shadow_settings, spot) in world.view_iter::<(
|
||||||
|
Entities,
|
||||||
|
&Transform,
|
||||||
|
Option<&ShadowCasterSettings>,
|
||||||
|
&SpotLight,
|
||||||
|
)>() {
|
||||||
|
if !self.depth_maps.contains_key(&entity) {
|
||||||
|
let (custom_settings, shadow_settings) = shadow_settings
|
||||||
|
.map(|ss| (true, ss.clone()))
|
||||||
|
.unwrap_or((false, settings));
|
||||||
|
|
||||||
|
let atlas_index = self.create_depth_map(
|
||||||
|
&context.queue,
|
||||||
|
LightType::Spotlight,
|
||||||
|
entity,
|
||||||
|
*pos,
|
||||||
|
Some(spot.outer_cutoff),
|
||||||
|
custom_settings,
|
||||||
|
shadow_settings,
|
||||||
|
);
|
||||||
|
index_components_queue.push_back((entity, atlas_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// now consume from the queue adding the components to the entities
|
// now consume from the queue adding the components to the entities
|
||||||
while let Some((entity, depth)) = index_components_queue.pop_front() {
|
while let Some((entity, depth)) = index_components_queue.pop_front() {
|
||||||
world.insert(
|
world.insert(
|
||||||
|
@ -844,7 +864,7 @@ impl Node for ShadowMapsPass {
|
||||||
&frame,
|
&frame,
|
||||||
light_depth_map.uniform_index[0] as _,
|
light_depth_map.uniform_index[0] as _,
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
LightType::Point => {
|
LightType::Point => {
|
||||||
pass.set_pipeline(&point_light_pipeline);
|
pass.set_pipeline(&point_light_pipeline);
|
||||||
|
|
||||||
|
@ -864,10 +884,9 @@ impl Node for ShadowMapsPass {
|
||||||
ui as _,
|
ui as _,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
LightType::Spotlight => {
|
LightType::Spotlight => {
|
||||||
pass.set_pipeline(&pipeline);
|
pass.set_pipeline(&pipeline);
|
||||||
//pass.set_pipeline(&point_light_pipeline);
|
|
||||||
|
|
||||||
let frame = atlas
|
let frame = atlas
|
||||||
.texture_frame(light_depth_map.atlas_index)
|
.texture_frame(light_depth_map.atlas_index)
|
||||||
|
@ -882,7 +901,7 @@ impl Node for ShadowMapsPass {
|
||||||
&frame,
|
&frame,
|
||||||
light_depth_map.uniform_index[0] as _,
|
light_depth_map.uniform_index[0] as _,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1051,17 +1070,35 @@ pub enum ShadowFilteringMode {
|
||||||
None,
|
None,
|
||||||
/// Uses hardware features for 2x2 PCF.
|
/// Uses hardware features for 2x2 PCF.
|
||||||
Pcf2x2,
|
Pcf2x2,
|
||||||
#[default]
|
|
||||||
Pcf,
|
Pcf,
|
||||||
/// Percentage-Closer Soft Shadows
|
#[default]
|
||||||
/// https://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf
|
|
||||||
///
|
|
||||||
/// PCSS is only implemented for directional lights. Use PCF for point and spot lights instead.
|
|
||||||
/// PCSS is expensive per-frame, so it has not been implemented for them. If you use this for
|
|
||||||
/// point and/or spot lights, the renderer will fall back to PCF.
|
|
||||||
Pcss,
|
Pcss,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ShadowSettings {
|
||||||
|
pub filtering_mode: ShadowFilteringMode,
|
||||||
|
/// How many PCF filtering samples are used per dimension.
|
||||||
|
///
|
||||||
|
/// A value of 25 is common, this is maxed to 128.
|
||||||
|
pub pcf_samples_num: u32,
|
||||||
|
/// How many samples are used for the PCSS blocker search step.
|
||||||
|
///
|
||||||
|
/// Multiple samples are required to avoid holes int he penumbra due to missing blockers.
|
||||||
|
/// A value of 25 is common, this is maxed to 128.
|
||||||
|
pub pcss_blocker_search_samples: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ShadowSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
filtering_mode: ShadowFilteringMode::default(),
|
||||||
|
pcf_samples_num: 25,
|
||||||
|
pcss_blocker_search_samples: 25,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
const PCF_SAMPLES_NUM_MAX: u32 = 128;
|
const PCF_SAMPLES_NUM_MAX: u32 = 128;
|
||||||
const PCSS_SAMPLES_NUM_MAX: u32 = 128;
|
const PCSS_SAMPLES_NUM_MAX: u32 = 128;
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ pub struct SpotLight {
|
||||||
pub range: f32,
|
pub range: f32,
|
||||||
pub intensity: f32,
|
pub intensity: f32,
|
||||||
pub smoothness: f32,
|
pub smoothness: f32,
|
||||||
/// Cutoff angle that specifies the light radius.
|
|
||||||
/// This is half of the light's FOV.
|
|
||||||
pub cutoff: math::Angle,
|
pub cutoff: math::Angle,
|
||||||
pub outer_cutoff: math::Angle,
|
pub outer_cutoff: math::Angle,
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,6 +182,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
|
|
||||||
if (light.light_ty == LIGHT_TY_DIRECTIONAL) {
|
if (light.light_ty == LIGHT_TY_DIRECTIONAL) {
|
||||||
let shadow_u: LightShadowMapUniform = u_light_shadow[light.light_shadow_uniform_index[0]];
|
let shadow_u: LightShadowMapUniform = u_light_shadow[light.light_shadow_uniform_index[0]];
|
||||||
|
let frag_pos_light_space = shadow_u.light_space_matrix * vec4<f32>(in.world_position, 1.0);
|
||||||
|
|
||||||
let shadow = calc_shadow_dir_light(in.world_position, in.world_normal, light_dir, light);
|
let shadow = calc_shadow_dir_light(in.world_position, in.world_normal, light_dir, light);
|
||||||
light_res += blinn_phong_dir_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
light_res += blinn_phong_dir_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
||||||
|
@ -189,7 +190,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let shadow = calc_shadow_point_light(in.world_position, in.world_normal, light_dir, light, atlas_dimensions);
|
let shadow = calc_shadow_point_light(in.world_position, in.world_normal, light_dir, light, atlas_dimensions);
|
||||||
light_res += blinn_phong_point_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
light_res += blinn_phong_point_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
||||||
} else if (light.light_ty == LIGHT_TY_SPOT) {
|
} else if (light.light_ty == LIGHT_TY_SPOT) {
|
||||||
let shadow = calc_shadow_spot_light(in.world_position, in.world_normal, light_dir, light);
|
let shadow = calc_shadow_spot_light(in.world_position, in.world_normal, light_dir, light, atlas_dimensions);
|
||||||
light_res += blinn_phong_spot_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
light_res += blinn_phong_spot_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,12 +294,12 @@ fn calc_shadow_dir_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_di
|
||||||
}
|
}
|
||||||
// PCSS
|
// PCSS
|
||||||
else if pcf_samples_num > 0u && pcss_blocker_search_samples > 0u {
|
else if pcf_samples_num > 0u && pcss_blocker_search_samples > 0u {
|
||||||
shadow = pcss_dir_light(xy_remapped, current_depth, i32(pcss_blocker_search_samples), i32(pcf_samples_num), map_data);
|
shadow = pcss_dir_light(xy_remapped, current_depth, map_data);
|
||||||
}
|
}
|
||||||
// only PCF
|
// only PCF
|
||||||
else if pcf_samples_num > 0u {
|
else if pcf_samples_num > 0u {
|
||||||
let texel_size = 1.0 / f32(map_data.atlas_frame.width);
|
let texel_size = 1.0 / f32(map_data.atlas_frame.width);
|
||||||
shadow = pcf_dir_light(xy_remapped, current_depth, map_data, i32(pcf_samples_num), texel_size);
|
shadow = pcf_dir_light(xy_remapped, current_depth, map_data, texel_size);
|
||||||
}
|
}
|
||||||
// no filtering
|
// no filtering
|
||||||
else {
|
else {
|
||||||
|
@ -352,13 +353,13 @@ fn to_atlas_frame_coords(shadow_u: LightShadowMapUniform, coords: vec2<f32>, saf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the average blocker distance for a directiona llight
|
/// Find the average blocker distance for a directiona llight
|
||||||
fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, search_samples: i32, receiver_depth: f32, bias: f32, shadow_u: LightShadowMapUniform) -> vec2<f32> {
|
fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, bias: f32, shadow_u: LightShadowMapUniform) -> vec2<f32> {
|
||||||
let search_width = search_width(shadow_u.near_plane, shadow_u.light_size_uv, receiver_depth);
|
let search_width = search_width(shadow_u.near_plane, shadow_u.light_size_uv, receiver_depth);
|
||||||
|
|
||||||
var blockers = 0;
|
var blockers = 0;
|
||||||
var avg_dist = 0.0;
|
var avg_dist = 0.0;
|
||||||
//let samples = i32(u_shadow_settings.pcss_blocker_search_samples);
|
let samples = i32(u_shadow_settings.pcss_blocker_search_samples);
|
||||||
for (var i = 0; i < search_samples; i++) {
|
for (var i = 0; i < samples; i++) {
|
||||||
let offset_coords = tex_coords + u_pcss_poisson_disc[i] * search_width;
|
let offset_coords = tex_coords + u_pcss_poisson_disc[i] * search_width;
|
||||||
let new_coords = to_atlas_frame_coords(shadow_u, offset_coords, false);
|
let new_coords = to_atlas_frame_coords(shadow_u, offset_coords, false);
|
||||||
let z = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, new_coords, 0.0);
|
let z = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, new_coords, 0.0);
|
||||||
|
@ -373,8 +374,8 @@ fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, search_samples: i32, r
|
||||||
return vec2<f32>(avg_dist / b, b);
|
return vec2<f32>(avg_dist / b, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pcss_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, pcss_blocker_samples: i32, pcf_samples_num: i32, shadow_u: LightShadowMapUniform) -> f32 {
|
fn pcss_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, shadow_u: LightShadowMapUniform) -> f32 {
|
||||||
let blocker_search = find_blocker_distance_dir_light(tex_coords, pcss_blocker_samples, receiver_depth, 0.0, shadow_u);
|
let blocker_search = find_blocker_distance_dir_light(tex_coords, receiver_depth, 0.0, shadow_u);
|
||||||
|
|
||||||
// If no blockers were found, exit now to save in filtering
|
// If no blockers were found, exit now to save in filtering
|
||||||
if blocker_search.y == 0.0 {
|
if blocker_search.y == 0.0 {
|
||||||
|
@ -387,12 +388,13 @@ fn pcss_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, pcss_blocker_sampl
|
||||||
|
|
||||||
// PCF
|
// PCF
|
||||||
let uv_radius = penumbra_width * shadow_u.light_size_uv * shadow_u.near_plane / receiver_depth;
|
let uv_radius = penumbra_width * shadow_u.light_size_uv * shadow_u.near_plane / receiver_depth;
|
||||||
return pcf_dir_light(tex_coords, receiver_depth, shadow_u, pcf_samples_num, uv_radius);
|
return pcf_dir_light(tex_coords, receiver_depth, shadow_u, uv_radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the shadow coefficient using PCF of a directional light
|
/// Calculate the shadow coefficient using PCF of a directional light
|
||||||
fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, samples_num: i32, uv_radius: f32) -> f32 {
|
fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, uv_radius: f32) -> f32 {
|
||||||
var shadow = 0.0;
|
var shadow = 0.0;
|
||||||
|
let samples_num = i32(u_shadow_settings.pcf_samples_num);
|
||||||
for (var i = 0; i < samples_num; i++) {
|
for (var i = 0; i < samples_num; i++) {
|
||||||
let offset = tex_coords + u_pcf_poisson_disc[i] * uv_radius;
|
let offset = tex_coords + u_pcf_poisson_disc[i] * uv_radius;
|
||||||
let new_coords = to_atlas_frame_coords(shadow_u, offset, false);
|
let new_coords = to_atlas_frame_coords(shadow_u, offset, false);
|
||||||
|
@ -439,10 +441,15 @@ fn calc_shadow_point_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_
|
||||||
let region_coords = to_atlas_frame_coords(u, coords_2d, true);
|
let region_coords = to_atlas_frame_coords(u, coords_2d, true);
|
||||||
shadow = textureSampleCompareLevel(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, region_coords, current_depth);
|
shadow = textureSampleCompareLevel(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, region_coords, current_depth);
|
||||||
}
|
}
|
||||||
// only PCF, PCSS is not supported so no need to check for it
|
// PCSS
|
||||||
|
else if pcf_samples_num > 0u && pcss_blocker_search_samples > 0u {
|
||||||
|
shadow = pcss_dir_light(coords_2d, current_depth, u);
|
||||||
|
}
|
||||||
|
// only PCF
|
||||||
else if pcf_samples_num > 0u {
|
else if pcf_samples_num > 0u {
|
||||||
let texel_size = 1.0 / f32(u.atlas_frame.width);
|
let texel_size = 1.0 / f32(u.atlas_frame.width);
|
||||||
shadow = pcf_point_light(frag_to_light, current_depth, uniforms, pcf_samples_num, texel_size);
|
shadow = pcf_point_light(frag_to_light, current_depth, uniforms, pcf_samples_num, 0.007);
|
||||||
|
//shadow = pcf_point_light(coords_2d, current_depth, u, pcf_samples_num, texel_size);
|
||||||
}
|
}
|
||||||
// no filtering
|
// no filtering
|
||||||
else {
|
else {
|
||||||
|
@ -476,21 +483,7 @@ fn pcf_point_light(tex_coords: vec3<f32>, test_depth: f32, shadow_us: array<Ligh
|
||||||
return saturate(shadow);
|
return saturate(shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pcf_spot_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, samples_num: i32, uv_radius: f32) -> f32 {
|
fn calc_shadow_spot_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_dir: vec3<f32>, light: Light, atlas_dimensions: vec2<i32>) -> f32 {
|
||||||
var shadow = 0.0;
|
|
||||||
for (var i = 0; i < samples_num; i++) {
|
|
||||||
let offset = tex_coords + u_pcf_poisson_disc[i] * uv_radius;
|
|
||||||
let new_coords = to_atlas_frame_coords(shadow_u, offset, false);
|
|
||||||
|
|
||||||
shadow += textureSampleCompare(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, new_coords, test_depth);
|
|
||||||
}
|
|
||||||
shadow /= f32(samples_num);
|
|
||||||
|
|
||||||
// clamp shadow to [0; 1]
|
|
||||||
return saturate(shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calc_shadow_spot_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_dir: vec3<f32>, light: Light) -> f32 {
|
|
||||||
let map_data: LightShadowMapUniform = u_light_shadow[light.light_shadow_uniform_index[0]];
|
let map_data: LightShadowMapUniform = u_light_shadow[light.light_shadow_uniform_index[0]];
|
||||||
let frag_pos_light_space = map_data.light_space_matrix * vec4<f32>(world_pos, 1.0);
|
let frag_pos_light_space = map_data.light_space_matrix * vec4<f32>(world_pos, 1.0);
|
||||||
|
|
||||||
|
@ -540,6 +533,21 @@ fn calc_shadow_spot_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_d
|
||||||
return shadow;
|
return shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the shadow coefficient using PCF of a directional light
|
||||||
|
fn pcf_spot_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, samples_num: i32, uv_radius: f32) -> f32 {
|
||||||
|
var shadow = 0.0;
|
||||||
|
for (var i = 0; i < samples_num; i++) {
|
||||||
|
let offset = tex_coords + u_pcf_poisson_disc[i] * uv_radius;
|
||||||
|
let new_coords = to_atlas_frame_coords(shadow_u, offset, false);
|
||||||
|
|
||||||
|
shadow += textureSampleCompare(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, new_coords, test_depth);
|
||||||
|
}
|
||||||
|
shadow /= f32(samples_num);
|
||||||
|
|
||||||
|
// clamp shadow to [0; 1]
|
||||||
|
return saturate(shadow);
|
||||||
|
}
|
||||||
|
|
||||||
fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
||||||
let tile_index_float: vec2<f32> = in.clip_position.xy / 16.0;
|
let tile_index_float: vec2<f32> = in.clip_position.xy / 16.0;
|
||||||
let tile_index = vec2<u32>(floor(tile_index_float));
|
let tile_index = vec2<u32>(floor(tile_index_float));
|
||||||
|
@ -653,14 +661,13 @@ fn blinn_phong_spot_light(world_pos: vec3<f32>, world_norm: vec3<f32>, spot_ligh
|
||||||
let distance = length(light_pos - world_pos);
|
let distance = length(light_pos - world_pos);
|
||||||
let attenuation = calc_attenuation(spot_light, distance);
|
let attenuation = calc_attenuation(spot_light, distance);
|
||||||
|
|
||||||
ambient_color *= attenuation * spot_light.intensity * cone;
|
ambient_color *= attenuation * cone;
|
||||||
diffuse_color *= attenuation * spot_light.intensity * cone;
|
diffuse_color *= attenuation * cone;
|
||||||
specular_color *= attenuation * spot_light.intensity * cone;
|
specular_color *= attenuation * cone;
|
||||||
//// end of spot light attenuation ////
|
//// end of spot light attenuation ////
|
||||||
|
|
||||||
|
|
||||||
//return /*ambient_color +*/ diffuse_color + specular_color;
|
//return /*ambient_color +*/ diffuse_color + specular_color;
|
||||||
return (shadow * (diffuse_color + specular_color));
|
return (shadow * (diffuse_color + specular_color)) * spot_light.intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_attenuation(light: Light, distance: f32) -> f32 {
|
fn calc_attenuation(light: Light, distance: f32) -> f32 {
|
||||||
|
|
|
@ -24,10 +24,15 @@ struct LightShadowMapUniform {
|
||||||
|
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<storage, read> u_light_shadow: array<LightShadowMapUniform>;
|
var<storage, read> u_light_shadow: array<LightShadowMapUniform>;
|
||||||
|
/*@group(0) @binding(1)
|
||||||
|
var<uniform> u_light_pos: vec3<f32>;
|
||||||
|
@group(0) @binding(2)
|
||||||
|
var<uniform> u_light_far_plane: f32;*/
|
||||||
|
|
||||||
@group(1) @binding(0)
|
@group(1) @binding(0)
|
||||||
var<uniform> u_model_transform_data: TransformData;
|
var<uniform> u_model_transform_data: TransformData;
|
||||||
|
|
||||||
|
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position)
|
@builtin(position)
|
||||||
clip_position: vec4<f32>,
|
clip_position: vec4<f32>,
|
||||||
|
|
Loading…
Reference in New Issue