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}