render: pass shadow settings to gpu
This commit is contained in:
parent
ff06bd55f3
commit
27bc88c5a7
|
@ -115,9 +115,9 @@ impl Node for MeshPass {
|
||||||
.expect("missing ShadowMapsPassSlots::ShadowAtlasSampler")
|
.expect("missing ShadowMapsPassSlots::ShadowAtlasSampler")
|
||||||
.as_sampler()
|
.as_sampler()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let atlas_size_buf = graph
|
let shadow_settings_buf = graph
|
||||||
.slot_value(ShadowMapsPassSlots::ShadowAtlasSizeBuffer)
|
.slot_value(ShadowMapsPassSlots::ShadowSettingsUniform)
|
||||||
.expect("missing ShadowMapsPassSlots::ShadowAtlasSizeBuffer")
|
.expect("missing ShadowMapsPassSlots::ShadowSettingsUniform")
|
||||||
.as_buffer()
|
.as_buffer()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let light_uniform_buf = graph
|
let light_uniform_buf = graph
|
||||||
|
@ -183,7 +183,7 @@ impl Node for MeshPass {
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 2,
|
binding: 2,
|
||||||
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||||
buffer: atlas_size_buf,
|
buffer: shadow_settings_buf,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
size: None,
|
size: None,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -16,16 +16,12 @@ use tracing::warn;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
use crate::render::{
|
use crate::render::{
|
||||||
graph::{Node, NodeDesc, NodeType, SlotAttribute, SlotValue},
|
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
|
||||||
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};
|
use super::{MeshBufferStorage, RenderAssets, RenderMeshes};
|
||||||
|
|
||||||
|
const PCF_SAMPLES_NUM: u32 = 4;
|
||||||
const SHADOW_SIZE: glam::UVec2 = glam::uvec2(1024, 1024);
|
const SHADOW_SIZE: glam::UVec2 = glam::uvec2(1024, 1024);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||||
|
@ -35,6 +31,7 @@ pub enum ShadowMapsPassSlots {
|
||||||
ShadowAtlasSampler,
|
ShadowAtlasSampler,
|
||||||
ShadowAtlasSizeBuffer,
|
ShadowAtlasSizeBuffer,
|
||||||
ShadowLightUniformsBuffer,
|
ShadowLightUniformsBuffer,
|
||||||
|
ShadowSettingsUniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||||
|
@ -333,7 +330,7 @@ impl ShadowMapsPass {
|
||||||
impl Node for ShadowMapsPass {
|
impl Node for ShadowMapsPass {
|
||||||
fn desc(
|
fn desc(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut crate::render::graph::RenderGraph,
|
graph: &mut crate::render::graph::RenderGraph,
|
||||||
) -> crate::render::graph::NodeDesc {
|
) -> crate::render::graph::NodeDesc {
|
||||||
let mut node = NodeDesc::new(NodeType::Render, None, vec![]);
|
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())),
|
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
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +389,12 @@ impl Node for ShadowMapsPass {
|
||||||
world: &mut lyra_ecs::World,
|
world: &mut lyra_ecs::World,
|
||||||
context: &mut crate::render::graph::RenderGraphContext,
|
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.render_meshes = world.try_get_resource_data::<RenderMeshes>();
|
||||||
self.transform_buffers = world.try_get_resource_data::<TransformBuffers>();
|
self.transform_buffers = world.try_get_resource_data::<TransformBuffers>();
|
||||||
self.mesh_buffers = world.try_get_resource_data::<RenderAssets<MeshBufferStorage>>();
|
self.mesh_buffers = world.try_get_resource_data::<RenderAssets<MeshBufferStorage>>();
|
||||||
|
@ -691,3 +706,29 @@ impl LightShadowMapAtlas {
|
||||||
self.0.write().unwrap()
|
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 ALPHA_CUTOFF = 0.1;
|
||||||
|
|
||||||
const SHADOW_MAP_PCF_SIZE = 4.0;
|
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec3<f32>,
|
@location(0) position: vec3<f32>,
|
||||||
@location(1) tex_coords: vec2<f32>,
|
@location(1) tex_coords: vec2<f32>,
|
||||||
|
@ -122,6 +120,10 @@ struct LightShadowMapUniform {
|
||||||
light_pos: vec3<f32>,
|
light_pos: vec3<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ShadowSettingsUniform {
|
||||||
|
pcf_samples_num: u32,
|
||||||
|
}
|
||||||
|
|
||||||
@group(4) @binding(0)
|
@group(4) @binding(0)
|
||||||
var<storage, read_write> u_light_indices: array<u32>;
|
var<storage, read_write> u_light_indices: array<u32>;
|
||||||
@group(4) @binding(1)
|
@group(4) @binding(1)
|
||||||
|
@ -132,7 +134,7 @@ var t_shadow_maps_atlas: texture_depth_2d;
|
||||||
@group(5) @binding(1)
|
@group(5) @binding(1)
|
||||||
var s_shadow_maps_atlas: sampler_comparison;
|
var s_shadow_maps_atlas: sampler_comparison;
|
||||||
@group(5) @binding(2)
|
@group(5) @binding(2)
|
||||||
var<uniform> u_shadow_maps_atlas_size: vec2<u32>;
|
var<uniform> u_shadow_settings: ShadowSettingsUniform;
|
||||||
@group(5) @binding(3)
|
@group(5) @binding(3)
|
||||||
var<storage, read> u_light_shadow: array<LightShadowMapUniform>;
|
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
|
/// 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 {
|
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));
|
let texel_size = 1.0 / vec2<f32>(f32(shadow_u.atlas_frame.width), f32(shadow_u.atlas_frame.height));
|
||||||
|
|
||||||
// Sample PCF
|
// Sample PCF
|
||||||
|
@ -292,7 +294,7 @@ fn pcf_dir_light(tex_coords: vec2<f32>, test_depth: f32, shadow_u: LightShadowMa
|
||||||
shadow += pcf_depth;
|
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
|
// ensure the shadow value does not go above 1.0
|
||||||
shadow = min(shadow, 1.0);
|
shadow = min(shadow, 1.0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue