Skip to content

Commit

Permalink
added lazy rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
KeKsBoTer committed Jan 29, 2024
1 parent d3820ac commit 79d48c6
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 42 deletions.
19 changes: 19 additions & 0 deletions src/camera.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::hash::{Hash, Hasher};
use cgmath::*;

use crate::animation::Lerp;
Expand All @@ -23,6 +24,14 @@ impl PerspectiveCamera {
}
}

impl Hash for PerspectiveCamera {
fn hash<H: Hasher>(&self, state: &mut H) {
bytemuck::bytes_of(&self.position).hash(state);
bytemuck::bytes_of(&self.rotation).hash(state);
self.projection.hash(state);
}
}

impl Lerp for PerspectiveCamera {
// using SPLIT interpolation to interpolate between two cameras
// see Kim et al. "A general construction scheme for unit quaternion curves with simple high order derivatives."
Expand Down Expand Up @@ -72,6 +81,16 @@ pub struct PerspectiveProjection {
fov2view_ratio: f32,
}

impl Hash for PerspectiveProjection {
fn hash<H: Hasher>(&self, state: &mut H) {
self.fov.x.0.to_bits().hash(state);
self.fov.y.0.to_bits().hash(state);
self.znear.to_bits().hash(state);
self.zfar.to_bits().hash(state);
self.fov2view_ratio.to_bits().hash(state);
}
}

#[rustfmt::skip]
pub const VIEWPORT_Y_FLIP: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
1.0, 0.0, 0.0, 0.0,
Expand Down
14 changes: 13 additions & 1 deletion src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,22 @@ impl CameraController {
camera.rotation = Quaternion::look_at(-new_dir, up);

// decay based on fps
let decay = (0.8).powf(dt * 60.);
let mut decay = (0.8).powf(dt * 60.);
if decay < 1e-4{
decay = 0.;
}
self.rotation *= decay;
if self.rotation.magnitude() < 1e-4 {
self.rotation = Vector3::zero();
}
self.shift *= decay;
if self.shift.magnitude() < 1e-4 {
self.shift = Vector2::zero();
}
self.scroll *= decay;
if self.scroll.abs() < 1e-4 {
self.scroll = 0.;
}
self.user_inptut = false;
}
}
Expand Down
60 changes: 39 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::io::{Read, Seek};
use std::{collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, io::{Read, Seek}};

#[cfg(target_arch = "wasm32")]
use instant::{Duration, Instant};
use renderer::Display;
use renderer::{Display, RenderSettings};
#[cfg(not(target_arch = "wasm32"))]
use std::time::{Duration, Instant};
use wgpu::Backends;
Expand Down Expand Up @@ -142,6 +142,11 @@ struct WindowContext {
display: Display,

background_color: egui::Color32,
gaussian_scale_factor: f32,

/// hash for the render settings
/// if render settings dont change we dont have to rerender
render_settings_hash:Option<u64>
}

impl WindowContext {
Expand Down Expand Up @@ -247,6 +252,8 @@ impl WindowContext {
ui_visible: true,
display,
background_color: Color32::BLACK,
render_settings_hash:None,
gaussian_scale_factor: 1.,
}
}

Expand Down Expand Up @@ -437,6 +444,9 @@ impl WindowContext {
&mut self.background_color,
egui::color_picker::Alpha::BlendOrAdditive,
);
ui.end_row();
ui.label("Gaussian Scaling");
ui.add(egui::DragValue::new(&mut self.gaussian_scale_factor).clamp_range(1e-4..=1.).speed(1e-2));
});
});

Expand Down Expand Up @@ -528,22 +538,28 @@ impl WindowContext {
..Default::default()
});
let view_srgb = output.texture.create_view(&Default::default());
let viewport = Vector2::new(output.texture.size().width, output.texture.size().height);
let rgba = self.background_color.to_srgba_unmultiplied();
self.renderer.render(
&self.wgpu_context.device,
&self.wgpu_context.queue,
&self.pc,
self.camera,
viewport,
self.display.texture(),
wgpu::Color {
r: rgba[0] as f64 / 255.,
g: rgba[1] as f64 / 255.,
b: rgba[2] as f64 / 255.,
a: rgba[3] as f64 / 255.,
},
);

let render_settings = RenderSettings {
camera: self.camera,
viewport:Vector2::new(output.texture.size().width, output.texture.size().height),
gaussian_scaling: self.gaussian_scale_factor,
};
let mut hasher = DefaultHasher::new();
render_settings.hash(&mut hasher);
let settings_hash = hasher.finish();

