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 let RainOcclusionMap::Enabled(ref rain_occlusion_renderer) = self.borrow.shadow?.rain_map
242 {
243 let mut render_pass = self.encoder.scoped_render_pass(
244 "rain_occlusion_pass",
245 wgpu::RenderPassDescriptor {
246 label: Some("rain occlusion pass"),
247 color_attachments: &[],
248 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
249 view: &rain_occlusion_renderer.depth.view,
250 depth_ops: Some(wgpu::Operations {
251 load: wgpu::LoadOp::Clear(1.0),
252 store: wgpu::StoreOp::Store,
253 }),
254 stencil_ops: None,
255 }),
256 timestamp_writes: None,
257 occlusion_query_set: None,
258 },
259 );
260
261 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
262
263 Some(RainOcclusionPassDrawer {
264 render_pass,
265 borrow: &self.borrow,
266 rain_occlusion_renderer,
267 })
268 } else {
269 None
270 }
271 }
272
273 pub fn shadow_pass(&mut self) -> Option<ShadowPassDrawer<'_>> {
276 if !self.borrow.pipeline_modes.shadow.is_map() {
277 return None;
278 }
279
280 if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow?.map {
281 let mut render_pass =
282 self.encoder
283 .scoped_render_pass("shadow_pass", wgpu::RenderPassDescriptor {
284 label: Some("shadow pass"),
285 color_attachments: &[],
286 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
287 view: &shadow_renderer.directed_depth.view,
288 depth_ops: Some(wgpu::Operations {
289 load: wgpu::LoadOp::Clear(1.0),
290 store: wgpu::StoreOp::Store,
291 }),
292 stencil_ops: None,
293 }),
294 timestamp_writes: None,
295 occlusion_query_set: None,
296 });
297
298 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
299
300 Some(ShadowPassDrawer {
301 render_pass,
302 borrow: &self.borrow,
303 shadow_renderer,
304 })
305 } else {
306 None
307 }
308 }
309
310 pub fn first_pass(&mut self) -> Option<FirstPassDrawer<'_>> {
312 let pipelines = self.borrow.pipelines.all()?;
313 let shadow = self.borrow.shadow?;
316
317 let mut render_pass =
318 self.encoder
319 .scoped_render_pass("first_pass", wgpu::RenderPassDescriptor {
320 label: Some("first pass"),
321 color_attachments: &[
322 Some(wgpu::RenderPassColorAttachment {
323 view: &self.borrow.views.tgt_color,
324 depth_slice: None,
325 resolve_target: None,
326 ops: wgpu::Operations {
327 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
328 store: wgpu::StoreOp::Store,
329 },
330 }),
331 Some(wgpu::RenderPassColorAttachment {
332 view: &self.borrow.views.tgt_mat,
333 depth_slice: None,
334 resolve_target: None,
335 ops: wgpu::Operations {
336 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
337 store: wgpu::StoreOp::Store,
338 },
339 }),
340 ],
341 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
342 view: &self.borrow.views.tgt_depth,
343 depth_ops: Some(wgpu::Operations {
344 load: wgpu::LoadOp::Clear(0.0),
345 store: wgpu::StoreOp::Store,
346 }),
347 stencil_ops: None,
348 }),
349 timestamp_writes: None,
350 occlusion_query_set: None,
351 });
352
353 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
354 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
355
356 Some(FirstPassDrawer {
357 render_pass,
358 borrow: &self.borrow,
359 pipelines,
360 globals: self.globals,
361 })
362 }
363
364 pub fn volumetric_pass(&mut self) -> Option<VolumetricPassDrawer<'_>> {
366 let pipelines = &self.borrow.pipelines.all()?;
367 let shadow = self.borrow.shadow?;
368
369 let mut render_pass =
370 self.encoder
371 .scoped_render_pass("volumetric_pass", wgpu::RenderPassDescriptor {
372 label: Some("volumetric pass (clouds)"),
373 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
374 view: &self.borrow.views.tgt_color_pp,
375 depth_slice: None,
376 resolve_target: None,
377 ops: wgpu::Operations {
378 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
379 store: wgpu::StoreOp::Store,
380 },
381 })],
382 depth_stencil_attachment: None,
383 timestamp_writes: None,
384 occlusion_query_set: None,
385 });
386
387 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
388 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
389
390 Some(VolumetricPassDrawer {
391 render_pass,
392 borrow: &self.borrow,
393 clouds_pipeline: &pipelines.clouds,
394 })
395 }
396
397 pub fn transparent_pass(&mut self) -> Option<TransparentPassDrawer<'_>> {
399 let pipelines = &self.borrow.pipelines.all()?;
400 let shadow = self.borrow.shadow?;
401
402 let mut render_pass =
403 self.encoder
404 .scoped_render_pass("transparent_pass", wgpu::RenderPassDescriptor {
405 label: Some("transparent pass (trails)"),
406 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
407 view: &self.borrow.views.tgt_color_pp,
408 depth_slice: None,
409 resolve_target: None,
410 ops: wgpu::Operations {
411 load: wgpu::LoadOp::Load,
412 store: wgpu::StoreOp::Store,
413 },
414 })],
415 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
416 view: &self.borrow.views.tgt_depth,
417 depth_ops: Some(wgpu::Operations {
418 load: wgpu::LoadOp::Load,
419 store: wgpu::StoreOp::Store,
420 }),
421 stencil_ops: None,
422 }),
423 timestamp_writes: None,
424 occlusion_query_set: None,
425 });
426
427 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
428 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
429
430 Some(TransparentPassDrawer {
431 render_pass,
432 borrow: &self.borrow,
433 trail_pipeline: &pipelines.trail,
434 })
435 }
436
437 pub fn run_bloom_passes(&mut self) {
441 let locals = &self.borrow.locals;
442 let views = &self.borrow.views;
443
444 let bloom_pipelines = match self.borrow.pipelines.all() {
445 Some(super::Pipelines { bloom: Some(p), .. }) => p,
446 _ => return,
447 };
448
449 let (bloom_tgts, bloom_binds) =
452 match views.bloom_tgts.as_ref().zip(locals.bloom_binds.as_ref()) {
453 Some((t, b)) => (t, b),
454 None => return,
455 };
456
457 let mut encoder = self.encoder.scope("bloom");
458
459 let mut run_bloom_pass = |bind, view, label: String, pipeline, load| {
460 let pass_label = format!("bloom {} pass", label);
461 let mut render_pass = encoder.scoped_render_pass(&label, wgpu::RenderPassDescriptor {
462 label: Some(&pass_label),
463 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
464 depth_slice: None,
465 resolve_target: None,
466 view,
467 ops: wgpu::Operations {
468 store: wgpu::StoreOp::Store,
469 load,
470 },
471 })],
472 depth_stencil_attachment: None,
473 timestamp_writes: None,
474 occlusion_query_set: None,
475 });
476
477 render_pass.set_bind_group(0, bind, &[]);
478 render_pass.set_pipeline(pipeline);
479 render_pass.draw(0..3, 0..1);
480 };
481
482 (0..bloom::NUM_SIZES - 1).for_each(|index| {
484 let bind = &bloom_binds[index].bind_group;
485 let view = &bloom_tgts[index + 1];
486 let (label, pipeline) = if index == 0 {
492 (
493 format!("downsample filtered {}", index + 1),
494 &bloom_pipelines.downsample_filtered,
495 )
496 } else {
497 (
498 format!("downsample {}", index + 1),
499 &bloom_pipelines.downsample,
500 )
501 };
502 run_bloom_pass(
503 bind,
504 view,
505 label,
506 pipeline,
507 wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
508 );
509 });
510
511 (0..bloom::NUM_SIZES - 1).for_each(|index| {
513 let bind = &bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group;
514 let view = &bloom_tgts[bloom::NUM_SIZES - 2 - index];
515 let label = format!("upsample {}", index + 1);
516 run_bloom_pass(
517 bind,
518 view,
519 label,
520 &bloom_pipelines.upsample,
521 if index + 2 == bloom::NUM_SIZES {
522 wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT)
524 } else {
525 wgpu::LoadOp::Load
528 },
529 );
530 });
531 }
532
533 fn run_ui_premultiply_passes(&mut self) {
536 prof_span!("run_ui_premultiply_passes");
537 let Some(premultiply_alpha) = self.borrow.pipelines.premultiply_alpha() else {
538 return;
539 };
540
541 let targets = self.borrow.ui_premultiply_uploads.take();
542
543 for (i, (target_texture, uploads)) in targets.into_iter().enumerate() {
544 prof_span!("ui premultiply pass");
545 let profile_name = format!("{UI_PREMULTIPLY_PASS} {i}");
546 let label = format!("ui premultiply pass {i}");
547 let mut render_pass =
548 self.encoder
549 .scoped_render_pass(&profile_name, wgpu::RenderPassDescriptor {
550 label: Some(&label),
551 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
552 view: &target_texture.view,
553 depth_slice: None,
554 resolve_target: None,
555 ops: wgpu::Operations {
556 load: wgpu::LoadOp::Load,
557 store: wgpu::StoreOp::Store,
558 },
559 })],
560 depth_stencil_attachment: None,
561 timestamp_writes: None,
562 occlusion_query_set: None,
563 });
564 render_pass.set_pipeline(&premultiply_alpha.pipeline);
565 for upload in &uploads {
566 let (source_bind_group, push_constant_data) = upload.draw_data(&target_texture);
567 let bytes = bytemuck::bytes_of(&push_constant_data);
568 render_pass.set_bind_group(0, source_bind_group, &[]);
569 render_pass.set_push_constants(wgpu::ShaderStages::VERTEX, 0, bytes);
570 render_pass.draw(0..6, 0..1);
571 }
572 }
573 }
574
575 pub fn third_pass(&mut self) -> ThirdPassDrawer<'_> {
580 self.run_ui_premultiply_passes();
581
582 let mut render_pass =
583 self.encoder
584 .scoped_render_pass("third_pass", wgpu::RenderPassDescriptor {
585 label: Some("third pass (postprocess + ui)"),
586 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
587 view: self
590 .taking_screenshot
591 .as_ref()
592 .map_or(&self.surface_view, |s| s.texture_view()),
593 depth_slice: None,
594 resolve_target: None,
595 ops: wgpu::Operations {
596 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
597 store: wgpu::StoreOp::Store,
598 },
599 })],
600 depth_stencil_attachment: None,
601 timestamp_writes: None,
602 occlusion_query_set: None,
603 });
604
605 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
606
607 ThirdPassDrawer {
608 render_pass,
609 borrow: &self.borrow,
610 }
611 }
612
613 #[cfg(feature = "egui-ui")]
614 pub fn draw_egui(
615 &mut self,
616 state: &mut egui_winit::State,
617 scale_factor: f32,
618 ) -> egui::PlatformOutput {
619 span!(guard, "Draw egui");
620
621 let output = state.egui_ctx().end_pass();
622
623 let paint_jobs = state.egui_ctx().tessellate(output.shapes, scale_factor);
624
625 let screen_descriptor = ScreenDescriptor {
626 size_in_pixels: [
627 self.borrow.surface_config.width,
628 self.borrow.surface_config.height,
629 ],
630 pixels_per_point: scale_factor,
631 };
632
633 for (id, delta) in output.textures_delta.set.iter() {
634 self.borrow.egui_renderer.update_texture(
635 self.borrow.device,
636 self.borrow.queue,
637 *id,
638 delta,
639 );
640 }
641
642 let _ = self.borrow.egui_renderer.update_buffers(
645 self.borrow.device,
646 self.borrow.queue,
647 self.encoder.encoder(),
648 &paint_jobs,
649 &screen_descriptor,
650 );
651
652 let mut render_pass = self
653 .encoder
654 .encoder()
655 .begin_render_pass(&wgpu::RenderPassDescriptor {
656 label: Some("egui pass"),
657 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
658 view: self
659 .taking_screenshot
660 .as_ref()
661 .map_or(&self.surface_view, |s| s.texture_view()),
662 depth_slice: None,
663 resolve_target: None,
664 ops: wgpu::Operations {
665 load: wgpu::LoadOp::Load,
666 store: wgpu::StoreOp::Store,
667 },
668 })],
669 depth_stencil_attachment: None,
670 timestamp_writes: None,
671 occlusion_query_set: None,
672 })
673 .forget_lifetime();
674
675 self.borrow
676 .egui_renderer
677 .render(&mut render_pass, &paint_jobs, &screen_descriptor);
678
679 for id in output.textures_delta.free.iter() {
680 self.borrow.egui_renderer.free_texture(id);
681 }
682
683 drop(guard);
684 output.platform_output
685 }
686
687 pub fn draw_point_shadows<'data>(
690 &mut self,
691 matrices: &[shadow::PointLightMatrix; 126],
692 chunks: impl Clone
693 + Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
694 ) {
695 if !self.borrow.pipeline_modes.shadow.is_map() {
696 return;
697 }
698
699 if let Some(ShadowMap::Enabled(shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) {
700 let mut encoder = self.encoder.scope("point shadows");
701 const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
702 let data = bytemuck::cast_slice(matrices);
703
704 for face in 0..6 {
705 let view =
707 shadow_renderer
708 .point_depth
709 .tex
710 .create_view(&wgpu::TextureViewDescriptor {
711 label: Some("Point shadow cubemap face"),
712 format: None,
713 dimension: Some(wgpu::TextureViewDimension::D2),
714 usage: None,
715 aspect: wgpu::TextureAspect::DepthOnly,
716 base_mip_level: 0,
717 mip_level_count: None,
718 base_array_layer: face,
719 array_layer_count: Some(1),
720 });
721
722 let label = format!("point shadow face-{} pass", face);
723 let mut render_pass =
724 encoder.scoped_render_pass(&label, wgpu::RenderPassDescriptor {
725 label: Some(&label),
726 color_attachments: &[],
727 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
728 view: &view,
729 depth_ops: Some(wgpu::Operations {
730 load: wgpu::LoadOp::Clear(1.0),
731 store: wgpu::StoreOp::Store,
732 }),
733 stencil_ops: None,
734 }),
735 timestamp_writes: None,
736 occlusion_query_set: None,
737 });
738
739 render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline);
740 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
741 render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
742
743 (0..1).for_each(|point_light| {
744 render_pass.set_push_constants(
745 wgpu::ShaderStages::VERTEX_FRAGMENT,
746 0,
747 &data[(6 * (point_light + 1) * STRIDE + face as usize * STRIDE)
748 ..(6 * (point_light + 1) * STRIDE + (face + 1) as usize * STRIDE)],
749 );
750 chunks.clone().for_each(|(model, locals)| {
751 render_pass.set_bind_group(1, &locals.bind_group, &[]);
752 render_pass.set_vertex_buffer(0, model.buf().slice(..));
753 render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
754 });
755 });
756 }
757 }
758 }
759
760 pub fn clear_shadows(&mut self) {
771 if let Some(ShadowMap::Enabled(shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) {
772 let _ = self.encoder.scoped_render_pass(
773 "clear_directed_shadow",
774 wgpu::RenderPassDescriptor {
775 label: Some("clear directed shadow pass"),
776 color_attachments: &[],
777 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
778 view: &shadow_renderer.directed_depth.view,
779 depth_ops: Some(wgpu::Operations {
780 load: wgpu::LoadOp::Clear(1.0),
781 store: wgpu::StoreOp::Store,
782 }),
783 stencil_ops: None,
784 }),
785 timestamp_writes: None,
786 occlusion_query_set: None,
787 },
788 );
789
790 for face in 0..6 {
791 let view =
793 shadow_renderer
794 .point_depth
795 .tex
796 .create_view(&wgpu::TextureViewDescriptor {
797 label: Some("Point shadow cubemap face"),
798 format: None,
799 dimension: Some(wgpu::TextureViewDimension::D2),
800 usage: None,
801 aspect: wgpu::TextureAspect::DepthOnly,
802 base_mip_level: 0,
803 mip_level_count: None,
804 base_array_layer: face,
805 array_layer_count: Some(1),
806 });
807
808 let label = format!("clear point shadow face-{} pass", face);
809 let _ = self
810 .encoder
811 .scoped_render_pass(&label, wgpu::RenderPassDescriptor {
812 label: Some(&label),
813 color_attachments: &[],
814 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
815 view: &view,
816 depth_ops: Some(wgpu::Operations {
817 load: wgpu::LoadOp::Clear(1.0),
818 store: wgpu::StoreOp::Store,
819 }),
820 stencil_ops: None,
821 }),
822 timestamp_writes: None,
823 occlusion_query_set: None,
824 });
825 }
826 }
827 }
828}
829
830impl Drop for Drawer<'_> {
831 fn drop(&mut self) {
832 let download_and_handle_screenshot = self
836 .taking_screenshot
837 .take()
838 .zip(self.borrow.pipelines.blit())
839 .map(|(screenshot, blit)| {
840 let mut render_pass = self.encoder.scoped_render_pass(
842 "screenshot blit",
843 wgpu::RenderPassDescriptor {
844 label: Some("Blit screenshot pass"),
845 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
846 view: &self.surface_view,
847 depth_slice: None,
848 resolve_target: None,
849 ops: wgpu::Operations {
850 load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
851 store: wgpu::StoreOp::Store,
852 },
853 })],
854 depth_stencil_attachment: None,
855 timestamp_writes: None,
856 occlusion_query_set: None,
857 },
858 );
859 render_pass.set_pipeline(&blit.pipeline);
860 render_pass.set_bind_group(0, screenshot.bind_group(), &[]);
861 render_pass.draw(0..3, 0..1);
862 drop(render_pass);
863 screenshot.copy_to_buffer(self.encoder.encoder())
867 });
868
869 let (profiler, mut encoder) = self.encoder.end_query();
870 profiler.resolve_queries(&mut encoder);
871
872 self.borrow.queue.submit(std::iter::once(encoder.finish()));
874 if let Some(f) = download_and_handle_screenshot {
877 f();
878 }
879 self.surface_texture.take().unwrap().present();
880
881 profiler
882 .end_frame()
883 .expect("Gpu profiler error! Maybe there was an unclosed scope?");
884 }
885}
886
887#[must_use]
889pub struct ShadowPassDrawer<'pass> {
890 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
891 borrow: &'pass RendererBorrow<'pass>,
892 shadow_renderer: &'pass ShadowMapRenderer,
893}
894
895impl<'pass> ShadowPassDrawer<'pass> {
896 pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
897 let mut render_pass = self.render_pass.scope("directed_figure_shadows");
898
899 render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
900 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
901
902 FigureShadowDrawer { render_pass }
903 }
904
905 pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
906 let mut render_pass = self.render_pass.scope("directed_terrain_shadows");
907
908 render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
909 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
910
911 TerrainShadowDrawer { render_pass }
912 }
913
914 pub fn draw_debug_shadows(&mut self) -> DebugShadowDrawer<'_, 'pass> {
915 let mut render_pass = self.render_pass.scope("directed_debug_shadows");
916
917 render_pass.set_pipeline(&self.shadow_renderer.debug_directed_pipeline.pipeline);
918 set_quad_index_buffer::<debug::Vertex>(&mut render_pass, self.borrow);
919
920 DebugShadowDrawer { render_pass }
921 }
922}
923
924#[must_use]
925pub struct RainOcclusionPassDrawer<'pass> {
926 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
927 borrow: &'pass RendererBorrow<'pass>,
928 rain_occlusion_renderer: &'pass RainOcclusionMapRenderer,
929}
930
931impl<'pass> RainOcclusionPassDrawer<'pass> {
932 pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
933 let mut render_pass = self.render_pass.scope("directed_figure_rain_occlusion");
934
935 render_pass.set_pipeline(&self.rain_occlusion_renderer.figure_pipeline.pipeline);
936 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
937
938 FigureShadowDrawer { render_pass }
939 }
940
941 pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
942 let mut render_pass = self.render_pass.scope("directed_terrain_rain_occlusion");
943
944 render_pass.set_pipeline(&self.rain_occlusion_renderer.terrain_pipeline.pipeline);
945 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
946
947 TerrainShadowDrawer { render_pass }
948 }
949}
950
951#[must_use]
952pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
953 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
954}
955
956impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
957 pub fn draw<'data: 'pass>(
958 &mut self,
959 model: SubModel<'data, terrain::Vertex>,
960 locals: &'data figure::BoundLocals,
961 ) {
962 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
963 self.render_pass.set_vertex_buffer(0, model.buf());
964 self.render_pass
965 .draw_indexed(0..model.len() / 4 * 6, 0, 0..1);
966 }
967}
968
969#[must_use]
970pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
971 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
972}
973
974impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
975 pub fn draw<'data: 'pass>(
976 &mut self,
977 model: &'data Model<terrain::Vertex>,
978 locals: &'data terrain::BoundLocals,
979 alt_indices: &'data AltIndices,
980 culling_mode: CullingMode,
981 ) {
982 let index_range = match culling_mode {
983 CullingMode::Underground => return, CullingMode::Surface => alt_indices.deep_end as u32..model.len() as u32,
987 CullingMode::None => 0..model.len() as u32,
988 };
989
990 if index_range.is_empty() {
992 return;
993 }
994
995 let submodel = model.submodel(index_range);
996
997 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
998 self.render_pass.set_vertex_buffer(0, submodel.buf());
999 self.render_pass
1000 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1001 }
1002}
1003
1004#[must_use]
1005pub struct DebugShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
1006 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1007}
1008
1009impl<'pass_ref, 'pass: 'pass_ref> DebugShadowDrawer<'pass_ref, 'pass> {
1010 pub fn draw<'data: 'pass>(
1011 &mut self,
1012 model: &'data Model<debug::Vertex>,
1013 locals: &'data debug::BoundLocals,
1014 ) {
1015 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
1016 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1017 self.render_pass.draw(0..model.len() as u32, 0..1);
1018 }
1019}
1020
1021#[must_use]
1023pub struct FirstPassDrawer<'pass> {
1024 pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1025 borrow: &'pass RendererBorrow<'pass>,
1026 pipelines: &'pass super::Pipelines,
1027 globals: &'pass GlobalsBindGroup,
1028}
1029
1030impl<'pass> FirstPassDrawer<'pass> {
1031 pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
1032 let mut render_pass = self.render_pass.scope("skybox");
1033
1034 render_pass.set_pipeline(&self.pipelines.skybox.pipeline);
1035 set_quad_index_buffer::<skybox::Vertex>(&mut render_pass, self.borrow);
1036 render_pass.set_vertex_buffer(0, model.buf().slice(..));
1037 render_pass.draw(0..model.len() as u32, 0..1);
1038 }
1039
1040 pub fn draw_debug(&mut self) -> DebugDrawer<'_, 'pass> {
1041 let mut render_pass = self.render_pass.scope("debug");
1042
1043 render_pass.set_pipeline(&self.pipelines.debug.pipeline);
1044 set_quad_index_buffer::<debug::Vertex>(&mut render_pass, self.borrow);
1045
1046 DebugDrawer { render_pass }
1047 }
1048
1049 pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model<lod_terrain::Vertex>) {
1050 let mut render_pass = self.render_pass.scope("lod_terrain");
1051
1052 render_pass.set_pipeline(&self.pipelines.lod_terrain.pipeline);
1053 set_quad_index_buffer::<lod_terrain::Vertex>(&mut render_pass, self.borrow);
1054 render_pass.set_vertex_buffer(0, model.buf().slice(..));
1055 render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1056 }
1057
1058 pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
1059 let mut render_pass = self.render_pass.scope("figures");
1060
1061 render_pass.set_pipeline(&self.pipelines.figure.pipeline);
1062 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
1064
1065 FigureDrawer { render_pass }
1066 }
1067
1068 pub fn draw_terrain(&mut self) -> TerrainDrawer<'_, 'pass> {
1069 let mut render_pass = self.render_pass.scope("terrain");
1070
1071 render_pass.set_pipeline(&self.pipelines.terrain.pipeline);
1072 set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, self.borrow);
1073
1074 TerrainDrawer {
1075 render_pass,
1076 atlas_textures: None,
1077 }
1078 }
1079
1080 pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
1081 let mut render_pass = self.render_pass.scope("particles");
1082
1083 render_pass.set_pipeline(&self.pipelines.particle.pipeline);
1084 set_quad_index_buffer::<particle::Vertex>(&mut render_pass, self.borrow);
1085
1086 ParticleDrawer { render_pass }
1087 }
1088
1089 pub fn draw_ropes(&mut self) -> RopeDrawer<'_, 'pass> {
1090 let mut render_pass = self.render_pass.scope("ropes");
1091
1092 render_pass.set_pipeline(&self.pipelines.rope.pipeline);
1093 set_quad_index_buffer::<rope::Vertex>(&mut render_pass, self.borrow);
1094
1095 RopeDrawer { render_pass }
1096 }
1097
1098 pub fn draw_sprites<'data: 'pass>(
1099 &mut self,
1100 globals: &'data sprite::SpriteGlobalsBindGroup,
1101 atlas_textures: &'data AtlasTextures<sprite::Locals, FigureSpriteAtlasData>,
1102 ) -> SpriteDrawer<'_, 'pass> {
1103 let mut render_pass = self.render_pass.scope("sprites");
1104
1105 render_pass.set_pipeline(&self.pipelines.sprite.pipeline);
1106 set_quad_index_buffer::<sprite::Vertex>(&mut render_pass, self.borrow);
1107 render_pass.set_bind_group(0, &globals.bind_group, &[]);
1108 render_pass.set_bind_group(2, &atlas_textures.bind_group, &[]);
1109
1110 SpriteDrawer {
1111 render_pass,
1112 globals: self.globals,
1113 }
1114 }
1115
1116 pub fn draw_lod_objects(&mut self) -> LodObjectDrawer<'_, 'pass> {
1117 let mut render_pass = self.render_pass.scope("lod objects");
1118
1119 render_pass.set_pipeline(&self.pipelines.lod_object.pipeline);
1120 set_quad_index_buffer::<lod_object::Vertex>(&mut render_pass, self.borrow);
1121
1122 LodObjectDrawer { render_pass }
1123 }
1124
1125 pub fn draw_fluid(&mut self) -> FluidDrawer<'_, 'pass> {
1126 let mut render_pass = self.render_pass.scope("fluid");
1127
1128 render_pass.set_pipeline(&self.pipelines.fluid.pipeline);
1129 set_quad_index_buffer::<fluid::Vertex>(&mut render_pass, self.borrow);
1130
1131 FluidDrawer { render_pass }
1132 }
1133}
1134
1135#[must_use]
1136pub struct DebugDrawer<'pass_ref, 'pass: 'pass_ref> {
1137 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1138}
1139
1140impl<'pass_ref, 'pass: 'pass_ref> DebugDrawer<'pass_ref, 'pass> {
1141 pub fn draw<'data: 'pass>(
1142 &mut self,
1143 model: &'data Model<debug::Vertex>,
1144 locals: &'data debug::BoundLocals,
1145 ) {
1146 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1147 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1148 self.render_pass.draw(0..model.len() as u32, 0..1);
1149 }
1150}
1151
1152#[must_use]
1153pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
1154 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1155}
1156
1157impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
1158 pub fn draw<'data: 'pass>(
1159 &mut self,
1160 model: SubModel<'data, terrain::Vertex>,
1161 locals: &'data figure::BoundLocals,
1162 atlas_textures: &'data AtlasTextures<figure::Locals, FigureSpriteAtlasData>,
1164 ) {
1165 self.render_pass
1166 .set_bind_group(2, &atlas_textures.bind_group, &[]);
1167 self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
1168 self.render_pass.set_vertex_buffer(0, model.buf());
1169 self.render_pass
1170 .draw_indexed(0..model.len() / 4 * 6, 0, 0..1);
1171 }
1172}
1173
1174#[must_use]
1175pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
1176 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1177 atlas_textures: Option<&'pass_ref Arc<AtlasTextures<terrain::Locals, TerrainAtlasData>>>,
1178}
1179
1180impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
1181 pub fn draw<'data: 'pass>(
1182 &mut self,
1183 model: &'data Model<terrain::Vertex>,
1184 atlas_textures: &'data Arc<AtlasTextures<terrain::Locals, TerrainAtlasData>>,
1185 locals: &'data terrain::BoundLocals,
1186 alt_indices: &'data AltIndices,
1187 culling_mode: CullingMode,
1188 ) {
1189 let index_range = match culling_mode {
1190 CullingMode::Underground => 0..alt_indices.underground_end as u32,
1191 CullingMode::Surface => alt_indices.deep_end as u32..model.len() as u32,
1192 CullingMode::None => 0..model.len() as u32,
1193 };
1194
1195 if index_range.is_empty() {
1197 return;
1198 }
1199
1200 let submodel = model.submodel(index_range);
1201
1202 if self.atlas_textures
1203 .filter(|current_atlas_textures| Arc::ptr_eq(current_atlas_textures, atlas_textures))
1206 .is_none()
1207 {
1208 self.render_pass
1209 .set_bind_group(2, &atlas_textures.bind_group, &[]);
1210 self.atlas_textures = Some(atlas_textures);
1211 };
1212
1213 self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
1214
1215 self.render_pass.set_vertex_buffer(0, submodel.buf());
1216 self.render_pass
1217 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1218 }
1219}
1220
1221#[must_use]
1222pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
1223 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1224}
1225
1226impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
1227 pub fn draw<'data: 'pass>(
1230 &mut self,
1231 model: &'data Model<particle::Vertex>,
1232 instances: &'data Instances<particle::Instance>,
1233 ) {
1234 if instances.count() != 0 {
1235 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1236 self.render_pass
1237 .set_vertex_buffer(1, instances.buf().slice(..));
1238 self.render_pass
1239 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32);
1241 }
1242 }
1243}
1244
1245#[must_use]
1246pub struct RopeDrawer<'pass_ref, 'pass: 'pass_ref> {
1247 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1248}
1249
1250impl<'pass_ref, 'pass: 'pass_ref> RopeDrawer<'pass_ref, 'pass> {
1251 pub fn draw<'data: 'pass>(
1254 &mut self,
1255 model: &'data Model<rope::Vertex>,
1256 locals: &'data rope::BoundLocals,
1257 ) {
1258 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1259 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1260 self.render_pass
1263 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1264 }
1265}
1266
1267#[must_use]
1268pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
1269 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1270 globals: &'pass GlobalsBindGroup,
1271}
1272
1273impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
1274 pub fn draw<'data: 'pass, T>(
1275 &mut self,
1276 terrain_locals: &'data Bound<T>,
1277 instances: &'data Instances<sprite::Instance>,
1278 alt_indices: &'data AltIndices,
1279 culling_mode: CullingMode,
1280 ) {
1281 let instance_range = match culling_mode {
1282 CullingMode::Underground => 0..alt_indices.underground_end as u32,
1283 CullingMode::Surface => alt_indices.deep_end as u32..instances.count() as u32,
1284 CullingMode::None => 0..instances.count() as u32,
1285 };
1286
1287 if instance_range.is_empty() {
1289 return;
1290 }
1291
1292 self.render_pass
1293 .set_bind_group(3, &terrain_locals.bind_group, &[]);
1294
1295 let subinstances = instances.subinstances(instance_range);
1296
1297 self.render_pass.set_vertex_buffer(0, subinstances.buf());
1298 self.render_pass.draw_indexed(
1299 0..sprite::VERT_PAGE_SIZE / 4 * 6,
1300 0,
1301 0..subinstances.count(),
1302 );
1303 }
1304}
1305
1306impl<'pass_ref, 'pass: 'pass_ref> Drop for SpriteDrawer<'pass_ref, 'pass> {
1307 fn drop(&mut self) {
1308 self.render_pass
1310 .set_bind_group(0, &self.globals.bind_group, &[]);
1311 }
1312}
1313
1314#[must_use]
1315pub struct LodObjectDrawer<'pass_ref, 'pass: 'pass_ref> {
1316 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1317}
1318
1319impl<'pass_ref, 'pass: 'pass_ref> LodObjectDrawer<'pass_ref, 'pass> {
1320 pub fn draw<'data: 'pass>(
1321 &mut self,
1322 model: &'data Model<lod_object::Vertex>,
1323 instances: &'data Instances<lod_object::Instance>,
1324 ) {
1325 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1326 self.render_pass
1327 .set_vertex_buffer(1, instances.buf().slice(..));
1328 self.render_pass
1329 .draw(0..model.len() as u32, 0..instances.count() as u32);
1330 }
1331}
1332
1333#[must_use]
1334pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
1335 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1336}
1337
1338impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
1339 pub fn draw<'data: 'pass>(
1340 &mut self,
1341 model: &'data Model<fluid::Vertex>,
1342 locals: &'data terrain::BoundLocals,
1343 ) {
1344 self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
1345 self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
1346 self.render_pass
1347 .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
1348 }
1349}
1350
1351#[must_use]
1353pub struct VolumetricPassDrawer<'pass> {
1354 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1355 borrow: &'pass RendererBorrow<'pass>,
1356 clouds_pipeline: &'pass clouds::CloudsPipeline,
1357}
1358
1359impl VolumetricPassDrawer<'_> {
1360 pub fn draw_clouds(&mut self) {
1361 self.render_pass
1362 .set_pipeline(&self.clouds_pipeline.pipeline);
1363 self.render_pass
1364 .set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]);
1365 self.render_pass.draw(0..3, 0..1);
1366 }
1367}
1368
1369#[must_use]
1371pub struct TransparentPassDrawer<'pass> {
1372 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1373 borrow: &'pass RendererBorrow<'pass>,
1374 trail_pipeline: &'pass trail::TrailPipeline,
1375}
1376
1377impl<'pass> TransparentPassDrawer<'pass> {
1378 pub fn draw_trails(&mut self) -> Option<TrailDrawer<'_, 'pass>> {
1379 let shadow = &self.borrow.shadow?;
1380
1381 let mut render_pass = self.render_pass.scope("trails");
1382
1383 render_pass.set_pipeline(&self.trail_pipeline.pipeline);
1384 set_quad_index_buffer::<trail::Vertex>(&mut render_pass, self.borrow);
1385
1386 render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]);
1387
1388 Some(TrailDrawer { render_pass })
1389 }
1390}
1391
1392#[must_use]
1393pub struct TrailDrawer<'pass_ref, 'pass: 'pass_ref> {
1394 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1395}
1396
1397impl<'pass_ref, 'pass: 'pass_ref> TrailDrawer<'pass_ref, 'pass> {
1398 pub fn draw(&mut self, submodel: SubModel<'pass, trail::Vertex>) {
1399 self.render_pass.set_vertex_buffer(0, submodel.buf());
1400 self.render_pass
1401 .draw_indexed(0..submodel.len() / 4 * 6, 0, 0..1);
1402 }
1403}
1404
1405#[must_use]
1407pub struct ThirdPassDrawer<'pass> {
1408 render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
1409 borrow: &'pass RendererBorrow<'pass>,
1410}
1411
1412impl<'pass> ThirdPassDrawer<'pass> {
1413 pub fn draw_postprocess(&mut self) {
1415 let postprocess = match self.borrow.pipelines.all() {
1416 Some(p) => &p.postprocess,
1417 None => return,
1418 };
1419
1420 let mut render_pass = self.render_pass.scope("postprocess");
1421 render_pass.set_pipeline(&postprocess.pipeline);
1422 render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]);
1423 render_pass.draw(0..3, 0..1);
1424 }
1425
1426 pub fn draw_ui(&mut self) -> Option<UiDrawer<'_, 'pass>> {
1429 let ui = self.borrow.pipelines.ui()?;
1430
1431 let mut render_pass = self.render_pass.scope("ui");
1432 render_pass.set_pipeline(&ui.pipeline);
1433 set_quad_index_buffer::<ui::Vertex>(&mut render_pass, self.borrow);
1434
1435 Some(UiDrawer { render_pass })
1436 }
1437}
1438
1439#[must_use]
1440pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
1441 render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
1442}
1443
1444#[must_use]
1445pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
1446 render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
1447}
1448
1449impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
1450 pub fn prepare<'data: 'pass>(
1454 &mut self,
1455 locals: &'data ui::BoundLocals,
1456 buf: &'data DynamicModel<ui::Vertex>,
1457 scissor: Aabr<u16>,
1458 ) -> PreparedUiDrawer<'_, 'pass> {
1459 let mut prepared = PreparedUiDrawer {
1462 render_pass: &mut self.render_pass,
1463 };
1464 prepared.set_locals(locals);
1466 prepared.set_model(buf);
1467 prepared.set_scissor(scissor);
1468
1469 prepared
1470 }
1471}
1472
1473impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
1474 pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) {
1475 self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
1476 }
1477
1478 pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel<ui::Vertex>) {
1479 self.render_pass.set_vertex_buffer(0, model.buf().slice(..))
1480 }
1481
1482 pub fn set_scissor(&mut self, scissor: Aabr<u16>) {
1483 let Aabr { min, max } = scissor;
1484 self.render_pass.set_scissor_rect(
1485 min.x as u32,
1486 min.y as u32,
1487 (max.x - min.x) as u32,
1488 (max.y - min.y) as u32,
1489 );
1490 }
1491
1492 pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) {
1493 self.render_pass.set_bind_group(2, &texture.bind_group, &[]);
1494 self.render_pass.draw(verts, 0..1);
1495 }
1496}
1497
1498fn set_quad_index_buffer<'a, V: super::Vertex>(
1499 pass: &mut wgpu::RenderPass<'a>,
1500 borrow: &RendererBorrow<'a>,
1501) {
1502 if let Some(format) = V::QUADS_INDEX {
1503 let slice = match format {
1504 wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..),
1505 wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..),
1506 };
1507
1508 pass.set_index_buffer(slice, format);
1509 }
1510}