diff --git a/src/app/dem_renderer.rs b/src/app/dem_renderer.rs index e5b134d..980ba3c 100644 --- a/src/app/dem_renderer.rs +++ b/src/app/dem_renderer.rs @@ -12,6 +12,8 @@ pub struct DemRenderer { vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, index_count: usize, + uniforms: Uniforms, + animation_start: std::time::Instant, } #[repr(C)] @@ -20,6 +22,51 @@ struct Vertex { position: [f32; 4], } +struct Uniforms { + projection_matrix: glam::Mat4, + view_matrix: glam::Mat4, + buffer: wgpu::Buffer, +} + +impl Uniforms { + fn new(device: &wgpu::Device, aspect_ratio: f32) -> Self { + let projection_matrix = + glam::Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, aspect_ratio, 1.0, 10.0); + let view_matrix = glam::Mat4::look_at_rh(glam::Vec3::ZERO, glam::Vec3::ZERO, glam::Vec3::Z); + let camera_matrix = projection_matrix * view_matrix; + let camera_matrix_ref: &[f32; 16] = camera_matrix.as_ref(); + let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Uniform Buffer"), + contents: bytemuck::cast_slice(camera_matrix_ref), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + Self { + projection_matrix, + view_matrix, + buffer, + } + } + + fn set_camera_position(&mut self, position: glam::Vec3) { + self.view_matrix = glam::Mat4::look_at_rh(position, glam::Vec3::ZERO, glam::Vec3::Z); + } + + fn set_aspect_ratio(&mut self, ratio: f32) { + self.projection_matrix = + glam::Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, ratio, 1.0, 10.0); + } + + fn update_buffer(&self, queue: &wgpu::Queue) { + let camera_matrix = self.projection_matrix * self.view_matrix; + let camera_matrix_ref: &[f32; 16] = camera_matrix.as_ref(); + queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(camera_matrix_ref)) + } + + fn binding(&self) -> wgpu::BindingResource<'_> { + self.buffer.as_entire_binding() + } +} + impl DemRenderer { pub fn new( source: Rc, @@ -42,16 +89,10 @@ impl DemRenderer { let index_count = index_data.len(); - let uniform_buf = { - let mx_total = - generate_matrix(surface_config.width as f32 / surface_config.height as f32); - let mx_ref: &[f32; 16] = mx_total.as_ref(); - device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Uniform Buffer"), - contents: bytemuck::cast_slice(mx_ref), - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - }) - }; + let uniforms = Uniforms::new( + device, + surface_config.width as f32 / surface_config.height as f32, + ); let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -83,7 +124,7 @@ impl DemRenderer { layout: &bind_group_layout, entries: &[wgpu::BindGroupEntry { binding: 0, - resource: uniform_buf.as_entire_binding(), + resource: uniforms.binding(), }], label: Some("DemRendererBindGroup"), }); @@ -140,6 +181,8 @@ impl DemRenderer { vertex_buffer, index_buffer, index_count, + animation_start: std::time::Instant::now(), + uniforms, } } @@ -147,6 +190,9 @@ impl DemRenderer { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("DemRendererCommandEncoder"), }); + self.uniforms + .set_camera_position(get_animated_camera_position(self.animation_start.elapsed())); + self.uniforms.update_buffer(queue); { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("DemRendererRenderPass"), @@ -224,13 +270,11 @@ fn create_vertices() -> (Vec, Vec) { (vertex_data.to_vec(), index_data.to_vec()) } -fn generate_matrix(aspect_ratio: f32) -> glam::Mat4 { - let projection = - glam::Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, aspect_ratio, 1.0, 10.0); - let view = glam::Mat4::look_at_rh( - glam::Vec3::new(1.5f32, -5.0, 3.0), - glam::Vec3::ZERO, - glam::Vec3::Z, - ); - projection * view +fn get_animated_camera_position(animation_time: std::time::Duration) -> glam::Vec3 { + let animation_phase = 2.0 * std::f32::consts::PI * (animation_time.as_secs_f32() % 10.0) / 10.0; + glam::Vec3::new( + 5.0 * f32::sin(animation_phase), + 5.0 * f32::cos(animation_phase), + 3.0, + ) }