render: shadow maps and PCF for spot lights
This commit is contained in:
parent
fefcf58765
commit
8c1738334c
|
@ -5,10 +5,10 @@ use lyra_engine::{
|
|||
Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource,
|
||||
InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput,
|
||||
},
|
||||
math::{self, Quat, Transform, Vec3},
|
||||
math::{self, Angle, Quat, Transform, Vec3},
|
||||
render::{
|
||||
graph::{ShadowCasterSettings, ShadowFilteringMode},
|
||||
light::{directional::DirectionalLight, PointLight},
|
||||
light::{directional::DirectionalLight, PointLight, SpotLight},
|
||||
},
|
||||
scene::{
|
||||
CameraComponent, FreeFlyCamera, FreeFlyCameraPlugin, WorldTransform,
|
||||
|
@ -189,7 +189,7 @@ fn setup_scene_plugin(game: &mut Game) {
|
|||
light_tran,
|
||||
));
|
||||
|
||||
world.spawn((
|
||||
/* world.spawn((
|
||||
cube_mesh.clone(),
|
||||
PointLight {
|
||||
enabled: true,
|
||||
|
@ -207,6 +207,33 @@ fn setup_scene_plugin(game: &mut Game) {
|
|||
Quat::IDENTITY,
|
||||
Vec3::new(0.5, 0.5, 0.5),
|
||||
),
|
||||
)); */
|
||||
|
||||
let t = Transform::new(
|
||||
Vec3::new(4.0 - 1.43, -13.0, 0.0),
|
||||
//Vec3::new(-5.0, 1.0, -0.28),
|
||||
//Vec3::new(-10.0, 0.94, -0.28),
|
||||
|
||||
Quat::from_euler(math::EulerRot::XYZ, 0.0, math::Angle::Degrees(-45.0).to_radians(), 0.0),
|
||||
Vec3::new(0.15, 0.15, 0.15),
|
||||
);
|
||||
|
||||
world.spawn((
|
||||
SpotLight {
|
||||
enabled: true,
|
||||
color: Vec3::new(1.0, 0.0, 0.0),
|
||||
intensity: 3.0,
|
||||
range: 4.5,
|
||||
//cutoff: math::Angle::Degrees(45.0),
|
||||
..Default::default()
|
||||
},
|
||||
/* ShadowCasterSettings {
|
||||
filtering_mode: ShadowFilteringMode::Pcf,
|
||||
..Default::default()
|
||||
}, */
|
||||
WorldTransform::from(t),
|
||||
t,
|
||||
//cube_mesh.clone(),
|
||||
));
|
||||
|
||||
/* world.spawn((
|
||||
|
@ -224,14 +251,13 @@ fn setup_scene_plugin(game: &mut Game) {
|
|||
|
||||
let mut camera = CameraComponent::new_3d();
|
||||
//camera.transform.translation += math::Vec3::new(0.0, 2.0, 10.5);
|
||||
/* camera.transform.translation = math::Vec3::new(-3.0, -8.0, -3.0);
|
||||
camera.transform.translation = math::Vec3::new(-1.0, -10.0, -1.5);
|
||||
camera.transform.rotate_x(math::Angle::Degrees(-27.0));
|
||||
camera.transform.rotate_y(math::Angle::Degrees(-55.0)); */
|
||||
camera.transform.rotate_y(math::Angle::Degrees(-90.0));
|
||||
|
||||
camera.transform.translation = math::Vec3::new(15.0, -8.0, 1.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));
|
||||
camera.transform.rotate_y(math::Angle::Degrees(90.0));
|
||||
camera.transform.rotate_y(math::Angle::Degrees(90.0)); */
|
||||
|
||||
world.spawn((camera, FreeFlyCamera::default()));
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use wgpu::util::DeviceExt;
|
|||
|
||||
use crate::render::{
|
||||
graph::{Node, NodeDesc, NodeType, SlotAttribute, SlotValue},
|
||||
light::{directional::DirectionalLight, LightType, PointLight},
|
||||
light::{directional::DirectionalLight, LightType, PointLight, SpotLight},
|
||||
resource::{FragmentState, RenderPipeline, RenderPipelineDescriptor, Shader, VertexState},
|
||||
transform_buffer_storage::TransformBuffers,
|
||||
vertex::Vertex,
|
||||
|
@ -186,6 +186,7 @@ impl ShadowMapsPass {
|
|||
light_type: LightType,
|
||||
entity: Entity,
|
||||
light_pos: Transform,
|
||||
light_half_outer_angle: Option<Angle>,
|
||||
are_settings_custom: bool,
|
||||
shadow_settings: ShadowCasterSettings,
|
||||
) -> LightDepthMap {
|
||||
|
@ -200,17 +201,6 @@ impl ShadowMapsPass {
|
|||
let has_shadow_settings = if are_settings_custom {
|
||||
1
|
||||
} 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 {
|
||||
LightType::Directional => {
|
||||
|
@ -265,7 +255,49 @@ impl ShadowMapsPass {
|
|||
indices[0] = uniform_index;
|
||||
(atlas_index, indices)
|
||||
}
|
||||
LightType::Spotlight => todo!(),
|
||||
LightType::Spotlight => {
|
||||
// allocate a single frame in the shadow map atlas
|
||||
let atlas_index = atlas
|
||||
.pack(SHADOW_SIZE.x as _, SHADOW_SIZE.y as _)
|
||||
.expect("failed to pack new shadow map into texture atlas");
|
||||
let atlas_frame = atlas.texture_frame(atlas_index).expect("Frame missing");
|
||||
|
||||
let aspect = SHADOW_SIZE.x as f32 / SHADOW_SIZE.y as f32;
|
||||
let projection = glam::Mat4::perspective_rh(
|
||||
//Angle::Degrees(90.0).to_radians(),
|
||||
(light_half_outer_angle.unwrap() * 2.0).to_radians(),
|
||||
aspect,
|
||||
shadow_settings.near_plane,
|
||||
shadow_settings.far_plane,
|
||||
);
|
||||
|
||||
let light_trans = light_pos.translation;
|
||||
let forward = light_pos.forward();
|
||||
let up = light_pos.up();
|
||||
let view = glam::Mat4::look_to_rh(light_trans, forward, up);
|
||||
|
||||
let light_proj = projection * view;
|
||||
|
||||
let u = LightShadowUniform {
|
||||
space_mat: light_proj,
|
||||
atlas_frame,
|
||||
near_plane: shadow_settings.near_plane,
|
||||
far_plane: shadow_settings.far_plane,
|
||||
light_size_uv: 0.0,
|
||||
_padding1: 0,
|
||||
light_pos: light_pos.translation,
|
||||
has_shadow_settings,
|
||||
pcf_samples_num: u.pcf_samples_num,
|
||||
pcss_blocker_search_samples: u.pcss_blocker_search_samples,
|
||||
constant_depth_bias: DEFAULT_CONSTANT_DEPTH_BIAS * shadow_settings.constant_depth_bias_scale,
|
||||
_padding2: 0,
|
||||
};
|
||||
|
||||
let uniform_index = self.light_uniforms_buffer.insert(queue, &u);
|
||||
let mut indices = [0; 6];
|
||||
indices[0] = uniform_index;
|
||||
(atlas_index, indices)
|
||||
},
|
||||
LightType::Point => {
|
||||
let aspect = SHADOW_SIZE.x as f32 / SHADOW_SIZE.y as f32;
|
||||
let projection = glam::Mat4::perspective_rh(
|
||||
|
@ -626,6 +658,31 @@ impl Node for ShadowMapsPass {
|
|||
LightType::Directional,
|
||||
entity,
|
||||
*pos,
|
||||
None,
|
||||
custom_settings,
|
||||
shadow_settings,
|
||||
);
|
||||
index_components_queue.push_back((entity, atlas_index));
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
);
|
||||
|
@ -649,6 +706,7 @@ impl Node for ShadowMapsPass {
|
|||
LightType::Point,
|
||||
entity,
|
||||
*pos,
|
||||
None,
|
||||
custom_settings,
|
||||
shadow_settings,
|
||||
);
|
||||
|
@ -786,7 +844,7 @@ impl Node for ShadowMapsPass {
|
|||
&frame,
|
||||
light_depth_map.uniform_index[0] as _,
|
||||
);
|
||||
}
|
||||
},
|
||||
LightType::Point => {
|
||||
pass.set_pipeline(&point_light_pipeline);
|
||||
|
||||
|
@ -806,8 +864,25 @@ impl Node for ShadowMapsPass {
|
|||
ui as _,
|
||||
);
|
||||
}
|
||||
},
|
||||
LightType::Spotlight => {
|
||||
pass.set_pipeline(&pipeline);
|
||||
//pass.set_pipeline(&point_light_pipeline);
|
||||
|
||||
let frame = atlas
|
||||
.texture_frame(light_depth_map.atlas_index)
|
||||
.expect("missing atlas frame for light");
|
||||
|
||||
light_shadow_pass_impl(
|
||||
&mut pass,
|
||||
&self.uniforms_bg,
|
||||
&render_meshes,
|
||||
&mesh_buffers,
|
||||
&transforms,
|
||||
&frame,
|
||||
light_depth_map.uniform_index[0] as _,
|
||||
);
|
||||
}
|
||||
LightType::Spotlight => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -976,35 +1051,17 @@ pub enum ShadowFilteringMode {
|
|||
None,
|
||||
/// Uses hardware features for 2x2 PCF.
|
||||
Pcf2x2,
|
||||
Pcf,
|
||||
#[default]
|
||||
Pcf,
|
||||
/// Percentage-Closer Soft Shadows
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/* #[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 PCSS_SAMPLES_NUM_MAX: u32 = 128;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ pub struct SpotLight {
|
|||
pub range: f32,
|
||||
pub intensity: f32,
|
||||
pub smoothness: f32,
|
||||
/// Cutoff angle that specifies the light radius.
|
||||
/// This is half of the light's FOV.
|
||||
pub cutoff: math::Angle,
|
||||
pub outer_cutoff: math::Angle,
|
||||
}
|
||||
|
|
|
@ -182,7 +182,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||
|
||||
if (light.light_ty == LIGHT_TY_DIRECTIONAL) {
|
||||
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);
|
||||
light_res += blinn_phong_dir_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
||||
|
@ -190,7 +189,8 @@ 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);
|
||||
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) {
|
||||
light_res += blinn_phong_spot_light(in.world_position, in.world_normal, light, u_material, specular_color);
|
||||
let shadow = calc_shadow_spot_light(in.world_position, in.world_normal, light_dir, light);
|
||||
light_res += blinn_phong_spot_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,12 +293,12 @@ fn calc_shadow_dir_light(world_pos: vec3<f32>, world_normal: vec3<f32>, light_di
|
|||
}
|
||||
// PCSS
|
||||
else if pcf_samples_num > 0u && pcss_blocker_search_samples > 0u {
|
||||
shadow = pcss_dir_light(xy_remapped, current_depth, map_data);
|
||||
shadow = pcss_dir_light(xy_remapped, current_depth, i32(pcss_blocker_search_samples), i32(pcf_samples_num), map_data);
|
||||
}
|
||||
// only PCF
|
||||
else if pcf_samples_num > 0u {
|
||||
let texel_size = 1.0 / f32(map_data.atlas_frame.width);
|
||||
shadow = pcf_dir_light(xy_remapped, current_depth, map_data, texel_size);
|
||||
shadow = pcf_dir_light(xy_remapped, current_depth, map_data, i32(pcf_samples_num), texel_size);
|
||||
}
|
||||
// no filtering
|
||||
else {
|
||||
|
@ -352,13 +352,13 @@ fn to_atlas_frame_coords(shadow_u: LightShadowMapUniform, coords: vec2<f32>, saf
|
|||
}
|
||||
|
||||
/// Find the average blocker distance for a directiona llight
|
||||
fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, bias: f32, shadow_u: LightShadowMapUniform) -> vec2<f32> {
|
||||
fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, search_samples: i32, 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);
|
||||
|
||||
var blockers = 0;
|
||||
var avg_dist = 0.0;
|
||||
let samples = i32(u_shadow_settings.pcss_blocker_search_samples);
|
||||
for (var i = 0; i < samples; i++) {
|
||||
//let samples = i32(u_shadow_settings.pcss_blocker_search_samples);
|
||||
for (var i = 0; i < search_samples; i++) {
|
||||
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 z = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, new_coords, 0.0);
|
||||
|
@ -373,8 +373,8 @@ fn find_blocker_distance_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, b
|
|||
return vec2<f32>(avg_dist / b, b);
|
||||
}
|
||||
|
||||
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, receiver_depth, 0.0, shadow_u);
|
||||
fn pcss_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, pcss_blocker_samples: i32, pcf_samples_num: i32, shadow_u: LightShadowMapUniform) -> f32 {
|
||||
let blocker_search = find_blocker_distance_dir_light(tex_coords, pcss_blocker_samples, receiver_depth, 0.0, shadow_u);
|
||||
|
||||
// If no blockers were found, exit now to save in filtering
|
||||
if blocker_search.y == 0.0 {
|
||||
|
@ -387,13 +387,12 @@ fn pcss_dir_light(tex_coords: vec2<f32>, receiver_depth: f32, shadow_u: LightSha
|
|||
|
||||
// PCF
|
||||
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, uv_radius);
|
||||
return pcf_dir_light(tex_coords, receiver_depth, shadow_u, pcf_samples_num, uv_radius);
|
||||
}
|
||||
|
||||
/// Calculate the shadow coefficient using PCF of a directional light
|
||||
fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, uv_radius: f32) -> f32 {
|
||||
fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, samples_num: i32, uv_radius: f32) -> f32 {
|
||||
var shadow = 0.0;
|
||||
let samples_num = i32(u_shadow_settings.pcf_samples_num);
|
||||
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);
|
||||
|
@ -440,15 +439,10 @@ 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);
|
||||
shadow = textureSampleCompareLevel(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, region_coords, current_depth);
|
||||
}
|
||||
// PCSS
|
||||
else if pcf_samples_num > 0u && pcss_blocker_search_samples > 0u {
|
||||
shadow = pcss_dir_light(coords_2d, current_depth, u);
|
||||
}
|
||||
// only PCF
|
||||
// only PCF, PCSS is not supported so no need to check for it
|
||||
else if pcf_samples_num > 0u {
|
||||
let texel_size = 1.0 / f32(u.atlas_frame.width);
|
||||
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);
|
||||
shadow = pcf_point_light(frag_to_light, current_depth, uniforms, pcf_samples_num, texel_size);
|
||||
}
|
||||
// no filtering
|
||||
else {
|
||||
|
@ -482,11 +476,11 @@ fn pcf_point_light(tex_coords: vec3<f32>, test_depth: f32, shadow_us: array<Ligh
|
|||
return saturate(shadow);
|
||||
}
|
||||
|
||||
/*fn pcf_point_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMapUniform, samples_num: u32, uv_radius: f32) -> f32 {
|
||||
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 < i32(samples_num); i++) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
@ -494,7 +488,57 @@ fn pcf_point_light(tex_coords: vec3<f32>, test_depth: f32, shadow_us: array<Ligh
|
|||
|
||||
// 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 frag_pos_light_space = map_data.light_space_matrix * vec4<f32>(world_pos, 1.0);
|
||||
|
||||
var proj_coords = frag_pos_light_space.xyz / frag_pos_light_space.w;
|
||||
// for some reason the y component is flipped after transforming
|
||||
proj_coords.y = -proj_coords.y;
|
||||
|
||||
// Remap xy to [0.0, 1.0]
|
||||
let xy_remapped = proj_coords.xy * 0.5 + 0.5;
|
||||
|
||||
// use a bias to avoid shadow acne
|
||||
let current_depth = proj_coords.z - map_data.constant_depth_bias;
|
||||
|
||||
// get settings
|
||||
let settings = get_shadow_settings(map_data);
|
||||
let pcf_samples_num = settings.x;
|
||||
let pcss_blocker_search_samples = settings.y;
|
||||
|
||||
var shadow = 0.0;
|
||||
// hardware 2x2 PCF via camparison sampler
|
||||
if pcf_samples_num == 2u {
|
||||
let region_coords = to_atlas_frame_coords(map_data, xy_remapped, false);
|
||||
shadow = textureSampleCompareLevel(t_shadow_maps_atlas, s_shadow_maps_atlas_compare, region_coords, current_depth);
|
||||
}
|
||||
// only PCF is supported for spot lights
|
||||
else if pcf_samples_num > 0u {
|
||||
let texel_size = 1.0 / f32(map_data.atlas_frame.width);
|
||||
shadow = pcf_spot_light(xy_remapped, current_depth, map_data, i32(pcf_samples_num), texel_size);
|
||||
}
|
||||
// no filtering
|
||||
else {
|
||||
let region_coords = to_atlas_frame_coords(map_data, xy_remapped, false);
|
||||
let closest_depth = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, region_coords, 0.0);
|
||||
shadow = select(1.0, 0.0, current_depth > closest_depth);
|
||||
}
|
||||
|
||||
// dont cast shadows outside the light's far plane
|
||||
if (proj_coords.z > 1.0) {
|
||||
shadow = 1.0;
|
||||
}
|
||||
|
||||
// dont cast shadows if the texture coords would go past the shadow maps
|
||||
if (xy_remapped.x > 1.0 || xy_remapped.x < 0.0 || xy_remapped.y > 1.0 || xy_remapped.y < 0.0) {
|
||||
shadow = 1.0;
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
||||
let tile_index_float: vec2<f32> = in.clip_position.xy / 16.0;
|
||||
|
@ -574,7 +618,7 @@ fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_li
|
|||
return (shadow * (ambient_color + diffuse_color + specular_color)) * point_light.intensity;
|
||||
}
|
||||
|
||||
fn blinn_phong_spot_light(world_pos: vec3<f32>, world_norm: vec3<f32>, spot_light: Light, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||
fn blinn_phong_spot_light(world_pos: vec3<f32>, world_norm: vec3<f32>, spot_light: Light, material: Material, specular_factor: vec3<f32>, shadow: f32) -> vec3<f32> {
|
||||
let light_color = spot_light.color;
|
||||
let light_pos = spot_light.position;
|
||||
let camera_view_pos = u_camera.position;
|
||||
|
@ -615,7 +659,8 @@ fn blinn_phong_spot_light(world_pos: vec3<f32>, world_norm: vec3<f32>, spot_ligh
|
|||
//// 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));
|
||||
}
|
||||
|
||||
fn calc_attenuation(light: Light, distance: f32) -> f32 {
|
||||
|
|
|
@ -24,15 +24,10 @@ struct LightShadowMapUniform {
|
|||
|
||||
@group(0) @binding(0)
|
||||
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)
|
||||
var<uniform> u_model_transform_data: TransformData;
|
||||
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position)
|
||||
clip_position: vec4<f32>,
|
||||
|
|
|
@ -10,7 +10,7 @@ pub fn radians_to_degrees(radians: f32) -> f32 {
|
|||
radians * 180.0 / PI
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Angle {
|
||||
Degrees(f32),
|
||||
Radians(f32),
|
||||
|
@ -68,4 +68,18 @@ impl std::ops::SubAssign for Angle {
|
|||
Angle::Radians(r) => *r -= rhs.to_radians(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Angle {
|
||||
type Output = Angle;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Angle::Radians(self.to_radians() * rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::MulAssign<f32> for Angle {
|
||||
fn mul_assign(&mut self, rhs: f32) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue