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}