Implement Shadows #24
|
@ -115,9 +115,9 @@ impl Node for MeshPass {
|
|||
.expect("missing ShadowMapsPassSlots::ShadowAtlasSampler")
|
||||
.as_sampler()
|
||||
.unwrap();
|
||||
let atlas_size_buf = graph
|
||||
.slot_value(ShadowMapsPassSlots::ShadowAtlasSizeBuffer)
|
||||
.expect("missing ShadowMapsPassSlots::ShadowAtlasSizeBuffer")
|
||||
let shadow_settings_buf = graph
|
||||
.slot_value(ShadowMapsPassSlots::ShadowSettingsUniform)
|
||||
.expect("missing ShadowMapsPassSlots::ShadowSettingsUniform")
|
||||
.as_buffer()
|
||||
.unwrap();
|
||||
let light_uniform_buf = graph
|
||||
|
@ -183,7 +183,7 @@ impl Node for MeshPass {
|
|||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||
buffer: atlas_size_buf,
|
||||
buffer: shadow_settings_buf,
|
||||
offset: 0,
|
||||
size: None,
|
||||
}),
|
||||
|
|
|
@ -16,16 +16,12 @@ use tracing::warn;
|
|||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::render::{
|
||||
graph::{Node, NodeDesc, NodeType, SlotAttribute, SlotValue},
|
||||
light::{directional::DirectionalLight, LightType, PointLight},
|
||||
resource::{FragmentState, RenderPipeline, RenderPipelineDescriptor, Shader, VertexState},
|
||||
transform_buffer_storage::TransformBuffers,
|
||||
vertex::Vertex,
|
||||
AtlasFrame, GpuSlotBuffer, TextureAtlas,
|
||||
graph::{Node, NodeDesc, NodeType, SlotAttribute, SlotValue}, light::{directional::DirectionalLight, LightType, PointLight}, resource::{FragmentState, RenderPipeline, RenderPipelineDescriptor, Shader, VertexState}, transform_buffer_storage::TransformBuffers, vertex::Vertex, AtlasFrame, GpuSlotBuffer, TextureAtlas
|
||||
};
|
||||
|
||||
use super::{MeshBufferStorage, RenderAssets, RenderMeshes};
|
||||
|
||||
const PCF_SAMPLES_NUM: u32 = 4;
|
||||
const SHADOW_SIZE: glam::UVec2 = glam::uvec2(1024, 1024);
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||
|
@ -35,6 +31,7 @@ pub enum ShadowMapsPassSlots {
|
|||
ShadowAtlasSampler,
|
||||
ShadowAtlasSizeBuffer,
|
||||
ShadowLightUniformsBuffer,
|
||||
ShadowSettingsUniform,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||
|
@ -333,7 +330,7 @@ impl ShadowMapsPass {
|
|||
impl Node for ShadowMapsPass {
|
||||
fn desc(
|
||||
&mut self,
|
||||
_: &mut crate::render::graph::RenderGraph,
|
||||
graph: &mut crate::render::graph::RenderGraph,
|
||||
) -> crate::render::graph::NodeDesc {
|
||||
let mut node = NodeDesc::new(NodeType::Render, None, vec![]);
|
||||
|
||||
|
@ -371,6 +368,18 @@ impl Node for ShadowMapsPass {
|
|||
Some(SlotValue::Buffer(self.atlas_size_buffer.clone())),
|
||||
);
|
||||
|
||||
let settings_buffer = graph.device().create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("buffer_shadow_settings"),
|
||||
size: mem::size_of::<ShadowSettingsUniform>() as _,
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
node.add_buffer_slot(
|
||||
ShadowMapsPassSlots::ShadowSettingsUniform,
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(Arc::new(settings_buffer))),
|
||||
);
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
|
@ -380,6 +389,12 @@ impl Node for ShadowMapsPass {
|
|||
world: &mut lyra_ecs::World,
|
||||
context: &mut crate::render::graph::RenderGraphContext,
|
||||
) {
|
||||
{
|
||||
// TODO: only write buffer on changes to resource
|
||||
let shadow_settings = world.get_resource_or_default::<ShadowSettings>();
|
||||
context.queue_buffer_write_with(ShadowMapsPassSlots::ShadowSettingsUniform, 0, ShadowSettingsUniform::from(*shadow_settings));
|
||||
}
|
||||
|
||||
self.render_meshes = world.try_get_resource_data::<RenderMeshes>();
|
||||
self.transform_buffers = world.try_get_resource_data::<TransformBuffers>();
|
||||
self.mesh_buffers = world.try_get_resource_data::<RenderAssets<MeshBufferStorage>>();
|
||||
|
@ -691,3 +706,29 @@ impl LightShadowMapAtlas {
|
|||
self.0.write().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ShadowSettings {
|
||||
pub pcf_samples_num: u32,
|
||||
}
|
||||
|
||||
impl Default for ShadowSettings {
|
||||
fn default() -> Self {
|
||||
Self { pcf_samples_num: PCF_SAMPLES_NUM }
|
||||
}
|
||||
}
|
||||
|
||||
/// Uniform version of [`ShadowSettings`]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct ShadowSettingsUniform {
|
||||
pcf_samples_num: u32,
|
||||
}
|
||||
|
||||
impl From<ShadowSettings> for ShadowSettingsUniform {
|
||||
fn from(value: ShadowSettings) -> Self {
|
||||
Self {
|
||||
pcf_samples_num: value.pcf_samples_num,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,8 +8,6 @@ const LIGHT_TY_SPOT = 2u;
|
|||
|
||||
const ALPHA_CUTOFF = 0.1;
|
||||
|
||||
const SHADOW_MAP_PCF_SIZE = 4.0;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec3<f32>,
|
||||
@location(1) tex_coords: vec2<f32>,
|
||||
|
@ -122,6 +120,10 @@ struct LightShadowMapUniform {
|
|||
light_pos: vec3<f32>,
|
||||
}
|
||||
|
||||
struct ShadowSettingsUniform {
|
||||
pcf_samples_num: u32,
|
||||
}
|
||||
|
||||
@group(4) @binding(0)
|
||||
var<storage, read_write> u_light_indices: array<u32>;
|
||||
@group(4) @binding(1)
|
||||
|
@ -132,7 +134,7 @@ var t_shadow_maps_atlas: texture_depth_2d;
|
|||
@group(5) @binding(1)
|
||||
var s_shadow_maps_atlas: sampler_comparison;
|
||||
@group(5) @binding(2)
|
||||
var<uniform> u_shadow_maps_atlas_size: vec2<u32>;
|
||||
var<uniform> u_shadow_settings: ShadowSettingsUniform;
|
||||
@group(5) @binding(3)
|
||||
var<storage, read> u_light_shadow: array<LightShadowMapUniform>;
|
||||
|
||||
|
@ -280,7 +282,7 @@ fn calc_shadow_dir_light(normal: vec3<f32>, light_dir: vec3<f32>, frag_pos_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) -> f32 {
|
||||
let half_filter_size = SHADOW_MAP_PCF_SIZE / 2.0;
|
||||
let half_filter_size = f32(u_shadow_settings.pcf_samples_num) / 2.0;
|
||||
let texel_size = 1.0 / vec2<f32>(f32(shadow_u.atlas_frame.width), f32(shadow_u.atlas_frame.height));
|
||||
|
||||
// Sample PCF
|
||||
|
@ -292,7 +294,7 @@ fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMa
|
|||
shadow += pcf_depth;
|
||||
}
|
||||
}
|
||||
shadow /= pow(SHADOW_MAP_PCF_SIZE, 2.0);
|
||||
shadow /= pow(f32(u_shadow_settings.pcf_samples_num), 2.0);
|
||||
// ensure the shadow value does not go above 1.0
|
||||
shadow = min(shadow, 1.0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue