Skip to main content

oxide_engine/camera/
uniform.rs

1//! Camera uniform buffer for GPU
2
3use bytemuck::{Pod, Zeroable};
4use glam::Mat4;
5use wgpu::{Buffer, BufferDescriptor, BufferUsages, Device};
6
7#[repr(C)]
8#[derive(Copy, Clone, Debug, Pod, Zeroable)]
9pub struct CameraUniform {
10    view_proj: [[f32; 4]; 4],
11    position: [f32; 4],
12}
13
14impl Default for CameraUniform {
15    fn default() -> Self {
16        Self {
17            view_proj: Mat4::IDENTITY.to_cols_array_2d(),
18            position: [0.0, 0.0, 0.0, 1.0],
19        }
20    }
21}
22
23impl CameraUniform {
24    pub fn new() -> Self {
25        Self::default()
26    }
27
28    pub fn update(&mut self, view_proj: Mat4, position: glam::Vec3) {
29        self.view_proj = view_proj.to_cols_array_2d();
30        self.position = [position.x, position.y, position.z, 1.0];
31    }
32}
33
34pub struct CameraBuffer {
35    pub buffer: Buffer,
36    pub bind_group_layout: wgpu::BindGroupLayout,
37    pub bind_group: wgpu::BindGroup,
38}
39
40impl CameraBuffer {
41    pub fn new(device: &Device) -> Self {
42        let buffer = device.create_buffer(&BufferDescriptor {
43            label: Some("Camera Buffer"),
44            size: std::mem::size_of::<CameraUniform>() as wgpu::BufferAddress,
45            usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
46            mapped_at_creation: false,
47        });
48
49        let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
50            label: Some("Camera Bind Group Layout"),
51            entries: &[wgpu::BindGroupLayoutEntry {
52                binding: 0,
53                visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
54                ty: wgpu::BindingType::Buffer {
55                    ty: wgpu::BufferBindingType::Uniform,
56                    has_dynamic_offset: false,
57                    min_binding_size: None,
58                },
59                count: None,
60            }],
61        });
62
63        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
64            label: Some("Camera Bind Group"),
65            layout: &bind_group_layout,
66            entries: &[wgpu::BindGroupEntry {
67                binding: 0,
68                resource: buffer.as_entire_binding(),
69            }],
70        });
71
72        Self {
73            buffer,
74            bind_group_layout,
75            bind_group,
76        }
77    }
78
79    pub fn update(&self, queue: &wgpu::Queue, uniform: &CameraUniform) {
80        queue.write_buffer(&self.buffer, 0, bytemuck::bytes_of(uniform));
81    }
82}