1use crate::render::Bound;
2
3use super::{
4 super::{
5 AltIndices, CullingMode,
6 buffer::Buffer,
7 instances::Instances,
8 model::{DynamicModel, Model, SubModel},
9 pipelines::{
10 AtlasTextures, FigureSpriteAtlasData, GlobalsBindGroup, TerrainAtlasData, blit, bloom,
11 clouds, debug, figure, fluid, lod_object, lod_terrain, particle, rope, shadow, skybox,
12 sprite, terrain, trail, ui,
13 },
14 },
15 Renderer, ShadowMap, ShadowMapRenderer,
16 rain_occlusion_map::{RainOcclusionMap, RainOcclusionMapRenderer},
17};
18use common_base::prof_span;
19use core::ops::Range;
20use std::sync::Arc;
21use vek::Aabr;
22use wgpu_profiler::{OwningScope, Scope};
23#[cfg(feature = "egui-ui")]
24use {common_base::span, egui_wgpu::ScreenDescriptor};
25
26pub const UI_PREMULTIPLY_PASS: &str = "ui_premultiply_pass";
28
29enum Pipelines<'frame> {
31 Interface(&'frame super::InterfacePipelines),
32 All(&'frame super::Pipelines),
33 None,
35}
36
37impl Pipelines<'_> {
38 fn ui(&self) -> Option<&ui::UiPipeline> {
39 match self {
40 Pipelines::Interface(pipelines) => Some(&pipelines.ui),
41 Pipelines::All(pipelines) => Some(&pipelines.ui),
42 Pipelines::None => None,
43 }
44 }
45
46 fn premultiply_alpha(&self) -> Option<&ui::PremultiplyAlphaPipeline> {
47 match self {
48 Pipelines::Interface(pipelines) => Some(&pipelines.premultiply_alpha),
49 Pipelines::All(pipelines) => Some(&pipelines.premultiply_alpha),
50 Pipelines::None => None,
51 }
52 }
53
54 fn blit(&self) -> Option<&blit::BlitPipeline> {
55 match self {
56 Pipelines::Interface(pipelines) => Some(&pipelines.blit),
57 Pipelines::All(pipelines) => Some(&pipelines.blit),
58 Pipelines::None => None,
59 }
60 }
61
62 fn all(&self) -> Option<&super::Pipelines> {
63 match self {
64 Pipelines::All(pipelines) => Some(pipelines),
65 Pipelines::Interface(_) | Pipelines::None => None,
66 }
67 }
68}
69
70struct ManualScope<'a> {
71 profiler: &'a mut wgpu_profiler::GpuProfiler,
72 encoder: Option<wgpu::CommandEncoder>,
73 scope: Option<wgpu_profiler::GpuProfilerQuery>,
74}
75
76impl<'a> ManualScope<'a> {
77 fn start(
78 label: &str,
79 profiler: &'a mut wgpu_profiler::GpuProfiler,
80 mut encoder: wgpu::CommandEncoder,
81 ) -> Self {
82 let scope = profiler.begin_query(label, &mut encoder);
83 Self {
84 profiler,
85 encoder: Some(encoder),
86 scope: Some(scope),
87 }
88 }
89
90 fn encoder(&mut self) -> &mut wgpu::CommandEncoder { self.encoder.as_mut().unwrap() }
91
92 #[must_use]
93 #[track_caller]
94 pub fn scope(&mut self, label: impl Into<String>) -> Scope<'_, wgpu::CommandEncoder> {
95 let encoder = self.encoder.as_mut().unwrap();
96
97 let scope = self
98 .profiler
99 .begin_query(label, encoder)
100 .with_parent(self.scope.as_ref());
101
102 Scope {
103 profiler: self.profiler,
104 recorder: encoder,
105 scope: Some(scope),
106 }
107 }
108
109 #[track_caller]
110 fn scoped_render_pass<'pass>(
111 &'pass mut self,
112 label: &str,
113 descriptor: wgpu::RenderPassDescriptor<'_>,
114 ) -> OwningScope<'pass, wgpu::RenderPass<'pass>> {
115 let encoder = self.encoder.as_mut().unwrap();
116
117 let child_scope = self
118 .profiler
119 .begin_pass_query(label, encoder)
120 .with_parent(self.scope.as_ref());
121 let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
122 timestamp_writes: child_scope.render_pass_timestamp_writes(),
123 label: descriptor.label.or(Some(&child_scope.label)),
124 ..descriptor
125 });
126
127 OwningScope {
128 profiler: self.profiler,
129 recorder: render_pass,
130 scope: Some(child_scope),
131 }
132 }
133
134 fn end_query(&mut self) -> (&mut wgpu_profiler::GpuProfiler, wgpu::CommandEncoder) {
135 let mut encoder = self.encoder.take().unwrap();
136 self.profiler
137 .end_query(&mut encoder, self.scope.take().unwrap());
138 (self.profiler, encoder)
139 }
140}
141
142struct RendererBorrow<'frame> {
145 queue: &'frame wgpu::Queue,
146 #[allow(unused)]
147 device: &'frame wgpu::Device,
148 #[cfg(feature = "egui-ui")]
149 surface_config: &'frame wgpu::SurfaceConfiguration,
150 shadow: Option<&'frame super::Shadow>,
151 pipelines: Pipelines<'frame>,
152 locals: &'frame super::locals::Locals,
153 views: &'frame super::Views,
154 pipeline_modes: &'frame super::PipelineModes,
155 quad_index_buffer_u16: &'frame Buffer<u16>,
156 quad_index_buffer_u32: &'frame Buffer<u32>,
157 ui_premultiply_uploads: &'frame mut ui::BatchedUploads,
158 #[cfg(feature = "egui-ui")]
159 egui_renderer: &'frame mut egui_wgpu::Renderer,
160}
161
162pub struct Drawer<'frame> {
163 surface_view: wgpu::TextureView,
164 encoder: ManualScope<'frame>,
165 borrow: RendererBorrow<'frame>,
166 surface_texture: Option<wgpu::SurfaceTexture>,
167 globals: &'frame GlobalsBindGroup,
168 taking_screenshot: Option<super::screenshot::TakeScreenshot>,
171}
172
173impl<'frame> Drawer<'frame> {
174 pub fn new(
175 encoder: wgpu::CommandEncoder,
176 renderer: &'frame mut Renderer,
177 surface_texture: wgpu::SurfaceTexture,
178 globals: &'frame GlobalsBindGroup,
179 ) -> Self {
180 let taking_screenshot = renderer.take_screenshot.take().map(|screenshot_fn| {
181 super::screenshot::TakeScreenshot::new(
182 &renderer.device,
183 &renderer.layouts.blit,
184 &renderer.sampler,
185 &renderer.surface_config,
186 screenshot_fn,
187 )
188 });
189
190 let (pipelines, shadow) = match &renderer.state {
191 super::State::Interface { pipelines, .. } => (Pipelines::Interface(pipelines), None),
192 super::State::Complete {
193 pipelines, shadow, ..
194 } => (Pipelines::All(pipelines), Some(shadow)),
195 super::State::Nothing => (Pipelines::None, None),
196 };
197
198 let borrow = RendererBorrow {
199 queue: &renderer.queue,
200 device: &renderer.device,
201 #[cfg(feature = "egui-ui")]
202 surface_config: &renderer.surface_config,
203 shadow,
204 pipelines,
205 locals: &renderer.locals,
206 views: &renderer.views,
207 pipeline_modes: &renderer.pipeline_modes,
208 quad_index_buffer_u16: &renderer.quad_index_buffer_u16,
209 quad_index_buffer_u32: &renderer.quad_index_buffer_u32,
210 ui_premultiply_uploads: &mut renderer.ui_premultiply_uploads,
211 #[cfg(feature = "egui-ui")]
212 egui_renderer: &mut renderer.egui_renderer,
213 };
214
215 let encoder = ManualScope::start("frame", &mut renderer.profiler, encoder);
216
217 let surface_view = surface_texture
219 .texture
220 .create_view(&wgpu::TextureViewDescriptor {
221 label: Some("Surface texture view"),
222 ..Default::default()
223 });
224
225 Self {
226 surface_view,
227 encoder,
228 borrow,
229 surface_texture: Some(surface_texture),
230 globals,
231 taking_screenshot,
232 }
233 }
234
235 pub fn pipeline_modes(&self) -> &super::PipelineModes { self.borrow.pipeline_modes }
237
238 pub fn rain_occlusion_pass(&mut self) -> Option<RainOcclusionPassDrawer<'_>> {
241 if !self.borrow.pipeline_modes.cloud.is_enabled() {
242 return None;
243 }
244
245 if let RainOcclusionMap::Enabled(ref rain_occlusion_renderer) = self.borrow.shadow?.rain_map
246 {
247 let mut render_pass = self.encoder.scoped_render_pass(
248 "rain_occlusion_pass",
249 wgpu::RenderPassDescriptor {
250 label: Some("rain occlusion pass"),
251 color_attachments: &[],
252 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
253 view: &rain_occlusion_renderer.depth.view,
254 depth_ops: Some(wgpu::Operations {
255 load: wgpu::LoadOp::Clear(1.0),
256 store: wgpu::StoreOp::Store,
257 }),
258 stencil_ops: None,
259 }),
260 timestamp_writes: None,
261 occlusion_query_set: None,
262 },
263 );
264
265 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
266
267 Some(RainOcclusionPassDrawer {
268 render_pass,
269 borrow: &self.borrow,
270 rain_occlusion_renderer,
271 })
272 } else {
273 None
274 }
275 }
276
277 pub fn shadow_pass(&mut self) -> Option<ShadowPassDrawer<'_>> {
280 if !self.borrow.pipeline_modes.shadow.is_map() {
281 return None;
282 }
283
284 if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow?.map {
285 let mut render_pass =
286 self.encoder
287 .scoped_render_pass("shadow_pass", wgpu::RenderPassDescriptor {
288 label: Some("shadow pass"),
289 color_attachments: &[],
290 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
291 view: &shadow_renderer.directed_depth.view,
292 depth_ops: Some(wgpu::Operations {
293 load: wgpu::LoadOp::Clear(1.0),
294 store: wgpu::StoreOp::Store,
295 }),
296 stencil_ops: None,
297 }),
298 timestamp_writes: None,
299 occlusion_query_set: None,
300 });
301
302 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
303
304 Some(ShadowPassDrawer {
305 render_pass,
306 borrow: &self.borrow,
307 shadow_renderer,
308 })
309 } else {
310 None
311 }
312 }
313
314 pub fn first_pass(&mut self) -> Option<FirstPassDrawer<'_>> {
316 let pipelines = self.borrow.pipelines.all()?;
317 let shadow = self.borrow.shadow?;
320
321 let mut render_pass =
322 self.encoder
323 .scoped_render_pass("first_pass", wgpu::RenderPassDescriptor {
324 label: Some("first pass"),
325 color_attachments: &[
326 Some(wgpu::RenderPassColorAttachment {
327 view: &self.borrow.views.tgt_color,
328 depth_slice: None,
329 resolve_target: None,
330 ops: wgpu::Operations {
331 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
332 store: wgpu::StoreOp::Store,
333 },
334 }),
335 Some(wgpu::RenderPassColorAttachment {
336 view: &self.borrow.views.tgt_mat,
337 depth_slice: None,
338 resolve_target: None,
339 ops: wgpu::Operations {
340 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
341 store: wgpu::StoreOp::Store,
342 },
343 }),
344 ],
345 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
346 view: &self.borrow.views.tgt_depth,
347 depth_ops: Some(wgpu::Operations {
348 load: wgpu::LoadOp::Clear(0.0),
349 store: wgpu::StoreOp::Store,
350 }),
351 stencil_ops: None,
352 }),
353 timestamp_writes: None,
354 occlusion_query_set: None,
355 });
356
357 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
358 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
359
360 Some(FirstPassDrawer {
361 render_pass,
362 borrow: &self.borrow,
363 pipelines,
364 globals: self.globals,
365 })
366 }
367
368 pub fn volumetric_pass(&mut self) -> Option<VolumetricPassDrawer<'_>> {
370 let pipelines = &self.borrow.pipelines.all()?;
371 let shadow = self.borrow.shadow?;
372
373 let mut render_pass =
374 self.encoder
375 .scoped_render_pass("volumetric_pass", wgpu::RenderPassDescriptor {
376 label: Some("volumetric pass (clouds)"),
377 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
378 view: &self.borrow.views.tgt_color_pp,
379 depth_slice: None,
380 resolve_target: None,
381 ops: wgpu::Operations {
382 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
383 store: wgpu::StoreOp::Store,
384 },
385 })],
386 depth_stencil_attachment: None,
387 timestamp_writes: None,
388 occlusion_query_set: None,
389 });
390
391 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
392 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
393
394 Some(VolumetricPassDrawer {
395 render_pass,
396 borrow: &self.borrow,
397 clouds_pipeline: &pipelines.clouds,
398 })
399 }
400
401 pub fn transparent_pass(&mut self) -> Option<TransparentPassDrawer<'_>> {
403 let pipelines = &self.borrow.pipelines.all()?;
404 let shadow = self.borrow.shadow?;
405
406 let mut render_pass =
407 self.encoder
408 .scoped_render_pass("transparent_pass", wgpu::RenderPassDescriptor {
409 label: Some("transparent pass (trails)"),
410 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
411 view: &self.borrow.views.tgt_color_pp,
412 depth_slice: None,
413 resolve_target: None,
414 ops: wgpu::Operations {
415 load: wgpu::LoadOp::Load,
416 store: wgpu::StoreOp::Store,
417 },
418 })],
419 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
420 view: &self.borrow.views.tgt_depth,
421 depth_ops: Some(wgpu::Operations {
422 load: wgpu::LoadOp::Load,
423 store: wgpu::StoreOp::Store,
424 }),
425 stencil_ops: None,
426 }),
427 timestamp_writes: None,
428 occlusion_query_set: None,
429 });
430
431 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
432 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
433
434 Some(TransparentPassDrawer {
435 render_pass,
436 borrow: &self.borrow,
437 trail_pipeline: &pipelines.trail,
438 })
439 }
440
441 pub fn run_bloom_passes(&mut self) {
445 let locals = &self.borrow.locals;
446 let views = &self.borrow.views;
447
448 let bloom_pipelines = match self.borrow.pipelines.all() {
449 Some(super::Pipelines { bloom: Some(p), .. }) => p,
450 _ => return,
451 };
452
453 let (bloom_tgts, bloom_binds) =
456 match views.bloom_tgts.as_ref().zip(locals.bloom_binds.as_ref()) {
457 Some((t, b)) => (t, b),
458 None => return,
459 };
460
461 let mut encoder = self.encoder.scope("bloom");
462
463 let mut run_bloom_pass = |bind, view, label: String, pipeline, load| {
464 let pass_label = format!("bloom {} pass", label);
465 let mut render_pass = encoder.scoped_render_pass(&label, wgpu::RenderPassDescriptor {
466 label: Some(&pass_label),
467 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
468 depth_slice: None,
469 resolve_target: None,
470 view,
471 ops: wgpu::Operations {
472 store: wgpu::StoreOp::Store,
473 load,
474 },
475 })],
476 depth_stencil_attachment: None,
477 timestamp_writes: None,
478 occlusion_query_set: None,
479 });
480
481 render_pass.set_bind_group(0, bind, &[]);
482 render_pass.set_pipeline(pipeline);
483 render_pass.draw(0..3, 0..1);
484 };
485
486 (0..bloom::NUM_SIZES - 1).for_each(|index| {
488 let bind = &bloom_binds[index].bind_group;
489 let view = &bloom_tgts[index + 1];
490 let (label, pipeline) = if index == 0 {
496 (
497 format!("downsample filtered {}", index + 1),
498 &bloom_pipelines.downsample_filtered,
499 )
500 } else {
501 (
502 format!("downsample {}", index + 1),
503 &bloom_pipelines.downsample,
504 )
505 };
506 run_bloom_pass(
507 bind,
508 view,
509 label,
510 pipeline,
511 wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
512 );
513 });
514
515 (0..bloom::NUM_SIZES - 1).for_each(|index| {
517 let bind = &bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group;
518 let view = &bloom_tgts[bloom::NUM_SIZES - 2 - index];
519 let label = format!("upsample {}", index + 1);
520 run_bloom_pass(
521 bind,
522 view,
523 label,
524 &bloom_pipelines.upsample,
525 if index + 2 == bloom::NUM_SIZES {
526 wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT)
528 } else {
529 wgpu::LoadOp::Load
532 },
533 );
534 });
535 }
536
537 fn run_ui_premultiply_passes(&mut self) {
540 prof_span!("run_ui_premultiply_passes");
541 let Some(premultiply_alpha) = self.borrow.pipelines.premultiply_alpha() else {
542 return;
543 };
544
545 let targets = self.borrow.ui_premultiply_uploads.take();
546
547 for (i, (target_texture, uploads)) in targets.into_iter().enumerate() {
548 prof_span!("ui premultiply pass");
549 let profile_name = format!("{UI_PREMULTIPLY_PASS} {i}");
550 let label = format!("ui premultiply pass {i}");
551 let mut render_pass =
552 self.encoder
553 .scoped_render_pass(&profile_name, wgpu::RenderPassDescriptor {
554 label: Some(&label),
555 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
556 view: &target_texture.view,
557 depth_slice: None,
558 resolve_target: None,
559 ops: wgpu::Operations {
560 load: wgpu::LoadOp::Load,
561 store: wgpu::StoreOp::Store,
562 },
563 })],
564 depth_stencil_attachment: None,
565 timestamp_writes: None,
566 occlusion_query_set: None,
567 });
568 render_pass.set_pipeline(&premultiply_alpha.pipeline);
569 for upload in &uploads {
570 let (source_bind_group, push_constant_data) = upload.draw_data(&target_texture);
571 let bytes = bytemuck::bytes_of(&push_constant_data);
572 render_pass.set_bind_group(0, source_bind_group, &[]);
573 render_pass.set_push_constants(wgpu::ShaderStages::VERTEX, 0, bytes);
574 render_pass.draw(0..6, 0..1);
575 }
576 }
577 }
578
579 pub fn third_pass(&mut self) -> ThirdPassDrawer<'_> {
584 self.run_ui_premultiply_passes();
585
586 let mut render_pass =
587 self.encoder
588 .scoped_render_pass("third_pass", wgpu::RenderPassDescriptor {
589 label: Some("third pass (postprocess + ui)"),
590 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
591 view: self
594 .taking_screenshot
595 .as_ref()
596 .map_or(&self.surface_view, |s| s.texture_view()),
597 depth_slice: None,
598 resolve_target: None,
599 ops: wgpu::Operations {
600 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
601 store: wgpu::StoreOp::Store,
602 },
603 })],
604 depth_stencil_attachment: None,
605 timestamp_writes: None,
606 occlusion_query_set: None,
607 });
608
609 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
610
611 ThirdPassDrawer {
612 render_pass,
613 borrow: &self.borrow,
614 }
615 }
616
617 #[cfg(feature = "egui-ui")]
618 pub fn draw_egui(
619 &mut self,
620 state: &mut egui_winit::State,
621 scale_factor: f32,
622 ) -> egui::PlatformOutput {
623 span!(guard, "Draw egui");
624
625 let output = state.egui_ctx().end_pass();
626
627 let paint_jobs = state.egui_ctx().tessellate(output.shapes, scale_factor);
628
629 let screen_descriptor = ScreenDescriptor {
630 size_in_pixels: [
631 self.borrow.surface_config.width,
632 self.borrow.surface_config.height,
633 ],
634 pixels_per_point: scale_factor,
635 };
636
637 for (id, delta) in output.textures_delta.set.iter() {
638 self.borrow.egui_renderer.update_texture(
639 self.borrow.device,
640 self.borrow.queue,
641 *id,
642 delta,
643 );
644 }
645
646 let _ = self.borrow.egui_renderer.update_buffers(
649 self.borrow.device,
650 self.borrow.queue,
651 self.encoder.encoder(),
652 &paint_jobs,
653 &screen_descriptor,
654 );
655
656 let mut render_pass = self
657 .encoder
658 .encoder()
659 .begin_render_pass(&wgpu::RenderPassDescriptor {
660 label: Some("egui pass"),
661 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
662 view: self
663 .taking_screenshot
664 .as_ref()
665 .map_or(&self.surface_view, |s| s.texture_view()),
666 depth_slice: None,
667 resolve_target: None,
668 ops: wgpu::Operations {
669 load: wgpu::LoadOp::Load,
670 store: wgpu::StoreOp::Store,
671 },
672 })],
673 depth_stencil_attachment: None,
674 timestamp_writes: None,
675 occlusion_query_set: None,
676 })
677 .forget_lifetime();
678
679 self.borrow
680 .egui_renderer
681 .render(&mut render_pass, &paint_jobs, &screen_descriptor);
682
683 for id in output.textures_delta.free.iter() {
684 self.borrow.egui_renderer.free_texture(id);
685 }
686
687 drop(guard);
688 output.platform_output
689 }
690
691 pub fn draw_point_shadows<'data>(
694 &mut self,
695 matrices: &[shadow::PointLightMatrix; 126],
696 chunks: impl Clone
697 + Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
698 ) {
699 if !self.borrow.pipeline_modes.shadow.is_map() {
700 return;
701 }
702
703 if let Some(ShadowMap::Enabled(shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) {
704 let mut encoder = self.encoder.scope("point shadows");
705 const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
706 let data = bytemuck::cast_slice(matrices);
707
708 for face in 0..6 {
709 let view =
711 shadow_renderer
712 .point_depth
713 .tex
714 .create_view(&wgpu::TextureViewDescriptor {
715 label: Some("Point shadow cubemap face"),
716 format: None,
717 dimension: Some(wgpu::TextureViewDimension::D2),
718 usage: None,
719 aspect: wgpu::TextureAspect::DepthOnly,
720 base_mip_level: 0,
721 mip_level_count: None,
722 base_array_layer: face,
723 array_layer_count: Some(1),
724 });
725
726 let label = format!("point shadow face-{} pass", face);
727 let mut render_pass =
728 encoder.scoped_render_pass(&label, wgpu::RenderPassDescriptor {
729 label: Some(&label),
730 color_attachments: &[],
731 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
732 view: &view,
733 depth_ops: Some(wgpu::Operations {
734 load: wgpu::LoadOp::Clear(1.0),
735 store: wgpu::StoreOp::Store,
736 }),
737 stencil_ops: None,
738 }),
739 timestamp_writes: None,
740 occlusion_query_set: None,
741 });
742
743 render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline);
744 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
745 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
746
747 (0..1).for_each(|point_light| {
748 render_pass.set_push_constants(
749 wgpu::ShaderStages::VERTEX_FRAGMENT,
750 0,
751 &data[(6 * (point_light + 1) * STRIDE + face as usize * STRIDE)
752 ..(6 * (point_light + 1) * STRIDE + (face + 1) as usize * STRIDE)],
753 );
754 chunks.clone().for_each(|(model, locals)| {
755 render_pass.set_bind_group(1, &locals.bind_group, &[]);
756 render_pass.set_vertex_buffer(0, model.buf().slice(..));
757 render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
758 });
759 });
760 }
761 }
762 }
763
764 pub fn clear_shadows(&mut self) {
775 if let Some(ShadowMap::Enabled(shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) {
776 let _ = self.encoder.scoped_render_pass(
777 "clear_directed_shadow",
778 wgpu::RenderPassDescriptor {
779 label: Some("clear directed shadow pass"),
780 color_attachments: &[],
781 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
782 view: &shadow_renderer.directed_depth.view,
783 depth_ops: Some(wgpu::Operations {
784 load: wgpu::LoadOp::Clear(1.0),
785 store: wgpu::StoreOp::Store,
786 }),
787 stencil_ops: None,
788 }),
789 timestamp_writes: None,
790 occlusion_query_set: None,
791 },
792 );
793
794 for face in 0..6 {
795 let view =
797 shadow_renderer
798 .point_depth
799 .tex
800 .create_view(&wgpu::TextureViewDescriptor {
801 label: Some("Point shadow cubemap face"),
802 format: None,
803 dimension: Some(wgpu::TextureViewDimension::D2),
804 usage: None,
805 aspect: wgpu::TextureAspect::DepthOnly,
806 base_mip_level: 0,
807 mip_level_count: None,
808 base_array_layer: face,
809 array_layer_count: Some(1),
810 });
811
812 let label = format!("clear point shadow face-{} pass", face);
813 let _ = self
814 .encoder
815 .scoped_render_pass(&label, wgpu::RenderPassDescriptor {
816 label: Some(&label),
817 color_attachments: &[],
818 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
819 view: &view,
820 depth_ops: Some(wgpu::Operations {
821 load: wgpu::LoadOp::Clear(1.0),
822 store: wgpu::StoreOp::Store,
823 }),
824 stencil_ops: None,
825 }),
826 timestamp_writes: None,
827 occlusion_query_set: None,
828 });
829 }
830 }
831 }
832}
833
834impl Drop for Drawer<'_> {
835 fn drop(&mut self) {
836 let download_and_handle_screenshot = self
840 .taking_screenshot
841 .take()
842 .zip(self.borrow.pipelines.blit())
843 .map(|(screenshot, blit)| {
844 let mut render_pass = self.encoder.scoped_render_pass(
846 "screenshot blit",
847 wgpu::RenderPassDescriptor {
848 label: Some("Blit screenshot pass"),
849 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
850 view: &self.surface_view,
851 depth_slice: None,
852 resolve_target: None,
853 ops: wgpu::Operations {
854 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
855 store: wgpu::StoreOp::Store,
856 },
857 })],
858 depth_stencil_attachment: None,
859 timestamp_writes: None,
860 occlusion_query_set: None,
861 },
862 );
863 render_pass.set_pipeline(&blit.pipeline);
864 render_pass.set_bind_group(0, screenshot.bind_group(), &[]);
865 render_pass.draw(0..3, 0..1);
866 drop(render_pass);
867 screenshot.copy_to_buffer(self.encoder.encoder())
871 });
872
873 let (profiler, mut encoder) = self.encoder.end_query();
874 profiler.resolve_queries(&mut encoder);
875
876 self.borrow.queue.submit(std::iter::once(encoder.finish()));
878 if let Some(f) = download_and_handle_screenshot {
881 f();
882 }
883 self.surface_texture.take().unwrap().present();
884
885 profiler
886 .end_frame()
887 .expect("Gpu profiler error! Maybe there was an unclosed scope?");
888 }
889}
890
891#[must_use]
893pub struct ShadowPassDrawer<'pass> {
894 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
895 borrow: &'pass RendererBorrow<'pass>,
896 shadow_renderer: &'pass ShadowMapRenderer,
897}
898
899impl<'pass> ShadowPassDrawer<'pass> {
900 pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
901 let mut render_pass = self.render_pass.scope("directed_figure_shadows");
902
903 render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
904 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
905
906 FigureShadowDrawer { render_pass }
907 }
908
909 pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
910 let mut render_pass = self.render_pass.scope("directed_terrain_shadows");
911
912 render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
913 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
914
915 TerrainShadowDrawer { render_pass }
916 }
917
918 pub fn draw_debug_shadows(&mut self) -> DebugShadowDrawer<'_, 'pass> {
919 let mut render_pass = self.render_pass.scope("directed_debug_shadows");
920
921 render_pass.set_pipeline(&self.shadow_renderer.debug_directed_pipeline.pipeline);
922 set_quad_index_buffer::<debug::Vertex>(&mut render_pass, self.borrow);
923
924 DebugShadowDrawer { render_pass }
925 }
926}
927
928#[must_use]
929pub struct RainOcclusionPassDrawer<'pass> {
930 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
931 borrow: &'pass RendererBorrow<'pass>,
932 rain_occlusion_renderer: &'pass RainOcclusionMapRenderer,
933}
934
935impl<'pass> RainOcclusionPassDrawer<'pass> {
936 pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
937 let mut render_pass = self.render_pass.scope("directed_figure_rain_occlusion");
938
939 render_pass.set_pipeline(&self.rain_occlusion_renderer.figure_pipeline.pipeline);
940 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
941
942 FigureShadowDrawer { render_pass }
943 }
944
945 pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
946 let mut render_pass = self.render_pass.scope("directed_terrain_rain_occlusion");
947
948 render_pass.set_pipeline(&self.rain_occlusion_renderer.terrain_pipeline.pipeline);
949 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
950
951 TerrainShadowDrawer { render_pass }
952 }
953}
954
955#[must_use]
956pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
957 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
958}
959
960impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
961 pub fn draw<'data: 'pass>(
962 &mut self,
963 model: SubModel<'data, terrain::Vertex>,
964 locals: &'data figure::BoundLocals,
965 ) {
966 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
967 self.render_pass.set_vertex_buffer(0, model.buf());
968 self.render_pass
969 .draw_indexed(0..model.len() / 4 * 6, 0, 0..1);
970 }
971}
972
973#[must_use]
974pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
975 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
976}
977
978impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
979 pub fn draw<'data: 'pass>(
980 &mut self,
981 model: &'data Model<terrain::Vertex>,
982 locals: &'data terrain::BoundLocals,
983 alt_indices: &'data AltIndices,
984 culling_mode: CullingMode,
985 ) {
986 let index_range = match culling_mode {
987 CullingMode::Underground => return, CullingMode::Surface => alt_indices.deep_end as u32..model.len() as u32,
991 CullingMode::None => 0..model.len() as u32,
992 };
993
994 if index_range.is_empty() {
996 return;
997 }
998
999 let submodel = model.submodel(index_range);
1000
1001 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
1002 self.render_pass.set_vertex_buffer(0, submodel.buf());
1003 self.render_pass
1004 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1005 }
1006}
1007
1008#[must_use]
1009pub struct DebugShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
1010 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1011}
1012
1013impl<'pass_ref, 'pass: 'pass_ref> DebugShadowDrawer<'pass_ref, 'pass> {
1014 pub fn draw<'data: 'pass>(
1015 &mut self,
1016 model: &'data Model<debug::Vertex>,
1017 locals: &'data debug::BoundLocals,
1018 ) {
1019 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
1020 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1021 self.render_pass.draw(0..model.len() as u32, 0..1);
1022 }
1023}
1024
1025#[must_use]
1027pub struct FirstPassDrawer<'pass> {
1028 pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1029 borrow: &'pass RendererBorrow<'pass>,
1030 pipelines: &'pass super::Pipelines,
1031 globals: &'pass GlobalsBindGroup,
1032}
1033
1034impl<'pass> FirstPassDrawer<'pass> {
1035 pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
1036 let mut render_pass = self.render_pass.scope("skybox");
1037
1038 render_pass.set_pipeline(&self.pipelines.skybox.pipeline);
1039 set_quad_index_buffer::<skybox::Vertex>(&mut render_pass, self.borrow);
1040 render_pass.set_vertex_buffer(0, model.buf().slice(..));
1041 render_pass.draw(0..model.len() as u32, 0..1);
1042 }
1043
1044 pub fn draw_debug(&mut self) -> DebugDrawer<'_, 'pass> {
1045 let mut render_pass = self.render_pass.scope("debug");
1046
1047 render_pass.set_pipeline(&self.pipelines.debug.pipeline);
1048 set_quad_index_buffer::<debug::Vertex>(&mut render_pass, self.borrow);
1049
1050 DebugDrawer { render_pass }
1051 }
1052
1053 pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model<lod_terrain::Vertex>) {
1054 let mut render_pass = self.render_pass.scope("lod_terrain");
1055
1056 render_pass.set_pipeline(&self.pipelines.lod_terrain.pipeline);
1057 set_quad_index_buffer::<lod_terrain::Vertex>(&mut render_pass, self.borrow);
1058 render_pass.set_vertex_buffer(0, model.buf().slice(..));
1059 render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1060 }
1061
1062 pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
1063 let mut render_pass = self.render_pass.scope("figures");
1064
1065 render_pass.set_pipeline(&self.pipelines.figure.pipeline);
1066 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
1068
1069 FigureDrawer { render_pass }
1070 }
1071
1072 pub fn draw_terrain(&mut self) -> TerrainDrawer<'_, 'pass> {
1073 let mut render_pass = self.render_pass.scope("terrain");
1074
1075 render_pass.set_pipeline(&self.pipelines.terrain.pipeline);
1076 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
1077
1078 TerrainDrawer {
1079 render_pass,
1080 atlas_textures: None,
1081 }
1082 }
1083
1084 pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
1085 let mut render_pass = self.render_pass.scope("particles");
1086
1087 render_pass.set_pipeline(&self.pipelines.particle.pipeline);
1088 set_quad_index_buffer::<particle::Vertex>(&mut render_pass, self.borrow);
1089
1090 ParticleDrawer { render_pass }
1091 }
1092
1093 pub fn draw_ropes(&mut self) -> RopeDrawer<'_, 'pass> {
1094 let mut render_pass = self.render_pass.scope("ropes");
1095
1096 render_pass.set_pipeline(&self.pipelines.rope.pipeline);
1097 set_quad_index_buffer::<rope::Vertex>(&mut render_pass, self.borrow);
1098
1099 RopeDrawer { render_pass }
1100 }
1101
1102 pub fn draw_sprites<'data: 'pass>(
1103 &mut self,
1104 globals: &'data sprite::SpriteGlobalsBindGroup,
1105 atlas_textures: &'data AtlasTextures<sprite::Locals, FigureSpriteAtlasData>,
1106 ) -> SpriteDrawer<'_, 'pass> {
1107 let mut render_pass = self.render_pass.scope("sprites");
1108
1109 render_pass.set_pipeline(&self.pipelines.sprite.pipeline);
1110 set_quad_index_buffer::<sprite::Vertex>(&mut render_pass, self.borrow);
1111 render_pass.set_bind_group(0, &globals.bind_group, &[]);
1112 render_pass.set_bind_group(2, &atlas_textures.bind_group, &[]);
1113
1114 SpriteDrawer {
1115 render_pass,
1116 globals: self.globals,
1117 }
1118 }
1119
1120 pub fn draw_lod_objects(&mut self) -> LodObjectDrawer<'_, 'pass> {
1121 let mut render_pass = self.render_pass.scope("lod objects");
1122
1123 render_pass.set_pipeline(&self.pipelines.lod_object.pipeline);
1124 set_quad_index_buffer::<lod_object::Vertex>(&mut render_pass, self.borrow);
1125
1126 LodObjectDrawer { render_pass }
1127 }
1128
1129 pub fn draw_fluid(&mut self) -> FluidDrawer<'_, 'pass> {
1130 let mut render_pass = self.render_pass.scope("fluid");
1131
1132 render_pass.set_pipeline(&self.pipelines.fluid.pipeline);
1133 set_quad_index_buffer::<fluid::Vertex>(&mut render_pass, self.borrow);
1134
1135 FluidDrawer { render_pass }
1136 }
1137}
1138
1139#[must_use]
1140pub struct DebugDrawer<'pass_ref, 'pass: 'pass_ref> {
1141 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1142}
1143
1144impl<'pass_ref, 'pass: 'pass_ref> DebugDrawer<'pass_ref, 'pass> {
1145 pub fn draw<'data: 'pass>(
1146 &mut self,
1147 model: &'data Model<debug::Vertex>,
1148 locals: &'data debug::BoundLocals,
1149 ) {
1150 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1151 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1152 self.render_pass.draw(0..model.len() as u32, 0..1);
1153 }
1154}
1155
1156#[must_use]
1157pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
1158 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1159}
1160
1161impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
1162 pub fn draw<'data: 'pass>(
1163 &mut self,
1164 model: SubModel<'data, terrain::Vertex>,
1165 locals: &'data figure::BoundLocals,
1166 atlas_textures: &'data AtlasTextures<figure::Locals, FigureSpriteAtlasData>,
1168 ) {
1169 self.render_pass
1170 .set_bind_group(2, &atlas_textures.bind_group, &[]);
1171 self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
1172 self.render_pass.set_vertex_buffer(0, model.buf());
1173 self.render_pass
1174 .draw_indexed(0..model.len() / 4 * 6, 0, 0..1);
1175 }
1176}
1177
1178#[must_use]
1179pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
1180 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1181 atlas_textures: Option<&'pass_ref Arc<AtlasTextures<terrain::Locals, TerrainAtlasData>>>,
1182}
1183
1184impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
1185 pub fn draw<'data: 'pass>(
1186 &mut self,
1187 model: &'data Model<terrain::Vertex>,
1188 atlas_textures: &'data Arc<AtlasTextures<terrain::Locals, TerrainAtlasData>>,
1189 locals: &'data terrain::BoundLocals,
1190 alt_indices: &'data AltIndices,
1191 culling_mode: CullingMode,
1192 ) {
1193 let index_range = match culling_mode {
1194 CullingMode::Underground => 0..alt_indices.underground_end as u32,
1195 CullingMode::Surface => alt_indices.deep_end as u32..model.len() as u32,
1196 CullingMode::None => 0..model.len() as u32,
1197 };
1198
1199 if index_range.is_empty() {
1201 return;
1202 }
1203
1204 let submodel = model.submodel(index_range);
1205
1206 if self.atlas_textures
1207 .filter(|current_atlas_textures| Arc::ptr_eq(current_atlas_textures, atlas_textures))
1210 .is_none()
1211 {
1212 self.render_pass
1213 .set_bind_group(2, &atlas_textures.bind_group, &[]);
1214 self.atlas_textures = Some(atlas_textures);
1215 };
1216
1217 self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
1218
1219 self.render_pass.set_vertex_buffer(0, submodel.buf());
1220 self.render_pass
1221 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1222 }
1223}
1224
1225#[must_use]
1226pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
1227 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1228}
1229
1230impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
1231 pub fn draw<'data: 'pass>(
1234 &mut self,
1235 model: &'data Model<particle::Vertex>,
1236 instances: &'data Instances<particle::Instance>,
1237 ) {
1238 if instances.count() != 0 {
1239 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1240 self.render_pass
1241 .set_vertex_buffer(1, instances.buf().slice(..));
1242 self.render_pass
1243 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32);
1245 }
1246 }
1247}
1248
1249#[must_use]
1250pub struct RopeDrawer<'pass_ref, 'pass: 'pass_ref> {
1251 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1252}
1253
1254impl<'pass_ref, 'pass: 'pass_ref> RopeDrawer<'pass_ref, 'pass> {
1255 pub fn draw<'data: 'pass>(
1258 &mut self,
1259 model: &'data Model<rope::Vertex>,
1260 locals: &'data rope::BoundLocals,
1261 ) {
1262 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1263 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1264 self.render_pass
1267 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1268 }
1269}
1270
1271#[must_use]
1272pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
1273 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1274 globals: &'pass GlobalsBindGroup,
1275}
1276
1277impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
1278 pub fn draw<'data: 'pass, T>(
1279 &mut self,
1280 terrain_locals: &'data Bound<T>,
1281 instances: &'data Instances<sprite::Instance>,
1282 alt_indices: &'data AltIndices,
1283 culling_mode: CullingMode,
1284 ) {
1285 let instance_range = match culling_mode {
1286 CullingMode::Underground => 0..alt_indices.underground_end as u32,
1287 CullingMode::Surface => alt_indices.deep_end as u32..instances.count() as u32,
1288 CullingMode::None => 0..instances.count() as u32,
1289 };
1290
1291 if instance_range.is_empty() {
1293 return;
1294 }
1295
1296 self.render_pass
1297 .set_bind_group(3, &terrain_locals.bind_group, &[]);
1298
1299 let subinstances = instances.subinstances(instance_range);
1300
1301 self.render_pass.set_vertex_buffer(0, subinstances.buf());
1302 self.render_pass.draw_indexed(
1303 0..sprite::VERT_PAGE_SIZE / 4 * 6,
1304 0,
1305 0..subinstances.count(),
1306 );
1307 }
1308}
1309
1310impl<'pass_ref, 'pass: 'pass_ref> Drop for SpriteDrawer<'pass_ref, 'pass> {
1311 fn drop(&mut self) {
1312 self.render_pass
1314 .set_bind_group(0, &self.globals.bind_group, &[]);
1315 }
1316}
1317
1318#[must_use]
1319pub struct LodObjectDrawer<'pass_ref, 'pass: 'pass_ref> {
1320 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1321}
1322
1323impl<'pass_ref, 'pass: 'pass_ref> LodObjectDrawer<'pass_ref, 'pass> {
1324 pub fn draw<'data: 'pass>(
1325 &mut self,
1326 model: &'data Model<lod_object::Vertex>,
1327 instances: &'data Instances<lod_object::Instance>,
1328 ) {
1329 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1330 self.render_pass
1331 .set_vertex_buffer(1, instances.buf().slice(..));
1332 self.render_pass
1333 .draw(0..model.len() as u32, 0..instances.count() as u32);
1334 }
1335}
1336
1337#[must_use]
1338pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
1339 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1340}
1341
1342impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
1343 pub fn draw<'data: 'pass>(
1344 &mut self,
1345 model: &'data Model<fluid::Vertex>,
1346 locals: &'data terrain::BoundLocals,
1347 ) {
1348 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1349 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1350 self.render_pass
1351 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1352 }
1353}
1354
1355#[must_use]
1357pub struct VolumetricPassDrawer<'pass> {
1358 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1359 borrow: &'pass RendererBorrow<'pass>,
1360 clouds_pipeline: &'pass clouds::CloudsPipeline,
1361}
1362
1363impl VolumetricPassDrawer<'_> {
1364 pub fn draw_clouds(&mut self) {
1365 self.render_pass
1366 .set_pipeline(&self.clouds_pipeline.pipeline);
1367 self.render_pass
1368 .set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]);
1369 self.render_pass.draw(0..3, 0..1);
1370 }
1371}
1372
1373#[must_use]
1375pub struct TransparentPassDrawer<'pass> {
1376 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1377 borrow: &'pass RendererBorrow<'pass>,
1378 trail_pipeline: &'pass trail::TrailPipeline,
1379}
1380
1381impl<'pass> TransparentPassDrawer<'pass> {
1382 pub fn draw_trails(&mut self) -> Option<TrailDrawer<'_, 'pass>> {
1383 let shadow = &self.borrow.shadow?;
1384
1385 let mut render_pass = self.render_pass.scope("trails");
1386
1387 render_pass.set_pipeline(&self.trail_pipeline.pipeline);
1388 set_quad_index_buffer::<trail::Vertex>(&mut render_pass, self.borrow);
1389
1390 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
1391
1392 Some(TrailDrawer { render_pass })
1393 }
1394}
1395
1396#[must_use]
1397pub struct TrailDrawer<'pass_ref, 'pass: 'pass_ref> {
1398 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1399}
1400
1401impl<'pass_ref, 'pass: 'pass_ref> TrailDrawer<'pass_ref, 'pass> {
1402 pub fn draw(&mut self, submodel: SubModel<'pass, trail::Vertex>) {
1403 self.render_pass.set_vertex_buffer(0, submodel.buf());
1404 self.render_pass
1405 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1406 }
1407}
1408
1409#[must_use]
1411pub struct ThirdPassDrawer<'pass> {
1412 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1413 borrow: &'pass RendererBorrow<'pass>,
1414}
1415
1416impl<'pass> ThirdPassDrawer<'pass> {
1417 pub fn draw_postprocess(&mut self) {
1419 let postprocess = match self.borrow.pipelines.all() {
1420 Some(p) => &p.postprocess,
1421 None => return,
1422 };
1423
1424 let mut render_pass = self.render_pass.scope("postprocess");
1425 render_pass.set_pipeline(&postprocess.pipeline);
1426 render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]);
1427 render_pass.draw(0..3, 0..1);
1428 }
1429
1430 pub fn draw_ui(&mut self) -> Option<UiDrawer<'_, 'pass>> {
1433 let ui = self.borrow.pipelines.ui()?;
1434
1435 let mut render_pass = self.render_pass.scope("ui");
1436 render_pass.set_pipeline(&ui.pipeline);
1437 set_quad_index_buffer::<ui::Vertex>(&mut render_pass, self.borrow);
1438
1439 Some(UiDrawer { render_pass })
1440 }
1441}
1442
1443#[must_use]
1444pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
1445 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1446}
1447
1448#[must_use]
1449pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
1450 render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
1451}
1452
1453impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
1454 pub fn prepare<'data: 'pass>(
1458 &mut self,
1459 locals: &'data ui::BoundLocals,
1460 buf: &'data DynamicModel<ui::Vertex>,
1461 scissor: Aabr<u16>,
1462 ) -> PreparedUiDrawer<'_, 'pass> {
1463 let mut prepared = PreparedUiDrawer {
1466 render_pass: &mut self.render_pass,
1467 };
1468 prepared.set_locals(locals);
1470 prepared.set_model(buf);
1471 prepared.set_scissor(scissor);
1472
1473 prepared
1474 }
1475}
1476
1477impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
1478 pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) {
1479 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
1480 }
1481
1482 pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel<ui::Vertex>) {
1483 self.render_pass.set_vertex_buffer(0, model.buf().slice(..))
1484 }
1485
1486 pub fn set_scissor(&mut self, scissor: Aabr<u16>) {
1487 let Aabr { min, max } = scissor;
1488 self.render_pass.set_scissor_rect(
1489 min.x as u32,
1490 min.y as u32,
1491 (max.x - min.x) as u32,
1492 (max.y - min.y) as u32,
1493 );
1494 }
1495
1496 pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) {
1497 self.render_pass.set_bind_group(2, &texture.bind_group, &[]);
1498 self.render_pass.draw(verts, 0..1);
1499 }
1500}
1501
1502fn set_quad_index_buffer<'a, V: super::Vertex>(
1503 pass: &mut wgpu::RenderPass<'a>,
1504 borrow: &RendererBorrow<'a>,
1505) {
1506 if let Some(format) = V::QUADS_INDEX {
1507 let slice = match format {
1508 wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..),
1509 wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..),
1510 };
1511
1512 pass.set_index_buffer(slice, format);
1513 }
1514}