158 lines
4.6 KiB
Rust
158 lines
4.6 KiB
Rust
use bytemuck::{Pod, Zeroable};
|
|
use cgmath::Vector3;
|
|
|
|
#[repr(u32)]
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum LightType {
|
|
Directional = 0,
|
|
Point = 1,
|
|
Spot = 2
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone, Copy, Pod, Zeroable, Debug)]
|
|
pub struct GpuLight {
|
|
pub position: [f32; 3],
|
|
pub light_type: u32,
|
|
pub color: [f32; 3],
|
|
pub intensity: f32,
|
|
pub direction: [f32; 3],
|
|
pub range: f32,
|
|
pub inner_cutoff: f32,
|
|
pub outer_cutoff: f32,
|
|
}
|
|
|
|
pub struct Light {
|
|
pub light_type: LightType,
|
|
pub position: Vector3<f32>,
|
|
pub direction: Vector3<f32>,
|
|
pub color: Vector3<f32>,
|
|
pub intensity: f32,
|
|
pub range: f32,
|
|
pub inner_cutoff: f32,
|
|
pub outer_cutoff: f32,
|
|
}
|
|
|
|
impl Light {
|
|
pub fn to_gpu(&self) -> GpuLight {
|
|
GpuLight {
|
|
position: self.position.into(),
|
|
light_type: self.light_type as u32,
|
|
color: self.color.into(),
|
|
intensity: self.intensity,
|
|
direction: self.direction.into(),
|
|
range: self.range,
|
|
inner_cutoff: self.inner_cutoff,
|
|
outer_cutoff: self.outer_cutoff,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct LightManager {
|
|
pub lights: Vec<Light>,
|
|
pub buffer: wgpu::Buffer,
|
|
pub bind_group: wgpu::BindGroup,
|
|
pub count_buffer: wgpu::Buffer,
|
|
pub layout: wgpu::BindGroupLayout
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone, Copy, Pod, Zeroable, Debug)]
|
|
pub struct LightCount {
|
|
pub count: u32,
|
|
}
|
|
|
|
impl LightManager {
|
|
pub fn new(device: &wgpu::Device, max_lights: usize) -> Self {
|
|
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: Some("Light Buffer"),
|
|
size: (max_lights * size_of::<GpuLight>()) as wgpu::BufferAddress,
|
|
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
|
mapped_at_creation: false,
|
|
});
|
|
|
|
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
label: Some("Light Bind Group Layout"),
|
|
entries: &[
|
|
// Binding 0: Storage buffer for lights
|
|
wgpu::BindGroupLayoutEntry {
|
|
binding: 0,
|
|
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
|
ty: wgpu::BindingType::Buffer {
|
|
ty: wgpu::BufferBindingType::Storage { read_only: true },
|
|
has_dynamic_offset: false,
|
|
min_binding_size: None,
|
|
},
|
|
count: None,
|
|
},
|
|
// Binding 1: Uniform buffer for light count
|
|
wgpu::BindGroupLayoutEntry {
|
|
binding: 1,
|
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
ty: wgpu::BindingType::Buffer {
|
|
ty: wgpu::BufferBindingType::Uniform,
|
|
has_dynamic_offset: false,
|
|
min_binding_size: None,
|
|
},
|
|
count: None,
|
|
},
|
|
],
|
|
});
|
|
|
|
let count_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: Some("Light Count Buffer"),
|
|
size: size_of::<LightCount>() as wgpu::BufferAddress,
|
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
mapped_at_creation: false,
|
|
});
|
|
|
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
label: Some("Light Bind Group"),
|
|
layout: &layout,
|
|
entries: &[
|
|
wgpu::BindGroupEntry {
|
|
binding: 0,
|
|
resource: buffer.as_entire_binding(),
|
|
},
|
|
wgpu::BindGroupEntry {
|
|
binding: 1,
|
|
resource: count_buffer.as_entire_binding(),
|
|
},
|
|
],
|
|
});
|
|
|
|
Self {
|
|
lights: Vec::new(),
|
|
buffer,
|
|
bind_group,
|
|
layout,
|
|
count_buffer,
|
|
}
|
|
}
|
|
|
|
pub fn add_light(&mut self, light: Light) {
|
|
self.lights.push(light);
|
|
}
|
|
|
|
pub fn update_gpu(&self, queue: &wgpu::Queue) {
|
|
let data: Vec<GpuLight> = self.lights.iter().map(|l| l.to_gpu()).collect();
|
|
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&data));
|
|
|
|
let count = LightCount {
|
|
count: self.lights.len() as u32,
|
|
};
|
|
queue.write_buffer(&self.count_buffer, 0, bytemuck::bytes_of(&count));
|
|
}
|
|
|
|
pub fn bind_group(&self) -> &wgpu::BindGroup {
|
|
&self.bind_group
|
|
}
|
|
|
|
pub fn layout(&self) -> &wgpu::BindGroupLayout {
|
|
&self.layout
|
|
}
|
|
|
|
pub fn clear(&mut self) {
|
|
self.lights.clear();
|
|
}
|
|
} |