Skip to main content

ViewportTexture

Struct ViewportTexture 

Source
pub struct ViewportTexture { /* private fields */ }
Expand description

A viewport selection texture for the compute bundle created by selection::create_viewport_bundle.

Implementations§

Source§

impl ViewportTexture

Source

pub fn new(device: &Device, size: UVec2) -> Self

Create a new viewport texture.

Source

pub fn texture(&self) -> &Texture

Get the texture.

Source

pub fn view(&self) -> &TextureView

Get the texture view.

Examples found in repository?
examples/utils/selection.rs (line 66)
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    }
More examples
Hide additional examples
examples/selection.rs (line 209)
96    async fn init(window: Arc<Window>, args: &Args) -> Self {
97        let model_path = &args.model;
98        let filter = args.filter;
99        let immediate = args.immediate;
100        let size = window.inner_size();
101
102        log::debug!("Creating wgpu instance");
103        let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
104
105        log::debug!("Creating window surface");
106        let surface = instance.create_surface(window.clone()).expect("surface");
107
108        log::debug!("Requesting adapter");
109        let adapter = instance
110            .request_adapter(&wgpu::RequestAdapterOptions {
111                power_preference: wgpu::PowerPreference::HighPerformance,
112                compatible_surface: Some(&surface),
113                force_fallback_adapter: false,
114            })
115            .await
116            .expect("adapter");
117
118        log::debug!("Requesting device");
119        let (device, queue) = adapter
120            .request_device(&wgpu::DeviceDescriptor {
121                label: Some("Device"),
122                required_limits: adapter.limits(),
123                ..Default::default()
124            })
125            .await
126            .expect("device");
127
128        let surface_caps = surface.get_capabilities(&adapter);
129        let surface_format = surface_caps.formats[0];
130        let config = wgpu::SurfaceConfiguration {
131            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
132            format: surface_format,
133            width: size.width.max(1),
134            height: size.height.max(1),
135            present_mode: surface_caps.present_modes[0],
136            alpha_mode: surface_caps.alpha_modes[0],
137            view_formats: vec![surface_format.remove_srgb_suffix()],
138            desired_maximum_frame_latency: 2,
139        };
140
141        log::debug!("Configuring surface");
142        surface.configure(&device, &config);
143
144        log::debug!("Creating gaussians");
145        let gaussians = [GaussiansSource::Ply, GaussiansSource::Spz]
146            .into_iter()
147            .find_map(|source| gs::core::Gaussians::read_from_file(model_path, source).ok())
148            .expect("gaussians");
149
150        log::debug!("Creating camera");
151        let camera = gs::Camera::new(0.1..1e4, 60f32.to_radians());
152
153        log::debug!("Creating viewer");
154        let mut viewer = gs::Viewer::new_with_options(
155            &device,
156            config.view_formats[0],
157            &gaussians,
158            gs::ViewerCreateOptions {
159                gaussians_buffer_usage:
160                    gs::core::GaussiansBuffer::<gs::DefaultGaussianPod>::DEFAULT_USAGES
161                        | wgpu::BufferUsages::COPY_SRC,
162                ..Default::default()
163            },
164        )
165        .expect("viewer");
166        viewer.update_model_transform(
167            &queue,
168            Vec3::ZERO,
169            Quat::from_axis_angle(Vec3::Z, 180f32.to_radians()),
170            Vec3::ONE,
171        );
172
173        log::debug!("Creating selector");
174        let mut selector = gs::selection::ViewportSelector::new(
175            &device,
176            &queue,
177            UVec2::new(size.width, size.height),
178            &viewer.camera_buffer,
179        )
180        .expect("selector");
181        selector.selector_type = gs::selection::ViewportSelectorType::Brush;
182
183        log::debug!("Creating selection viewport selection modifier");
184        let mut viewport_selection_modifier = gs::editor::NonDestructiveModifier::new(
185            &device,
186            &queue,
187            gs::editor::BasicSelectionModifier::new_with_basic_modifier(
188                &device,
189                &viewer.gaussians_buffer,
190                &viewer.model_transform_buffer,
191                &viewer.gaussian_transform_buffer,
192                vec![gs::selection::create_viewport_bundle::<
193                    gs::DefaultGaussianPod,
194                >(&device)],
195            ),
196            &viewer.gaussians_buffer,
197        )
198        .expect("modifier");
199
200        let viewport_selection_bind_group = viewport_selection_modifier.modifier.selection.bundles
201            [0]
202        .create_bind_group(
203            &device,
204            // index 0 is the Gaussians buffer, so we use 1,
205            // see docs of create_viewport_bundle
206            1,
207            [
208                viewer.camera_buffer.buffer().as_entire_binding(),
209                wgpu::BindingResource::TextureView(selector.texture().view()),
210            ],
211        )
212        .expect("bind group");
213
214        viewport_selection_modifier.modifier.selection_expr =
215            gs::editor::SelectionExpr::Selection(0, vec![viewport_selection_bind_group]);
216
217        viewport_selection_modifier // Non destructive modifier
218            .modifier // Selection modifier
219            .modifier // Basic modifier
220            .basic_color_modifiers_buffer
221            .update_with_pod(
222                &queue,
223                &gs::editor::BasicColorModifiersPod {
224                    rgb_or_hsv: BasicColorRgbOverrideOrHsvModifiersPod::new_rgb_override(
225                        Vec3::new(1.0, 1.0, 0.0),
226                    ),
227                    ..Default::default()
228                },
229            );
230
231        log::debug!("Creating selection viewport texture overlay renderer");
232        let viewport_texture_overlay_renderer =
233            utils::selection::ViewportTextureOverlayRenderer::new(
234                &device,
235                config.view_formats[0],
236                selector.texture(),
237            );
238
239        log::info!("System initialized");
240
241        Self {
242            surface,
243            device,
244            queue,
245            config,
246
247            filter,
248            immediate,
249            inverted: filter,
250            selector_type: None,
251
252            camera,
253            gaussians,
254            viewer,
255            selector,
256
257            viewport_selection_modifier,
258            viewport_texture_overlay_renderer,
259        }
260    }
261
262    fn update(&mut self, input: &core::Input, delta_time: f32) {
263        // Toggle selection mode
264        if input.pressed_keys.contains(&KeyCode::KeyN) {
265            self.selector_type = None;
266            log::info!("Selector: None");
267        }
268        if input.pressed_keys.contains(&KeyCode::KeyR) {
269            self.selector_type = Some(gs::selection::ViewportSelectorType::Rectangle);
270            log::info!("Selector: Rectangle");
271            self.selector.selector_type = gs::selection::ViewportSelectorType::Rectangle;
272        }
273        if input.pressed_keys.contains(&KeyCode::KeyB) {
274            self.selector_type = Some(gs::selection::ViewportSelectorType::Brush);
275            log::info!("Selector: Brush");
276            self.selector.selector_type = gs::selection::ViewportSelectorType::Brush;
277        }
278        if input.pressed_keys.contains(&KeyCode::KeyI) {
279            self.inverted = !self.inverted;
280            log::info!("Inverted: {}", self.inverted);
281            if self.filter {
282                self.viewer
283                    .invert_selection_buffer
284                    .update(&self.queue, self.inverted);
285            }
286        }
287
288        if self.selector_type.is_some() {
289            self.update_selection(input, delta_time);
290        } else {
291            self.update_movement(input, delta_time);
292        }
293
294        // Update the viewer
295        self.viewer.update_camera(
296            &self.queue,
297            &self.camera,
298            uvec2(self.config.width, self.config.height),
299        );
300    }
301
302    fn render(&mut self) {
303        let texture = match self.surface.get_current_texture() {
304            Ok(texture) => texture,
305            Err(e) => {
306                log::error!("Failed to get current texture: {e:?}");
307                return;
308            }
309        };
310        let texture_view = texture.texture.create_view(&wgpu::TextureViewDescriptor {
311            label: Some("Texture View"),
312            format: Some(self.config.view_formats[0]),
313            ..Default::default()
314        });
315
316        let mut encoder = self
317            .device
318            .create_command_encoder(&wgpu::CommandEncoderDescriptor {
319                label: Some("Command Encoder"),
320            });
321
322        self.viewer.render(&mut encoder, &texture_view);
323
324        if !self.immediate && self.selector_type.is_some() {
325            self.viewport_texture_overlay_renderer
326                .render(&mut encoder, &texture_view);
327        }
328
329        self.queue.submit(std::iter::once(encoder.finish()));
330        if let Err(e) = self.device.poll(wgpu::PollType::wait_indefinitely()) {
331            log::error!("Failed to poll device: {e:?}");
332        }
333        texture.present();
334    }
335
336    fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
337        if size.width > 0 && size.height > 0 {
338            self.config.width = size.width;
339            self.config.height = size.height;
340            self.surface.configure(&self.device, &self.config);
341
342            // Update selector viewport texture
343            self.selector
344                .resize(&self.device, UVec2::new(size.width, size.height));
345
346            // Update viewport selection bundle
347            let viewport_selection_bind_group =
348                self.viewport_selection_modifier.modifier.selection.bundles[0]
349                    .create_bind_group(
350                        &self.device,
351                        // index 0 is the Gaussians buffer, so we use 1,
352                        // see docs of create_viewport_bundle
353                        1,
354                        [
355                            self.viewer.camera_buffer.buffer().as_entire_binding(),
356                            wgpu::BindingResource::TextureView(self.selector.texture().view()),
357                        ],
358                    )
359                    .expect("bind group");
360
361            // Update viewport selection modifier selection expr
362            self.viewport_selection_modifier.modifier.selection_expr =
363                gs::editor::SelectionExpr::Selection(0, vec![viewport_selection_bind_group]);
364
365            // Update viewport texture overlay renderer
366            self.viewport_texture_overlay_renderer
367                .update_bind_group(&self.device, self.selector.texture());
368        }
369    }

Trait Implementations§

Source§

impl Clone for ViewportTexture

Source§

fn clone(&self) -> ViewportTexture

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ViewportTexture

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,