Implement Shadows #24
|
@ -8,9 +8,12 @@ use tracing::{debug, warn};
|
|||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::render::{
|
||||
graph::{Node, NodeDesc, NodeType},
|
||||
graph::{Node, NodeDesc, NodeType, SlotAttribute, SlotValue},
|
||||
light::directional::DirectionalLight,
|
||||
resource::{FragmentState, PipelineDescriptor, RenderPipeline, RenderPipelineDescriptor, Shader, VertexState},
|
||||
resource::{
|
||||
FragmentState, PipelineDescriptor, RenderPipeline, RenderPipelineDescriptor, Shader,
|
||||
VertexState,
|
||||
},
|
||||
transform_buffer_storage::TransformBuffers,
|
||||
vertex::Vertex,
|
||||
};
|
||||
|
@ -19,14 +22,18 @@ use super::{MeshBufferStorage, RenderAssets, RenderMeshes};
|
|||
|
||||
const SHADOW_SIZE: glam::UVec2 = glam::UVec2::new(1024, 1024);
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||
pub enum ShadowMapsPassSlots {
|
||||
ShadowAtlasTexture,
|
||||
ShadowAtlasTextureView,
|
||||
ShadowAtlasSampler,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||
pub struct ShadowMapsPassLabel;
|
||||
|
||||
struct LightDepthMap {
|
||||
light_projection_buffer: wgpu::Buffer,
|
||||
texture: wgpu::Texture,
|
||||
view: wgpu::TextureView,
|
||||
sampler: wgpu::Sampler,
|
||||
bindgroup: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
|
@ -41,39 +48,37 @@ pub struct ShadowMapsPass {
|
|||
render_meshes: Option<ResourceData>,
|
||||
mesh_buffers: Option<ResourceData>,
|
||||
pipeline: Option<RenderPipeline>,
|
||||
|
||||
/// The depth map atlas texture
|
||||
atlas_texture: Rc<wgpu::Texture>,
|
||||
/// The depth map atlas texture view
|
||||
atlas_view: Arc<wgpu::TextureView>,
|
||||
/// The depth map atlas sampler
|
||||
atlas_sampler: Rc<wgpu::Sampler>,
|
||||
}
|
||||
|
||||
impl ShadowMapsPass {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let bgl = Arc::new(device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("shadows_bgl"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(
|
||||
NonZeroU64::new(mem::size_of::<glam::Mat4>() as _).unwrap(),
|
||||
),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
}));
|
||||
let bgl = Arc::new(
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("bgl_shadows_light_projection"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(
|
||||
NonZeroU64::new(mem::size_of::<glam::Mat4>() as _).unwrap(),
|
||||
),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
}),
|
||||
);
|
||||
|
||||
Self {
|
||||
bgl,
|
||||
depth_maps: Default::default(),
|
||||
transform_buffers: None,
|
||||
render_meshes: None,
|
||||
mesh_buffers: None,
|
||||
pipeline: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_depth_map(&mut self, device: &wgpu::Device, entity: Entity, light_pos: Transform) {
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("texture_shadow_map_directional_light"),
|
||||
label: Some("texture_shadow_map_atlas"),
|
||||
size: wgpu::Extent3d {
|
||||
width: SHADOW_SIZE.x,
|
||||
height: SHADOW_SIZE.y,
|
||||
|
@ -93,7 +98,7 @@ impl ShadowMapsPass {
|
|||
});
|
||||
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: Some("sampler_light_depth_map"),
|
||||
label: Some("sampler_shadow_map_atlas"),
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
|
@ -104,17 +109,29 @@ impl ShadowMapsPass {
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
Self {
|
||||
bgl,
|
||||
depth_maps: Default::default(),
|
||||
transform_buffers: None,
|
||||
render_meshes: None,
|
||||
mesh_buffers: None,
|
||||
pipeline: None,
|
||||
|
||||
atlas_sampler: Rc::new(sampler),
|
||||
atlas_texture: Rc::new(tex),
|
||||
atlas_view: Arc::new(view),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_depth_map(&mut self, device: &wgpu::Device, entity: Entity, light_pos: Transform) {
|
||||
const NEAR_PLANE: f32 = 0.1;
|
||||
const FAR_PLANE: f32 = 80.0;
|
||||
|
||||
let ortho_proj =
|
||||
glam::Mat4::orthographic_rh_gl(-20.0, 20.0, -20.0, 20.0, NEAR_PLANE, FAR_PLANE);
|
||||
|
||||
let look_view = glam::Mat4::look_to_rh(
|
||||
light_pos.translation,
|
||||
light_pos.forward(),
|
||||
light_pos.up()
|
||||
);
|
||||
let look_view =
|
||||
glam::Mat4::look_to_rh(light_pos.translation, light_pos.forward(), light_pos.up());
|
||||
|
||||
let light_proj = OPENGL_TO_WGPU_MATRIX * (ortho_proj * look_view);
|
||||
|
||||
|
@ -142,9 +159,6 @@ impl ShadowMapsPass {
|
|||
entity,
|
||||
LightDepthMap {
|
||||
light_projection_buffer,
|
||||
texture: tex,
|
||||
view,
|
||||
sampler,
|
||||
bindgroup: bg,
|
||||
},
|
||||
);
|
||||
|
@ -168,7 +182,27 @@ impl Node for ShadowMapsPass {
|
|||
&mut self,
|
||||
graph: &mut crate::render::graph::RenderGraph,
|
||||
) -> crate::render::graph::NodeDesc {
|
||||
NodeDesc::new(NodeType::Render, None, vec![])
|
||||
let mut node = NodeDesc::new(NodeType::Render, None, vec![]);
|
||||
|
||||
node.add_texture_slot(
|
||||
ShadowMapsPassSlots::ShadowAtlasTexture,
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Texture(self.atlas_texture.clone())),
|
||||
);
|
||||
|
||||
node.add_texture_view_slot(
|
||||
ShadowMapsPassSlots::ShadowAtlasTextureView,
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::TextureView(self.atlas_view.clone())),
|
||||
);
|
||||
|
||||
node.add_sampler_slot(
|
||||
ShadowMapsPassSlots::ShadowAtlasSampler,
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Sampler(self.atlas_sampler.clone())),
|
||||
);
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn prepare(
|
||||
|
@ -201,10 +235,7 @@ impl Node for ShadowMapsPass {
|
|||
&graph.device,
|
||||
&RenderPipelineDescriptor {
|
||||
label: Some("pipeline_shadows".into()),
|
||||
layouts: vec![
|
||||
bgl,
|
||||
transforms,
|
||||
],
|
||||
layouts: vec![bgl, transforms],
|
||||
push_constant_ranges: vec![],
|
||||
vertex: VertexState {
|
||||
module: shader.clone(),
|
||||
|
@ -226,7 +257,7 @@ impl Node for ShadowMapsPass {
|
|||
primitive: wgpu::PrimitiveState::default(),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
}
|
||||
},
|
||||
));
|
||||
/* */
|
||||
}
|
||||
|
@ -261,7 +292,7 @@ impl Node for ShadowMapsPass {
|
|||
label: Some("pass_shadow_map"),
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: &dir_depth_map.view,
|
||||
view: &self.atlas_view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: true,
|
||||
|
|
Loading…
Reference in New Issue