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: Some("main"),
111                buffers: &[TerrainVertex::desc()],
112                compilation_options: Default::default(),
113            },
114            primitive: wgpu::PrimitiveState {
115                topology: wgpu::PrimitiveTopology::TriangleList,
116                strip_index_format: None,
117                front_face: wgpu::FrontFace::Ccw,
118                cull_mode: Some(wgpu::Face::Front),
119                unclipped_depth: true,
120                polygon_mode: wgpu::PolygonMode::Fill,
121                conservative: false,
122            },
123            depth_stencil: Some(wgpu::DepthStencilState {
124                format: wgpu::TextureFormat::Depth24Plus,
125                depth_write_enabled: true,
126                depth_compare: wgpu::CompareFunction::Less,
127                stencil: wgpu::StencilState {
128                    front: wgpu::StencilFaceState::IGNORE,
129                    back: wgpu::StencilFaceState::IGNORE,
130                    read_mask: !0,
131                    write_mask: 0,
132                },
133                bias: wgpu::DepthBiasState {
134                    constant: 0,
135                    slope_scale: 0.0,
136                    clamp: 0.0,
137                },
138            }),
139            multisample: wgpu::MultisampleState {
140                count: samples,
141                mask: !0,
142                alpha_to_coverage_enabled: false,
143            },
144            fragment: None,
145            multiview: None,
146            cache: None,
147        });
148
149        Self {
150            pipeline: render_pipeline,
151        }
152    }
153}
154
155pub struct ShadowPipeline {
156    pub pipeline: wgpu::RenderPipeline,
157}
158
159impl ShadowPipeline {
160    pub fn new(
161        device: &wgpu::Device,
162        vs_module: &wgpu::ShaderModule,
163        global_layout: &GlobalsLayouts,
164        terrain_layout: &TerrainLayout,
165        aa_mode: AaMode,
166    ) -> Self {
167        let render_pipeline_layout =
168            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
169                label: Some("Directed shadow pipeline layout"),
170                push_constant_ranges: &[],
171                bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
172            });
173
174        let samples = aa_mode.samples();
175
176        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
177            label: Some("Directed shadow pipeline"),
178            layout: Some(&render_pipeline_layout),
179            vertex: wgpu::VertexState {
180                module: vs_module,
181                entry_point: Some("main"),
182                buffers: &[TerrainVertex::desc()],
183                compilation_options: Default::default(),
184            },
185            primitive: wgpu::PrimitiveState {
186                topology: wgpu::PrimitiveTopology::TriangleList,
187                strip_index_format: None,
188                front_face: wgpu::FrontFace::Ccw,
189                cull_mode: Some(wgpu::Face::Front),
190                unclipped_depth: true,
191                polygon_mode: wgpu::PolygonMode::Fill,
192                conservative: false,
193            },
194            depth_stencil: Some(wgpu::DepthStencilState {
195                format: wgpu::TextureFormat::Depth24Plus,
196                depth_write_enabled: true,
197                depth_compare: wgpu::CompareFunction::Less,
198                stencil: wgpu::StencilState {
199                    front: wgpu::StencilFaceState::IGNORE,
200                    back: wgpu::StencilFaceState::IGNORE,
201                    read_mask: !0,
202                    write_mask: 0,
203                },
204                bias: wgpu::DepthBiasState {
205                    constant: 0,
206                    slope_scale: 0.0,
207                    clamp: 0.0,
208                },
209            }),
210            multisample: wgpu::MultisampleState {
211                count: samples,
212                mask: !0,
213                alpha_to_coverage_enabled: false,
214            },
215            fragment: None,
216            multiview: None,
217            cache: None,
218        });
219
220        Self {
221            pipeline: render_pipeline,
222        }
223    }
224}
225pub struct PointShadowPipeline {
226    pub pipeline: wgpu::RenderPipeline,
227}
228
229impl PointShadowPipeline {
230    pub fn new(
231        device: &wgpu::Device,
232        vs_module: &wgpu::ShaderModule,
233        global_layout: &GlobalsLayouts,
234        terrain_layout: &TerrainLayout,
235        aa_mode: AaMode,
236    ) -> Self {
237        let render_pipeline_layout =
238            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
239                label: Some("Point shadow pipeline layout"),
240                push_constant_ranges: &[wgpu::PushConstantRange {
241                    stages: wgpu::ShaderStages::VERTEX_FRAGMENT,
242                    range: 0..64,
243                }],
244                bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
245            });
246
247        let samples = aa_mode.samples();
248
249        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
250            label: Some("Point shadow pipeline"),
251            layout: Some(&render_pipeline_layout),
252            vertex: wgpu::VertexState {
253                module: vs_module,
254                entry_point: Some("main"),
255                buffers: &[TerrainVertex::desc()],
256                compilation_options: Default::default(),
257            },
258            primitive: wgpu::PrimitiveState {
259                topology: wgpu::PrimitiveTopology::TriangleList,
260                strip_index_format: None,
261                front_face: wgpu::FrontFace::Ccw,
262                cull_mode: Some(wgpu::Face::Back),
263                unclipped_depth: false,
264                polygon_mode: wgpu::PolygonMode::Fill,
265                conservative: false,
266            },
267            depth_stencil: Some(wgpu::DepthStencilState {
268                format: wgpu::TextureFormat::Depth24Plus,
269                depth_write_enabled: true,
270                depth_compare: wgpu::CompareFunction::Less,
271                stencil: wgpu::StencilState {
272                    front: wgpu::StencilFaceState::IGNORE,
273                    back: wgpu::StencilFaceState::IGNORE,
274                    read_mask: !0,
275                    write_mask: 0,
276                },
277                bias: wgpu::DepthBiasState {
278                    constant: 0,
279                    slope_scale: 0.0,
280                    clamp: 0.0,
281                },
282            }),
283            multisample: wgpu::MultisampleState {
284                count: samples,
285                mask: !0,
286                alpha_to_coverage_enabled: false,
287            },
288            fragment: None,
289            multiview: None,
290            cache: None,
291        });
292
293        Self {
294            pipeline: render_pipeline,
295        }
296    }
297}
298
299pub struct ShadowDebugPipeline {
300    pub pipeline: wgpu::RenderPipeline,
301}
302
303impl ShadowDebugPipeline {
304    pub fn new(
305        device: &wgpu::Device,
306        vs_module: &wgpu::ShaderModule,
307        global_layout: &GlobalsLayouts,
308        debug_layout: &DebugLayout,
309        aa_mode: AaMode,
310    ) -> Self {
311        let render_pipeline_layout =
312            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
313                label: Some("Directed shadow debug pipeline layout"),
314                push_constant_ranges: &[],
315                bind_group_layouts: &[&global_layout.globals, &debug_layout.locals],
316            });
317
318        let samples = aa_mode.samples();
319
320        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
321            label: Some("Directed shadow debug pipeline"),
322            layout: Some(&render_pipeline_layout),
323            vertex: wgpu::VertexState {
324                module: vs_module,
325                entry_point: Some("main"),
326                buffers: &[DebugVertex::desc()],
327                compilation_options: Default::default(),
328            },
329            primitive: wgpu::PrimitiveState {
330                topology: wgpu::PrimitiveTopology::TriangleList,
331                strip_index_format: None,
332                front_face: wgpu::FrontFace::Ccw,
333                cull_mode: Some(wgpu::Face::Front),
334                unclipped_depth: true,
335                polygon_mode: wgpu::PolygonMode::Fill,
336                conservative: false,
337            },
338            depth_stencil: Some(wgpu::DepthStencilState {
339                format: wgpu::TextureFormat::Depth24Plus,
340                depth_write_enabled: true,
341                depth_compare: wgpu::CompareFunction::Less,
342                stencil: wgpu::StencilState {
343                    front: wgpu::StencilFaceState::IGNORE,
344                    back: wgpu::StencilFaceState::IGNORE,
345                    read_mask: !0,
346                    write_mask: !0,
347                },
348                bias: wgpu::DepthBiasState {
349                    constant: 0,
350                    slope_scale: 0.0,
351                    clamp: 0.0,
352                },
353            }),
354            multisample: wgpu::MultisampleState {
355                count: samples,
356                mask: !0,
357                alpha_to_coverage_enabled: false,
358            },
359            fragment: None,
360            multiview: None,
361            cache: None,
362        });
363
364        Self {
365            pipeline: render_pipeline,
366        }
367    }
368}