render: update the shadow filting poisson disc when shadow settings are modified

This commit is contained in:
SeanOMik 2024-07-19 16:07:40 -04:00
parent 54b47c2178
commit c961568b96
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
1 changed files with 25 additions and 24 deletions

View File

@ -12,7 +12,7 @@ use lyra_ecs::{
use lyra_game_derive::RenderGraphLabel;
use lyra_math::{Angle, Transform};
use rustc_hash::FxHashMap;
use tracing::warn;
use tracing::{debug, warn};
use wgpu::util::DeviceExt;
use crate::render::{
@ -356,10 +356,8 @@ impl ShadowMapsPass {
/// Generate and write a Poisson disc to `buffer` with `num_pcf_samples.pow(2)` amount of points.
fn write_poisson_disc(&self, queue: &wgpu::Queue, buffer: &wgpu::Buffer, num_samples: u32) {
//let num_points = num_samples.pow(2);
let num_floats = num_samples * 2; // points are vec2f
let min_dist = (num_floats as f32).sqrt() / num_floats as f32;
//let min_dist = (num_samples as f32).sqrt() / num_samples as f32;
let mut points = vec![];
// use a while loop to ensure that the correct number of floats is created
@ -439,12 +437,11 @@ impl Node for ShadowMapsPass {
Some(SlotValue::Buffer(Arc::new(settings_buffer))),
);
let def_settings = ShadowSettings::default();
node.add_buffer_slot(
ShadowMapsPassSlots::PcfPoissonDiscBuffer,
SlotAttribute::Output,
Some(SlotValue::Buffer(Arc::new(
self.create_poisson_disc_buffer(device, "buffer_poisson_disc_pcf", def_settings.pcf_samples_num),
self.create_poisson_disc_buffer(device, "buffer_poisson_disc_pcf", PCF_SAMPLES_NUM_MAX),
))),
);
@ -452,7 +449,7 @@ impl Node for ShadowMapsPass {
ShadowMapsPassSlots::PcssPoissonDiscBuffer,
SlotAttribute::Output,
Some(SlotValue::Buffer(Arc::new(
self.create_poisson_disc_buffer(device, "buffer_poisson_disc_pcss", def_settings.pcss_blocker_search_samples),
self.create_poisson_disc_buffer(device, "buffer_poisson_disc_pcss", PCSS_SAMPLES_NUM_MAX),
))),
);
@ -465,25 +462,26 @@ impl Node for ShadowMapsPass {
world: &mut lyra_ecs::World,
context: &mut crate::render::graph::RenderGraphContext,
) {
{
// TODO: Update the poisson disc every time the PCF sampling point number changed
if !world.has_resource::<ShadowSettings>() {
let def_settings = ShadowSettings::default();
world.add_resource_default_if_absent::<ShadowSettings>();
if world.has_resource_changed::<ShadowSettings>() {
debug!("Detected change in ShadowSettings, recreating poisson disks");
let settings = world.get_resource::<ShadowSettings>();
// convert to uniform now since the from impl limits to max values
let uniform = ShadowSettingsUniform::from(*settings);
let buffer = graph.slot_value(ShadowMapsPassSlots::PcfPoissonDiscBuffer)
.unwrap().as_buffer().unwrap();
self.write_poisson_disc(&context.queue, &buffer, def_settings.pcf_samples_num);
self.write_poisson_disc(&context.queue, &buffer, uniform.pcf_samples_num);
let buffer = graph.slot_value(ShadowMapsPassSlots::PcssPoissonDiscBuffer)
.unwrap().as_buffer().unwrap();
self.write_poisson_disc(&context.queue, &buffer, def_settings.pcss_blocker_search_samples);
}
self.write_poisson_disc(&context.queue, &buffer, uniform.pcss_blocker_search_samples);
// 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),
uniform,
);
}
@ -811,12 +809,12 @@ impl LightShadowMapAtlas {
pub struct ShadowSettings {
/// How many PCF filtering samples are used per dimension.
///
/// A value of 16 is common.
/// 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 16 is common.
/// A value of 25 is common, this is maxed to 128.
pub pcss_blocker_search_samples: u32,
}
@ -829,6 +827,9 @@ impl Default for ShadowSettings {
}
}
const PCF_SAMPLES_NUM_MAX: u32 = 128;
const PCSS_SAMPLES_NUM_MAX: u32 = 128;
/// Uniform version of [`ShadowSettings`]
#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
@ -840,8 +841,8 @@ struct ShadowSettingsUniform {
impl From<ShadowSettings> for ShadowSettingsUniform {
fn from(value: ShadowSettings) -> Self {
Self {
pcf_samples_num: value.pcf_samples_num,
pcss_blocker_search_samples: value.pcss_blocker_search_samples,
pcf_samples_num: value.pcf_samples_num.min(PCF_SAMPLES_NUM_MAX),
pcss_blocker_search_samples: value.pcss_blocker_search_samples.min(PCSS_SAMPLES_NUM_MAX),
}
}
}