From ae20590f6e96f333cde2ed511488dd7a818c0480 Mon Sep 17 00:00:00 2001 From: tolelom <98kimsungmin@naver.com> Date: Thu, 26 Mar 2026 10:31:28 +0900 Subject: [PATCH] feat(editor): add ViewportTexture offscreen render target Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/voltex_editor/src/lib.rs | 5 ++ crates/voltex_editor/src/viewport_texture.rs | 69 ++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 crates/voltex_editor/src/viewport_texture.rs diff --git a/crates/voltex_editor/src/lib.rs b/crates/voltex_editor/src/lib.rs index fd09350..1ff04dd 100644 --- a/crates/voltex_editor/src/lib.rs +++ b/crates/voltex_editor/src/lib.rs @@ -5,6 +5,7 @@ pub mod renderer; pub mod ui_context; pub mod widgets; pub mod dock; +pub mod orbit_camera; pub use font::FontAtlas; pub use draw_list::{DrawVertex, DrawCommand, DrawList}; @@ -12,3 +13,7 @@ pub use layout::LayoutState; pub use renderer::UiRenderer; pub use ui_context::UiContext; pub use dock::{DockTree, DockNode, Axis, Rect, LeafLayout}; +pub use orbit_camera::OrbitCamera; + +pub mod viewport_texture; +pub use viewport_texture::{ViewportTexture, VIEWPORT_COLOR_FORMAT, VIEWPORT_DEPTH_FORMAT}; diff --git a/crates/voltex_editor/src/viewport_texture.rs b/crates/voltex_editor/src/viewport_texture.rs new file mode 100644 index 0000000..849a3b1 --- /dev/null +++ b/crates/voltex_editor/src/viewport_texture.rs @@ -0,0 +1,69 @@ +pub const VIEWPORT_COLOR_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm; +pub const VIEWPORT_DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; + +pub struct ViewportTexture { + pub color_texture: wgpu::Texture, + pub color_view: wgpu::TextureView, + pub depth_texture: wgpu::Texture, + pub depth_view: wgpu::TextureView, + pub width: u32, + pub height: u32, +} + +impl ViewportTexture { + pub fn new(device: &wgpu::Device, width: u32, height: u32) -> Self { + let w = width.max(1); + let h = height.max(1); + + let color_texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("Viewport Color"), + size: wgpu::Extent3d { + width: w, + height: h, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: VIEWPORT_COLOR_FORMAT, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }); + let color_view = color_texture.create_view(&wgpu::TextureViewDescriptor::default()); + + let depth_texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("Viewport Depth"), + size: wgpu::Extent3d { + width: w, + height: h, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: VIEWPORT_DEPTH_FORMAT, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }); + let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); + + ViewportTexture { + color_texture, + color_view, + depth_texture, + depth_view, + width: w, + height: h, + } + } + + pub fn ensure_size(&mut self, device: &wgpu::Device, width: u32, height: u32) -> bool { + let w = width.max(1); + let h = height.max(1); + if w == self.width && h == self.height { + return false; + } + *self = Self::new(device, w, h); + true + } +}