if self.render_settings_hash.and_then(|v|Some(v!=settings_hash)).unwrap_or(true){
self.renderer.render(
&self.wgpu_context.device,
&self.wgpu_context.queue,
&self.pc,
self.display.texture(),
render_settings,
);
self.render_settings_hash.replace(settings_hash);
}


let mut encoder =
self.wgpu_context
Expand All @@ -552,7 +568,12 @@ impl WindowContext {
label: Some("display"),
});

self.display.render(&mut encoder, &view_rgb);
self.display.render(&mut encoder, &view_rgb, wgpu::Color {
r: rgba[0] as f64 / 255.,
g: rgba[1] as f64 / 255.,
b: rgba[2] as f64 / 255.,
a: rgba[3] as f64 / 255.,
},);
self.wgpu_context.queue.submit([encoder.finish()]);

if self.ui_visible {
Expand All @@ -573,9 +594,6 @@ impl WindowContext {
&view_srgb,
shapes,
);
} else {
#[cfg(not(target_arch = "wasm32"))]
self.renderer.stopwatch.reset();
}

output.present();
Expand Down
76 changes: 58 additions & 18 deletions src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{

#[cfg(not(target_arch = "wasm32"))]
use crate::utils::GPUStopwatch;
use std::hash::{Hash, Hasher};
use std::num::NonZeroU64;

#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -18,6 +19,7 @@ use cgmath::{Matrix4, SquareMatrix, Vector2};
pub struct GaussianRenderer {
pipeline: wgpu::RenderPipeline,
camera: UniformBuffer<CameraUniform>,
render_settings:UniformBuffer<RenderSettingsUniform>,
preprocess: PreprocessPipeline,
draw_indirect_buffer: wgpu::Buffer,
#[allow(dead_code)]
Expand Down Expand Up @@ -116,6 +118,7 @@ impl GaussianRenderer {
stopwatch,
sorter,
sorter_suff: None,
render_settings:UniformBuffer::new_default(device,Some("render settings uniform buffer")),
}
}

Expand All @@ -124,16 +127,21 @@ impl GaussianRenderer {
encoder: &'a mut wgpu::CommandEncoder,
queue: &wgpu::Queue,
pc: &'a PointCloud,
camera: PerspectiveCamera,
viewport: Vector2<u32>,
render_settings:RenderSettings,
) {
let mut camera = camera;
camera.projection.resize(viewport.x, viewport.y);
let mut camera = render_settings.camera;
camera.projection.resize(render_settings.viewport.x, render_settings.viewport.y);
let uniform = self.camera.as_mut();
uniform.set_camera(camera);
uniform.set_focal(camera.projection.focal(viewport));
uniform.set_viewport(viewport.cast().unwrap());
uniform.set_focal(camera.projection.focal(render_settings.viewport));
uniform.set_viewport(render_settings.viewport.cast().unwrap());
self.camera.sync(queue);


let settings_uniform = self.render_settings.as_mut();
settings_uniform.gaussian_scaling = render_settings.gaussian_scaling;
self.render_settings.sync(queue);

// TODO perform this in vertex buffer after draw call
queue.write_buffer(
&self.draw_indirect_buffer,
Expand All @@ -147,7 +155,7 @@ impl GaussianRenderer {
.as_bytes(),
);
let depth_buffer = &self.sorter_suff.as_ref().unwrap().sorter_bg_pre;
self.preprocess.run(encoder, pc, &self.camera, depth_buffer);
self.preprocess.run(encoder, pc, &self.camera,&self.render_settings, depth_buffer);
}

#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -177,10 +185,8 @@ impl GaussianRenderer {
device: &wgpu::Device,
queue: &wgpu::Queue,
pc: &'a PointCloud,
camera: PerspectiveCamera,
viewport: Vector2<u32>,
target: &wgpu::TextureView,
background_color: wgpu::Color,
render_settings:RenderSettings,
) {
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
Expand Down Expand Up @@ -208,7 +214,7 @@ impl GaussianRenderer {
// convert 3D gaussian splats to 2D gaussian splats
#[cfg(not(target_arch = "wasm32"))]
self.stopwatch.start(&mut encoder, "preprocess").unwrap();
self.preprocess(&mut encoder, queue, &pc, camera, viewport);
self.preprocess(&mut encoder, queue, &pc, render_settings);
#[cfg(not(target_arch = "wasm32"))]
self.stopwatch.stop(&mut encoder, "preprocess").unwrap();

Expand Down Expand Up @@ -242,7 +248,7 @@ impl GaussianRenderer {
view: target,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(background_color),
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
store: wgpu::StoreOp::Store,
},
})],
Expand Down Expand Up @@ -275,10 +281,11 @@ impl GaussianRenderer {
queue: &wgpu::Queue,
) -> RenderStatistics {
let durations = self.stopwatch.take_measurements(device, queue).await;
self.stopwatch.reset();
RenderStatistics {
preprocess_time: durations["preprocess"],
sort_time: durations["sorting"],
rasterization_time: durations["rasterization"],
preprocess_time: *durations.get("preprocess").unwrap_or(&Duration::ZERO),
sort_time:*durations.get("sorting").unwrap_or(&Duration::ZERO),
rasterization_time: *durations.get("rasterization").unwrap_or(&Duration::ZERO),
}
}

