veloren_voxygen/render/pipelines/
shadow.rs

1use super::super::{
2    AaMode, Bound, Consts, DebugLayout, DebugVertex, FigureLayout, GlobalsLayouts, TerrainLayout,
3    TerrainVertex,
4};
5use bytemuck::{Pod, Zeroable};
6use vek::*;
7
8#[repr(C)]
9#[derive(Copy, Clone, Debug, Zeroable, Pod)]
10pub struct Locals {
11    shadow_matrices: [[f32; 4]; 4],
12    texture_mats: [[f32; 4]; 4],
13}
14
15impl Locals {
16    pub fn new(shadow_mat: Mat4<f32>, texture_mat: Mat4<f32>) -> Self {
17        Self {
18            shadow_matrices: shadow_mat.into_col_arrays(),
19            texture_mats: texture_mat.into_col_arrays(),
20        }
21    }
22}
23
24impl Default for Locals {
25    fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
26}
27
28pub type BoundLocals = Bound<Consts<Locals>>;
29
30pub struct ShadowLayout {
31    pub locals: wgpu::BindGroupLayout,
32}
33
34impl ShadowLayout {
35    pub fn new(device: &wgpu::Device) -> Self {
36        Self {
37            locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
38                label: None,
39                entries: &[wgpu::BindGroupLayoutEntry {
40                    binding: 0,
41                    visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
42                    ty: wgpu::BindingType::Buffer {
43                        ty: wgpu::BufferBindingType::Uniform,
44                        has_dynamic_offset: false,
45                        min_binding_size: None,
46                    },
47                    count: None,
48                }],
49            }),
50        }
51    }
52
53    pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
54        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
55            label: None,
56            layout: &self.locals,
57            entries: &[wgpu::BindGroupEntry {
58                binding: 0,
59                resource: locals.buf().as_entire_binding(),
60            }],
61        });
62
63        BoundLocals {
64            bind_group,
65            with: locals,
66        }
67    }
68}
69
70#[repr(C)]
71#[derive(Copy, Clone, Debug, Zeroable, Pod)]
72pub struct PointLightMatrix([[f32; 4]; 4]);
73
74impl PointLightMatrix {
75    pub fn new(shadow_mat: Mat4<f32>) -> Self { Self(shadow_mat.into_col_arrays()) }
76}
77
78impl Default for PointLightMatrix {
79    fn default() -> Self { Self::new(Mat4::identity()) }
80}
81
82pub struct ShadowFigurePipeline {
83    pub pipeline: wgpu::RenderPipeline,
84}
85
86impl ShadowFigurePipeline {
87    pub fn new(
88        device: &wgpu::Device,
89        vs_module: &wgpu::ShaderModule,
90        global_layout: &GlobalsLayouts,
91        figure_layout: &FigureLayout,
92        aa_mode: AaMode,
93    ) -> Self {
94        common_base::span!(_guard, "new");
95
96        let render_pipeline_layout =
97            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
98                label: Some("Directed figure shadow pipeline layout"),
99                push_constant_ranges: &[],
100                bind_group_layouts: &[&global_layout.globals, &figure_layout.locals],
101            });
102
103        let samples = aa_mode.samples();
104
105        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
106            label: Some("Directed shadow figure pipeline"),
107            layout: Some(&render_pipeline_layout),
108            vertex: wgpu::VertexState {
109                module: vs_module,
110                entry_point: "main",
111                buffers: &[TerrainVertex::desc()],
112            },
113            primitive: wgpu::PrimitiveState {
114                topology: wgpu::PrimitiveTopology::TriangleList,
115                strip_index_format: None,
116                front_face: wgpu::FrontFace::Ccw,
117                cull_mode: Some(wgpu::Face::Front),
118                unclipped_depth: true,
119                polygon_mode: wgpu::PolygonMode::Fill,
120                conservative: false,
121            },
122            depth_stencil: Some(wgpu::DepthStencilState {
123                format: wgpu::TextureFormat::Depth24Plus,
124                depth_write_enabled: true,
125                depth_compare: wgpu::CompareFunction::Less,
126                stencil: wgpu::StencilState {
127                    front: wgpu::StencilFaceState::IGNORE,
128                    back: wgpu::StencilFaceState::IGNORE,
129                    read_mask: !0,
130                    write_mask: 0,
131                },
132                bias: wgpu::DepthBiasState {
133                    constant: 0,
134                    slope_scale: 0.0,
135                    clamp: 0.0,
136                },
137            }),
138            multisample: wgpu::MultisampleState {
139                count: samples,
140                mask: !0,
141                alpha_to_coverage_enabled: false,
142            },
143            fragment: None,
144            multiview: None,
145        });
146
147        Self {
148            pipeline: render_pipeline,
149        }
150    }
151}
152
153pub struct ShadowPipeline {
154    pub pipeline: wgpu::RenderPipeline,
155}
156
157impl ShadowPipeline {
158    pub fn new(
159        device: &wgpu::Device,
160        vs_module: &wgpu::ShaderModule,
161        global_layout: &GlobalsLayouts,
162        terrain_layout: &TerrainLayout,
163        aa_mode: AaMode,
164    ) -> Self {
165        let render_pipeline_layout =
166            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
167                label: Some("Directed shadow pipeline layout"),
168                push_constant_ranges: &[],
169                bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
170            });
171
172        let samples = aa_mode.samples();
173
174        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
175            label: Some("Directed shadow pipeline"),
176            layout: Some(&render_pipeline_layout),
177            vertex: wgpu::VertexState {
178                module: vs_module,
179                entry_point: "main",
180                buffers: &[TerrainVertex::desc()],
181            },
182            primitive: wgpu::PrimitiveState {
183                topology: wgpu::PrimitiveTopology::TriangleList,
184                strip_index_format: None,
185                front_face: wgpu::FrontFace::Ccw,
186                cull_mode: Some(wgpu::Face::Front),
187                unclipped_depth: true,
188                polygon_mode: wgpu::PolygonMode::Fill,
189                conservative: false,
190            },
191            depth_stencil: Some(wgpu::DepthStencilState {
192                format: wgpu::TextureFormat::Depth24Plus,
193                depth_write_enabled: true,
194                depth_compare: wgpu::CompareFunction::Less,
195                stencil: wgpu::StencilState {
196                    front: wgpu::StencilFaceState::IGNORE,
197                    back: wgpu::StencilFaceState::IGNORE,
198                    read_mask: !0,
199                    write_mask: 0,
200                },
201                bias: wgpu::DepthBiasState {
202                    constant: 0,
203                    slope_scale: 0.0,
204                    clamp: 0.0,
205                },
206            }),
207            multisample: wgpu::MultisampleState {
208                count: samples,
209                mask: !0,
210                alpha_to_coverage_enabled: false,
211            },
212            fragment: None,
213            multiview: None,
214        });
215
216        Self {
217            pipeline: render_pipeline,
218        }
219    }
220}
221pub struct PointShadowPipeline {
222    pub pipeline: wgpu::RenderPipeline,
223}
224
225impl PointShadowPipeline {
226    pub fn new(
227        device: &wgpu::Device,
228        vs_module: &wgpu::ShaderModule,
229        global_layout: &GlobalsLayouts,
230        terrain_layout: &TerrainLayout,
231        aa_mode: AaMode,
232    ) -> Self {
233        let render_pipeline_layout =
234            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
235                label: Some("Point shadow pipeline layout"),
236                push_constant_ranges: &[wgpu::PushConstantRange {
237                    stages: wgpu::ShaderStages::VERTEX_FRAGMENT,
238                    range: 0..64,
239                }],
240                bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
241            });
242
243        let samples = aa_mode.samples();
244
245        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
246            label: Some("Point shadow pipeline"),
247            layout: Some(&render_pipeline_layout),
248            vertex: wgpu::VertexState {
249                module: vs_module,
250                entry_point: "main",
251                buffers: &[TerrainVertex::desc()],
252            },
253            primitive: wgpu::PrimitiveState {
254                topology: wgpu::PrimitiveTopology::TriangleList,
255                strip_index_format: None,
256                front_face: wgpu::FrontFace::Ccw,
257                cull_mode: Some(wgpu::Face::Back),
258                unclipped_depth: false,
259                polygon_mode: wgpu::PolygonMode::Fill,
260                conservative: false,
261            },
262            depth_stencil: Some(wgpu::DepthStencilState {
263                format: wgpu::TextureFormat::Depth24Plus,
264                depth_write_enabled: true,
265                depth_compare: wgpu::CompareFunction::Less,
266                stencil: wgpu::StencilState {
267                    front: wgpu::StencilFaceState::IGNORE,
268                    back: wgpu::StencilFaceState::IGNORE,
269                    read_mask: !0,
270                    write_mask: 0,
271                },
272                bias: wgpu::DepthBiasState {
273                    constant: 0,
274                    slope_scale: 0.0,
275                    clamp: 0.0,
276                },
277            }),
278            multisample: wgpu::MultisampleState {
279                count: samples,
280                mask: !0,
281                alpha_to_coverage_enabled: false,
282            },
283            fragment: None,
284            multiview: None,
285        });
286
287        Self {
288            pipeline: render_pipeline,
289        }
290    }
291}
292
293pub struct ShadowDebugPipeline {
294    pub pipeline: wgpu::RenderPipeline,
295}
296
297impl ShadowDebugPipeline {
298    pub fn new(
299        device: &wgpu::Device,
300        vs_module: &wgpu::ShaderModule,
301        global_layout: &GlobalsLayouts,
302        debug_layout: &DebugLayout,
303        aa_mode: AaMode,
304    ) -> Self {
305        let render_pipeline_layout =
306            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
307                label: Some("Directed shadow debug pipeline layout"),
308                push_constant_ranges: &[],
309                bind_group_layouts: &[&global_layout.globals, &debug_layout.locals],
310            });
311
312        let samples = aa_mode.samples();
313
314        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
315            label: Some("Directed shadow debug pipeline"),
316            layout: Some(&render_pipeline_layout),
317            vertex: wgpu::VertexState {
318                module: vs_module,
319                entry_point: "main",
320                buffers: &[DebugVertex::desc()],
321            },
322            primitive: wgpu::PrimitiveState {
323                topology: wgpu::PrimitiveTopology::TriangleList,
324                strip_index_format: None,
325                front_face: wgpu::FrontFace::Ccw,
326                cull_mode: Some(wgpu::Face::Front),
327                unclipped_depth: true,
328                polygon_mode: wgpu::PolygonMode::Fill,
329                conservative: false,
330            },
331            depth_stencil: Some(wgpu::DepthStencilState {
332                format: wgpu::TextureFormat::Depth24Plus,
333                depth_write_enabled: true,
334                depth_compare: wgpu::CompareFunction::Less,
335                stencil: wgpu::StencilState {
336                    front: wgpu::StencilFaceState::IGNORE,
337                    back: wgpu::StencilFaceState::IGNORE,
338                    read_mask: !0,
339                    write_mask: !0,
340                },
341                bias: wgpu::DepthBiasState {
342                    constant: 0,
343                    slope_scale: 0.0,
344                    clamp: 0.0,
345                },
346            }),
347            multisample: wgpu::MultisampleState {
348                count: samples,
349                mask: !0,
350                alpha_to_coverage_enabled: false,
351            },
352            fragment: None,
353            multiview: None,
354        });
355
356        Self {
357            pipeline: render_pipeline,
358        }
359    }
360}