use super::*;
impl ViewportRenderer {
pub(super) fn prepare_splat_sort(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
frame: &FrameData,
) {
self.gaussian_splat_draw_data.clear();
if !frame.scene.gaussian_splats.is_empty() {
self.resources.ensure_gaussian_splat_pipelines(device);
let vp_idx = frame.camera.viewport_index;
let eye = frame.camera.render_camera.eye_position;
let vp_w = frame.camera.viewport_size[0].max(1.0);
let vp_h = frame.camera.viewport_size[1].max(1.0);
for item in &frame.scene.gaussian_splats {
if item.settings.hidden {
continue;
}
let store_index = item.id.0;
if self
.resources
.gaussian_splat_store
.get(store_index)
.is_none()
{
continue;
}
let sh_degree = self
.resources
.gaussian_splat_store
.get(store_index)
.unwrap()
.sh_degree;
let count = self
.resources
.gaussian_splat_store
.get(store_index)
.unwrap()
.count;
self.resources.run_gaussian_splat_sort(
device,
queue,
store_index,
vp_idx,
eye,
item.model,
vp_w,
vp_h,
sh_degree,
);
self.gaussian_splat_draw_data
.push(crate::resources::GaussianSplatDrawData {
store_index,
viewport_index: vp_idx,
model: item.model,
count,
wireframe: frame.viewport.wireframe_mode || item.settings.wireframe,
});
}
}
}
pub(super) fn prepare_splat_wireframe(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
frame: &FrameData,
) {
let need_splat_wf = frame.viewport.wireframe_mode
|| frame
.scene
.gaussian_splats
.iter()
.any(|g| !g.settings.hidden && g.settings.wireframe);
if need_splat_wf {
self.resources.ensure_polyline_pipeline(device);
let vp_size = frame.camera.viewport_size;
for item in &frame.scene.gaussian_splats {
if item.settings.hidden {
continue;
}
if !(frame.viewport.wireframe_mode || item.settings.wireframe) {
continue;
}
let store_index = item.id.0;
let Some(gpu_set) = self.resources.gaussian_splat_store.get(store_index) else {
continue;
};
let count = gpu_set.count as usize;
let positions = gpu_set.cpu_positions.clone();
let scales = gpu_set.cpu_scales.clone();
let _ = gpu_set;
let polyline = splat_wireframe_polyline(&positions, &scales, item.model, count);
if !polyline.positions.is_empty() {
let gpu = self
.resources
.upload_polyline_per_frame(device, queue, &polyline, vp_size);
self.polyline_gpu_data.push(gpu);
}
}
}
}
pub(super) fn prepare_sprite_wireframe(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
frame: &FrameData,
) {
let need_sprite_wf = frame.viewport.wireframe_mode
|| frame
.scene
.sprite_items
.iter()
.any(|s| !s.settings.hidden && s.settings.wireframe);
if need_sprite_wf {
self.resources.ensure_polyline_pipeline(device);
let vp_size = frame.camera.viewport_size;
for item in &frame.scene.sprite_items {
if item.settings.hidden {
continue;
}
if !(frame.viewport.wireframe_mode || item.settings.wireframe) {
continue;
}
if item.positions.is_empty() {
continue;
}
let polyline = sprite_wireframe_polyline(item, &frame.camera);
if !polyline.positions.is_empty() {
let gpu = self
.resources
.upload_polyline_per_frame(device, queue, &polyline, vp_size);
self.polyline_gpu_data.push(gpu);
}
}
}
}
pub(super) fn prepare_debug_buffer(&mut self, device: &wgpu::Device, frame: &FrameData) {
{
let vp_idx = frame.camera.viewport_index;
let debug_active = frame.effects.lighting.debug_vis.active;
let ppp = frame.camera.pixels_per_point;
let vw = (frame.camera.viewport_size[0] * ppp).max(1.0) as u32;
let vh = (frame.camera.viewport_size[1] * ppp).max(1.0) as u32;
let slot = &self.viewport_slots[vp_idx];
if debug_active && slot.debug_frag_dims != (vw, vh) {
let size = (vw as u64) * (vh as u64) * 16;
let new_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("debug_frag_buf"),
size: size.max(16),
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC,
mapped_at_creation: false,
});
let new_bg = self.resources.create_camera_bind_group(
device,
&self.viewport_slots[vp_idx].camera_buf,
&self.viewport_slots[vp_idx].clip_planes_buf,
&self.viewport_slots[vp_idx].shadow_info_buf,
&self.viewport_slots[vp_idx].clip_volume_buf,
&new_buf,
"per_viewport_camera_bg_debug",
);
self.viewport_slots[vp_idx].debug_frag_buf = Some(new_buf);
self.viewport_slots[vp_idx].debug_frag_dims = (vw, vh);
self.viewport_slots[vp_idx].camera_bind_group = new_bg;
} else if !debug_active && slot.debug_frag_buf.is_some() {
let sentinel = &self.resources.debug_frag_sentinel_buf;
let new_bg = self.resources.create_camera_bind_group(
device,
&self.viewport_slots[vp_idx].camera_buf,
&self.viewport_slots[vp_idx].clip_planes_buf,
&self.viewport_slots[vp_idx].shadow_info_buf,
&self.viewport_slots[vp_idx].clip_volume_buf,
sentinel,
"per_viewport_camera_bg",
);
self.viewport_slots[vp_idx].debug_frag_buf = None;
self.viewport_slots[vp_idx].debug_frag_dims = (0, 0);
self.viewport_slots[vp_idx].camera_bind_group = new_bg;
}
}
}
pub(super) fn prepare_atlas_blit(
&mut self,
queue: &wgpu::Queue,
frame: &FrameData,
viewport_fx: &ViewportEffects<'_>,
) {
if viewport_fx.show_shadow_atlas {
let vw = frame.camera.viewport_size[0].max(1.0);
let vh = frame.camera.viewport_size[1].max(1.0);
let scale = viewport_fx.atlas_viewer_scale.clamp(0.05, 1.0);
let ndc_w = scale * 2.0;
let ndc_h = ndc_w * (vw / vh);
let margin_x = 20.0 / vw * 2.0;
let margin_y = 20.0 / vh * 2.0;
#[allow(unreachable_patterns)]
let rect = match viewport_fx.atlas_viewer_corner {
crate::renderer::types::debug::AtlasViewerCorner::BottomRight => {
let xmax = 1.0 - margin_x;
let ymin = -1.0 + margin_y;
[xmax - ndc_w, ymin, xmax, ymin + ndc_h]
}
crate::renderer::types::debug::AtlasViewerCorner::BottomLeft => {
let xmin = -1.0 + margin_x;
let ymin = -1.0 + margin_y;
[xmin, ymin, xmin + ndc_w, ymin + ndc_h]
}
crate::renderer::types::debug::AtlasViewerCorner::TopRight => {
let xmax = 1.0 - margin_x;
let ymax = 1.0 - margin_y;
[xmax - ndc_w, ymax - ndc_h, xmax, ymax]
}
crate::renderer::types::debug::AtlasViewerCorner::TopLeft => {
let xmin = -1.0 + margin_x;
let ymax = 1.0 - margin_y;
[xmin, ymax - ndc_h, xmin + ndc_w, ymax]
}
_ => [0.4, -1.0, 1.0, -0.4], };
queue.write_buffer(
&self.resources.shadow_atlas_viewer_buf,
0,
bytemuck::cast_slice(&[crate::resources::AtlasBlitUniform { rect }]),
);
}
}
}