Skip to main content

multi_model/utils/
selection.rs

1#![allow(dead_code)]
2
3use wgpu_3dgs_viewer::selection::ViewportTexture;
4
5/// Renderer to render the selection viewport texture as an overlay.
6#[derive(Debug)]
7pub struct ViewportTextureOverlayRenderer {
8    /// The sampler.
9    sampler: wgpu::Sampler,
10    /// The bind group layout.
11    bind_group_layout: wgpu::BindGroupLayout,
12    /// The bind group.
13    bind_group: wgpu::BindGroup,
14    /// The pipeline.
15    pipeline: wgpu::RenderPipeline,
16}
17
18impl ViewportTextureOverlayRenderer {
19    /// The bind group layout descriptor.
20    pub const BIND_GROUP_LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> =
21        wgpu::BindGroupLayoutDescriptor {
22            label: Some("Selection Viewport Texture Overlay Renderer Bind Group Layout"),
23            entries: &[
24                wgpu::BindGroupLayoutEntry {
25                    binding: 0,
26                    visibility: wgpu::ShaderStages::FRAGMENT,
27                    ty: wgpu::BindingType::Texture {
28                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
29                        view_dimension: wgpu::TextureViewDimension::D2,
30                        multisampled: false,
31                    },
32                    count: None,
33                },
34                wgpu::BindGroupLayoutEntry {
35                    binding: 1,
36                    visibility: wgpu::ShaderStages::FRAGMENT,
37                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
38                    count: None,
39                },
40            ],
41        };
42
43    /// Create a new selection viewport texture overlay renderer.
44    pub fn new(
45        device: &wgpu::Device,
46        texture_format: wgpu::TextureFormat,
47        viewport_texture: &ViewportTexture,
48    ) -> Self {
49        log::debug!("Creating selection viewport texture overlay renderer sampler");
50        let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
51            label: Some("Selection Viewport Texture Overlay Renderer Sampler"),
52            ..Default::default()
53        });
54
55        log::debug!("Creating selection viewport texture overlay renderer bind group layout");
56        let bind_group_layout =
57            device.create_bind_group_layout(&Self::BIND_GROUP_LAYOUT_DESCRIPTOR);
58
59        log::debug!("Creating selection viewport texture overlay renderer bind group");
60        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
61            label: Some("Selection Viewport Texture Overlay Renderer Bind Group"),
62            layout: &bind_group_layout,
63            entries: &[
64                wgpu::BindGroupEntry {
65                    binding: 0,
66                    resource: wgpu::BindingResource::TextureView(viewport_texture.view()),
67                },
68                wgpu::BindGroupEntry {
69                    binding: 1,
70                    resource: wgpu::BindingResource::Sampler(&sampler),
71                },
72            ],
73        });
74
75        log::debug!("Creating selection viewport texture overlay renderer pipeline layout");
76        let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
77            label: Some("Selection Viewport Texture Overlay Renderer Pipeline Layout"),
78            bind_group_layouts: &[&bind_group_layout],
79            ..Default::default()
80        });
81
82        log::debug!("Creating selection viewport texture overlay renderer shader");
83        let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
84            label: Some("Selection Viewport Texture Overlay Renderer Shader"),
85            source: wgpu::ShaderSource::Wgsl(
86                include_str!("../shader/selection/viewport_texture_overlay.wgsl").into(),
87            ),
88        });
89
90        log::debug!("Creating selection viewport texture overlay renderer pipeline");
91        let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
92            label: Some("Selection Viewport Texture Overlay Renderer Pipeline"),
93            layout: Some(&pipeline_layout),
94            vertex: wgpu::VertexState {
95                module: &shader,
96                entry_point: Some("vert_main"),
97                buffers: &[],
98                compilation_options: wgpu::PipelineCompilationOptions::default(),
99            },
100            fragment: Some(wgpu::FragmentState {
101                module: &shader,
102                entry_point: Some("frag_main"),
103                targets: &[Some(wgpu::ColorTargetState {
104                    format: texture_format,
105                    blend: Some(wgpu::BlendState::ALPHA_BLENDING),
106                    write_mask: wgpu::ColorWrites::ALL,
107                })],
108                compilation_options: wgpu::PipelineCompilationOptions::default(),
109            }),
110            primitive: wgpu::PrimitiveState::default(),
111            depth_stencil: None,
112            multisample: wgpu::MultisampleState::default(),
113            multiview_mask: None,
114            cache: None,
115        });
116
117        Self {
118            sampler,
119            bind_group_layout,
120            bind_group,
121            pipeline,
122        }
123    }
124
125    /// Update the bind group.
126    ///
127    /// This is specifically for updating the selection viewport texture size.
128    pub fn update_bind_group(&mut self, device: &wgpu::Device, viewport_texture: &ViewportTexture) {
129        self.bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
130            label: Some("Selection Viewport Texture Overlay Renderer Bind Group"),
131            layout: &self.bind_group_layout,
132            entries: &[
133                wgpu::BindGroupEntry {
134                    binding: 0,
135                    resource: wgpu::BindingResource::TextureView(viewport_texture.view()),
136                },
137                wgpu::BindGroupEntry {
138                    binding: 1,
139                    resource: wgpu::BindingResource::Sampler(&self.sampler),
140                },
141            ],
142        });
143    }
144
145    /// Render the selection viewport texture overlay.
146    pub fn render(&self, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView) {
147        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
148            label: Some("Selection Viewport Texture Overlay Render Pass"),
149            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
150                view,
151                resolve_target: None,
152                ops: wgpu::Operations {
153                    load: wgpu::LoadOp::Load,
154                    store: wgpu::StoreOp::Store,
155                },
156                depth_slice: None,
157            })],
158            ..Default::default()
159        });
160
161        self.render_with_pass(&mut render_pass);
162    }
163
164    /// Render the selection viewport texture overlay with a [`wgpu::RenderPass`].
165    pub fn render_with_pass(&self, pass: &mut wgpu::RenderPass<'_>) {
166        pass.set_pipeline(&self.pipeline);
167        pass.set_bind_group(0, &self.bind_group, &[]);
168        pass.draw(0..3, 0..1);
169    }
170}