Expand Down Expand Up @@ -375,6 +382,7 @@ impl PreprocessPipeline {
PointCloud::bind_group_layout(device)
},
&GPURSSorter::bind_group_layout_preprocess(device),
&UniformBuffer::<RenderSettingsUniform>::bind_group_layout(device),
],
push_constant_ranges: &[],
});
Expand Down Expand Up @@ -412,6 +420,7 @@ impl PreprocessPipeline {
encoder: &'a mut wgpu::CommandEncoder,
pc: &PointCloud,
camera: &UniformBuffer<CameraUniform>,
render_settings: &UniformBuffer<RenderSettingsUniform>,
sort_bg: &wgpu::BindGroup,
) {
let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
Expand All @@ -422,6 +431,7 @@ impl PreprocessPipeline {
pass.set_bind_group(0, camera.bind_group(), &[]);
pass.set_bind_group(1, pc.bind_group(), &[]);
pass.set_bind_group(2, &sort_bg, &[]);
pass.set_bind_group(3, render_settings.bind_group(), &[]);

let wgs_x = (pc.num_points() as f32 / 256.0).ceil() as u32;
pass.dispatch_workgroups(wgs_x, 1, 1);
Expand Down Expand Up @@ -475,7 +485,7 @@ impl Display {
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: target_format,
blend: None,
blend: Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
Expand Down Expand Up @@ -567,14 +577,14 @@ impl Display {
self.view = view;
}

pub fn render(&self, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView) {
pub fn render(&self, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView,background_color:wgpu::Color) {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("render pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
load: wgpu::LoadOp::Clear(background_color),
store: wgpu::StoreOp::Store,
},
})],
Expand All @@ -586,3 +596,33 @@ impl Display {
render_pass.draw(0..4, 0..1);
}
}


#[repr(C)]
#[derive(Copy, Clone,Debug) ]
pub struct RenderSettings{
pub camera:PerspectiveCamera,
pub viewport:Vector2<u32>,
pub gaussian_scaling:f32,
}

impl Hash for RenderSettings {
fn hash<H: Hasher>(&self, state: &mut H) {
self.camera.hash(state);
self.viewport.hash(state);
self.gaussian_scaling.to_bits().hash(state);
}
}

#[repr(C)]
#[derive(Copy, Clone,Debug,bytemuck::Pod,bytemuck::Zeroable) ]
struct RenderSettingsUniform{
gaussian_scaling:f32
}
impl Default for RenderSettingsUniform{
fn default() -> Self {
Self{
gaussian_scaling:1.0
}
}
}
12 changes: 11 additions & 1 deletion src/shaders/preprocess.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ struct SortInfos {
odd_pass: u32,
}

struct RenderSettings{
gaussian_scaling:f32
}


@group(0) @binding(0)
var<uniform> camera: CameraUniforms;

Expand Down Expand Up @@ -120,6 +125,8 @@ var<storage, read_write> sort_indices : array<u32>;
@group(2) @binding(3)
var<storage, read_write> sort_dispatch: DispatchIndirect;

@group(3) @binding(0)
var<uniform> render_settings: RenderSettings;

fn dequantize(value: i32, quantization: Quantization) -> f32 {
return (f32(value) - f32(quantization.zero_point)) * quantization.scaling;
Expand Down Expand Up @@ -223,11 +230,14 @@ fn preprocess(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgr
let cov1: vec2<f32> = unpack2x16float(geometric_info.cov[0]) * s2;
let cov2: vec2<f32> = unpack2x16float(geometric_info.cov[1]) * s2;
let cov3: vec2<f32> = unpack2x16float(geometric_info.cov[2]) * s2;


let scaling = render_settings.gaussian_scaling;
let Vrk = mat3x3<f32>(
cov1[0], cov1[1], cov2[0],
cov1[1], cov2[1], cov3[0],
cov2[0], cov3[0], cov3[1]
);
)*scaling*scaling;
let J = mat3x3<f32>(
focal.x / camspace.z,
0.,
Expand Down
Loading

0 comments on commit 79d48c6

Please sign in to comment.