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
impl ViewportTexture
Sourcepub fn view(&self) -> &TextureView
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
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
impl Clone for ViewportTexture
Source§fn clone(&self) -> ViewportTexture
fn clone(&self) -> ViewportTexture
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for ViewportTexture
impl !RefUnwindSafe for ViewportTexture
impl Send for ViewportTexture
impl Sync for ViewportTexture
impl Unpin for ViewportTexture
impl UnsafeUnpin for ViewportTexture
impl !UnwindSafe for ViewportTexture
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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