Get multiple light sources working
ci/woodpecker/push/build Pipeline was successful
Details
ci/woodpecker/push/build Pipeline was successful
Details
This commit is contained in:
parent
6510d5a7b9
commit
aa79ace401
|
@ -90,16 +90,27 @@ async fn main() {
|
||||||
quadratic: 0.032,
|
quadratic: 0.032,
|
||||||
};
|
};
|
||||||
world.spawn((light,)); */
|
world.spawn((light,)); */
|
||||||
let pos = Vec3::new(0.0, 0.0, -10.0);
|
|
||||||
world.spawn((
|
world.spawn((
|
||||||
PointLight {
|
PointLight {
|
||||||
color: Vec3::new(1.0, 1.0, 1.0),
|
color: Vec3::new(1.0, 1.0, 1.0),
|
||||||
intensity: 2.0,
|
intensity: 1.0,
|
||||||
constant: 1.0,
|
constant: 1.0,
|
||||||
linear: 0.045,
|
linear: 0.045,
|
||||||
quadratic: 0.0075,
|
quadratic: 0.0075,
|
||||||
},
|
},
|
||||||
TransformComponent::from(Transform::from_xyz(pos.x, pos.y, pos.z)),
|
TransformComponent::from(Transform::from_xyz(-2.5, 0.0, -10.0)),
|
||||||
|
ModelComponent(cube_model.clone()),
|
||||||
|
));
|
||||||
|
|
||||||
|
world.spawn((
|
||||||
|
PointLight {
|
||||||
|
color: Vec3::new(0.361, 0.984, 0.0),
|
||||||
|
intensity: 1.0,
|
||||||
|
constant: 1.0,
|
||||||
|
linear: 0.045,
|
||||||
|
quadratic: 0.0075,
|
||||||
|
},
|
||||||
|
TransformComponent::from(Transform::from_xyz(2.5, 0.0, -10.0)),
|
||||||
ModelComponent(cube_model),
|
ModelComponent(cube_model),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod point;
|
pub mod point;
|
||||||
use std::{collections::{VecDeque, HashMap}, num::NonZeroU64};
|
use std::{collections::{VecDeque, HashMap}, num::NonZeroU64, marker::PhantomData};
|
||||||
|
|
||||||
use edict::query::EpochOf;
|
use edict::query::EpochOf;
|
||||||
pub use point::*;
|
pub use point::*;
|
||||||
|
@ -10,11 +10,10 @@ use std::mem;
|
||||||
|
|
||||||
use crate::{math::Transform, ecs::components::TransformComponent};
|
use crate::{math::Transform, ecs::components::TransformComponent};
|
||||||
|
|
||||||
pub struct LightBuffer {
|
const MAX_LIGHT_COUNT: usize = 32;
|
||||||
pub bind_group: wgpu::BindGroup,
|
|
||||||
/// The buffer on the gpu storing the lights
|
pub struct LightBuffer<U: Default + bytemuck::Pod + bytemuck::Zeroable> {
|
||||||
buffer: wgpu::Buffer,
|
_phantom: PhantomData<U>,
|
||||||
device_limits: wgpu::Limits,
|
|
||||||
/// The max amount of light casters that could fit in this buffer.
|
/// The max amount of light casters that could fit in this buffer.
|
||||||
pub max_count: usize,
|
pub max_count: usize,
|
||||||
/// The current amount of light casters in this buffer.
|
/// The current amount of light casters in this buffer.
|
||||||
|
@ -25,59 +24,10 @@ pub struct LightBuffer {
|
||||||
dead_indexes: VecDeque<usize>,
|
dead_indexes: VecDeque<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightBuffer {
|
impl<U: Default + bytemuck::Pod + bytemuck::Zeroable> LightBuffer<U> {
|
||||||
pub fn new<U>(device: &wgpu::Device, layout: &wgpu::BindGroupLayout, max_count: usize) -> Self
|
pub fn new(layout: &wgpu::BindGroupLayout, max_count: usize) -> Self {
|
||||||
where
|
|
||||||
U: Default + bytemuck::Pod + bytemuck::Zeroable
|
|
||||||
{
|
|
||||||
let device_limits = device.limits();
|
|
||||||
|
|
||||||
let buffer = device.create_buffer(
|
|
||||||
&wgpu::BufferDescriptor {
|
|
||||||
label: Some("Light buffer"),
|
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
||||||
size: (mem::size_of::<U>() * max_count) as u64,//render_limits.max_uniform_buffer_binding_size as u64,
|
|
||||||
mapped_at_creation: false,
|
|
||||||
/* label: Some("Light Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&[U::default()]),
|
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, */
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/* let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: buffer.as_entire_binding(),
|
|
||||||
}
|
|
||||||
],
|
|
||||||
label: Some("light_bind_group"),
|
|
||||||
}); */
|
|
||||||
|
|
||||||
let stride = device_limits.min_uniform_buffer_offset_alignment as usize + mem::size_of::<U>();
|
|
||||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: wgpu::BindingResource::Buffer(
|
|
||||||
wgpu::BufferBinding {
|
|
||||||
buffer: &buffer,
|
|
||||||
offset: 0,
|
|
||||||
size: Some(NonZeroU64::new(stride as u64).unwrap())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
label: Some("light_bind_group"),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
_phantom: PhantomData::default(),
|
||||||
bind_group,
|
|
||||||
device_limits,
|
|
||||||
max_count,
|
max_count,
|
||||||
current_count: 0,
|
current_count: 0,
|
||||||
used_indexes: HashMap::new(),
|
used_indexes: HashMap::new(),
|
||||||
|
@ -90,16 +40,15 @@ impl LightBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update an existing light in the light buffer.
|
/// Update an existing light in the light buffer.
|
||||||
pub fn update_light(&mut self, queue: &wgpu::Queue, entity: edict::EntityId, light: &PointLightUniform) {
|
pub fn update_light(&mut self, lights_buffer: &mut [U; MAX_LIGHT_COUNT], entity: edict::EntityId, light: U) {
|
||||||
let buffer_idx = *self.used_indexes.get(&entity)
|
let buffer_idx = *self.used_indexes.get(&entity)
|
||||||
.expect("Entity for Light is not in buffer!");
|
.expect("Entity for Light is not in buffer!");
|
||||||
|
|
||||||
let offset = buffer_idx as u64 * self.device_limits.min_uniform_buffer_offset_alignment as u64;
|
lights_buffer[buffer_idx] = light;
|
||||||
queue.write_buffer(&self.buffer, offset, bytemuck::bytes_of(light));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new light to the light buffer.
|
/// Add a new light to the light buffer.
|
||||||
pub fn add_light(&mut self, queue: &wgpu::Queue, entity: edict::EntityId, light: &PointLightUniform) {
|
pub fn add_light(&mut self, lights_buffer: &mut [U; MAX_LIGHT_COUNT], entity: edict::EntityId, light: U) {
|
||||||
let buffer_idx = match self.dead_indexes.pop_front() {
|
let buffer_idx = match self.dead_indexes.pop_front() {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
|
@ -110,15 +59,15 @@ impl LightBuffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.used_indexes.insert(entity, buffer_idx);
|
self.used_indexes.insert(entity, buffer_idx);
|
||||||
self.update_light(queue, entity, light);
|
self.update_light(lights_buffer, entity, light);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update, or add a new caster, to the light buffer.
|
/// Update, or add a new caster, to the light buffer.
|
||||||
pub fn update_or_add(&mut self, queue: &wgpu::Queue, entity: edict::EntityId, light: &PointLightUniform) {
|
pub fn update_or_add(&mut self, lights_buffer: &mut [U; MAX_LIGHT_COUNT], entity: edict::EntityId, light: U) {
|
||||||
if self.used_indexes.contains_key(&entity) {
|
if self.used_indexes.contains_key(&entity) {
|
||||||
self.update_light(queue, entity, light);
|
self.update_light(lights_buffer, entity, light);
|
||||||
} else {
|
} else {
|
||||||
self.add_light(queue, entity, light);
|
self.add_light(lights_buffer, entity, light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,14 +81,24 @@ impl LightBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LightUniformBuffers {
|
pub struct LightUniformBuffers {
|
||||||
|
pub buffer: wgpu::Buffer,
|
||||||
pub bindgroup_layout: wgpu::BindGroupLayout,
|
pub bindgroup_layout: wgpu::BindGroupLayout,
|
||||||
pub point_lights: LightBuffer,
|
pub bindgroup: wgpu::BindGroup,
|
||||||
//spotlights: LightBuffer,
|
pub lights_uniform: LightsUniform,
|
||||||
//directional_light
|
pub point_lights: LightBuffer<PointLightUniform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightUniformBuffers {
|
impl LightUniformBuffers {
|
||||||
pub fn new(device: &wgpu::Device) -> Self {
|
pub fn new(device: &wgpu::Device) -> Self {
|
||||||
|
let buffer = device.create_buffer(
|
||||||
|
&wgpu::BufferDescriptor {
|
||||||
|
label: Some("Lights Uniform buffer"),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
|
size: mem::size_of::<LightsUniform>() as u64,
|
||||||
|
mapped_at_creation: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
@ -153,41 +112,58 @@ impl LightUniformBuffers {
|
||||||
count: None,
|
count: None,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
label: Some("light_bind_group_layout"),
|
label: Some("lights_bind_group_layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let point_lights = LightBuffer::new::<PointLightUniform>(device, &bindgroup_layout, 10);
|
let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &bindgroup_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::Buffer(
|
||||||
|
wgpu::BufferBinding {
|
||||||
|
buffer: &buffer,
|
||||||
|
offset: 0,
|
||||||
|
size: Some(NonZeroU64::new(mem::size_of::<LightsUniform>() as u64).unwrap())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
label: Some("light_bind_group"),
|
||||||
|
});
|
||||||
|
|
||||||
|
let point_lights = LightBuffer::new(&bindgroup_layout, MAX_LIGHT_COUNT);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
buffer,
|
||||||
bindgroup_layout,
|
bindgroup_layout,
|
||||||
|
bindgroup,
|
||||||
|
lights_uniform: LightsUniform::default(),
|
||||||
point_lights,
|
point_lights,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_lights(&mut self, queue: &wgpu::Queue, world: &edict::World) {
|
pub fn update_lights(&mut self, queue: &wgpu::Queue, world_epoch: edict::epoch::EpochId, world: &edict::World) {
|
||||||
let now_epoch = world.epoch();
|
|
||||||
for (entity, point_light, transform, light_epoch, transform_epoch)
|
for (entity, point_light, transform, light_epoch, transform_epoch)
|
||||||
in world.query::<(edict::Entities, &PointLight, &TransformComponent, EpochOf<PointLight>, EpochOf<TransformComponent>)>().iter() {
|
in world.query::<(edict::Entities, &PointLight, &TransformComponent, EpochOf<PointLight>, EpochOf<TransformComponent>)>().iter() {
|
||||||
|
|
||||||
/* if !self.point_lights.has_light(entity) || light_epoch == now_epoch || transform_epoch == now_epoch {
|
if !self.point_lights.has_light(entity) || light_epoch == world_epoch || transform_epoch == world_epoch {
|
||||||
debug!("Updated light after update!");
|
|
||||||
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
|
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
|
||||||
self.point_lights.update_or_add(queue, entity, &uniform);
|
self.point_lights.update_or_add(&mut self.lights_uniform.point_lights, entity, uniform);
|
||||||
} */
|
}
|
||||||
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
|
|
||||||
self.point_lights.update_or_add(queue, entity, &uniform);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Binds the light buffer to the render pass.
|
self.lights_uniform.point_light_count = self.point_lights.current_count as u32;
|
||||||
//
|
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.lights_uniform]));
|
||||||
// Parameters:
|
}
|
||||||
// * `render_pass` - The render pass to bind the buffers to.
|
}
|
||||||
// * `point_bind_index` - The bind group index that the point light buffers will be bound to.
|
|
||||||
/* pub fn bind_lights<'a, 'b: 'a>(&'a mut self, render_pass: &'b mut wgpu::RenderPass<'b>, point_bind_index: u32) {
|
#[repr(C)]
|
||||||
render_pass.set_bind_group(point_bind_index, &self.point_lights.bind_group, &[]);
|
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
//render_pass.set_bind_group(3, &self.point_light_bind_group, &[]);
|
pub struct LightsUniform {
|
||||||
} */
|
point_lights: [PointLightUniform; MAX_LIGHT_COUNT],
|
||||||
|
point_light_count: u32,
|
||||||
|
_padding: [u32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -530,6 +530,7 @@ impl BasicRenderer {
|
||||||
impl Renderer for BasicRenderer {
|
impl Renderer for BasicRenderer {
|
||||||
fn prepare(&mut self, main_world: &mut edict::World) {
|
fn prepare(&mut self, main_world: &mut edict::World) {
|
||||||
let last_epoch = main_world.epoch();
|
let last_epoch = main_world.epoch();
|
||||||
|
debug!("Last epoch: {last_epoch:?}");
|
||||||
|
|
||||||
let mut alive_entities = HashSet::new();
|
let mut alive_entities = HashSet::new();
|
||||||
|
|
||||||
|
@ -610,7 +611,7 @@ impl Renderer for BasicRenderer {
|
||||||
warn!("Missing camera!");
|
warn!("Missing camera!");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.light_buffers.update_lights(&self.queue, &main_world);
|
self.light_buffers.update_lights(&self.queue, last_epoch, &main_world);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||||
|
@ -672,7 +673,7 @@ impl Renderer for BasicRenderer {
|
||||||
|
|
||||||
// bind light
|
// bind light
|
||||||
//render_pass.set_bind_group(3, &self.point_light_bind_group, &[]);
|
//render_pass.set_bind_group(3, &self.point_light_bind_group, &[]);
|
||||||
render_pass.set_bind_group(3, &self.light_buffers.point_lights.bind_group, &[]);
|
render_pass.set_bind_group(3, &self.light_buffers.bindgroup, &[]);
|
||||||
////self.light_buffers.bind_lights(&mut render_pass, 3);
|
////self.light_buffers.bind_lights(&mut render_pass, 3);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Vertex shader
|
// Vertex shader
|
||||||
|
|
||||||
const max_light_count: i32 = 10;
|
const max_light_count: u32 = 32u;
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec3<f32>,
|
@location(0) position: vec3<f32>,
|
||||||
|
@ -29,6 +29,11 @@ struct PointLight {
|
||||||
quadratic: f32,
|
quadratic: f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Lights {
|
||||||
|
point_lights: array<PointLight, max_light_count>,
|
||||||
|
point_light_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
@group(1) @binding(0)
|
@group(1) @binding(0)
|
||||||
var<uniform> u_model_transform: mat4x4<f32>;
|
var<uniform> u_model_transform: mat4x4<f32>;
|
||||||
|
|
||||||
|
@ -36,7 +41,7 @@ var<uniform> u_model_transform: mat4x4<f32>;
|
||||||
var<uniform> u_camera: CameraUniform;
|
var<uniform> u_camera: CameraUniform;
|
||||||
|
|
||||||
@group(3) @binding(0)
|
@group(3) @binding(0)
|
||||||
var<uniform> u_point_lights: array<PointLight, max_light_count>;
|
var<uniform> u_lights: Lights;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(
|
fn vs_main(
|
||||||
|
@ -68,8 +73,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
||||||
|
|
||||||
var light_res = vec3<f32>(0.0);
|
var light_res = vec3<f32>(0.0);
|
||||||
for (var i = 0; i < 1; i++) {
|
for (var i = 0u; i < u_lights.point_light_count; i++) {
|
||||||
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_point_lights[i]);
|
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_lights.point_lights[i]);
|
||||||
}
|
}
|
||||||
let light_object_res = light_res * object_color.xyz;
|
let light_object_res = light_res * object_color.xyz;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue