Basic point lights
This commit is contained in:
parent
a3cdf9ef2a
commit
70336446ac
21
src/main.rs
21
src/main.rs
|
@ -229,8 +229,27 @@ fn main() {
|
|||
// let mut state: Box<dyn WorldState> = Box::new(Planets::new(&mut ren));
|
||||
let mut state: Box<dyn WorldState> = Box::new(Grid::new(&mut ren));
|
||||
|
||||
let lights = vec![
|
||||
PointLight {
|
||||
center: glam::Vec3A::new(0.0, 5.0, 0.0),
|
||||
intensity: glam::Vec3A::new(100.0, 100.0, 100.0),
|
||||
},
|
||||
PointLight {
|
||||
center: glam::Vec3A::new(-7.0, 5.0, 7.0),
|
||||
intensity: glam::Vec3A::new(100.0, 0.0, 0.0),
|
||||
},
|
||||
PointLight {
|
||||
center: glam::Vec3A::new(7.0, 5.0, 7.0),
|
||||
intensity: glam::Vec3A::new(0.0, 100.0, 0.0),
|
||||
},
|
||||
PointLight {
|
||||
center: glam::Vec3A::new(0.0, 5.0, -7.0),
|
||||
intensity: glam::Vec3A::new(0.0, 0.0, 100.0),
|
||||
},
|
||||
];
|
||||
|
||||
event_loop.run(move |event, _, control_flow| match event {
|
||||
Event::RedrawRequested(_) => match ren.render(&camera, &state.render()) {
|
||||
Event::RedrawRequested(_) => match ren.render(&camera, &state.render(), &lights) {
|
||||
Ok(_) => {}
|
||||
Err(wgpu::SurfaceError::Lost) => ren.resize(ren.size),
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use super::camera::Camera;
|
||||
use super::commands::{CommandSet, Command};
|
||||
use super::commands::{Command, CommandSet};
|
||||
use super::mesh::Vertex;
|
||||
use super::pool::{MeshGroup, MeshPool, TexturePool};
|
||||
use super::scene::MeshInstance;
|
||||
use super::scene::{MeshInstance, PointLight};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
pub struct Renderer {
|
||||
|
@ -17,6 +17,7 @@ pub struct Renderer {
|
|||
depth_texture_view: wgpu::TextureView,
|
||||
camera_uniform: CameraUniform,
|
||||
camera_buffer: wgpu::Buffer,
|
||||
point_lights_buffer: wgpu::Buffer,
|
||||
camera_bind_group: wgpu::BindGroup,
|
||||
meshes_buffer: wgpu::Buffer,
|
||||
meshes_bind_group: wgpu::BindGroup,
|
||||
|
@ -44,27 +45,52 @@ impl Renderer {
|
|||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let point_lights_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Point Lights Buffer"),
|
||||
size: 65536, // TODO buffer resizing
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let camera_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
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,
|
||||
},
|
||||
],
|
||||
label: Some("Camera Bind Group Layout"),
|
||||
});
|
||||
|
||||
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &camera_bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: camera_buffer.as_entire_binding(),
|
||||
}],
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: camera_buffer.as_entire_binding(),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: point_lights_buffer.as_entire_binding(),
|
||||
},
|
||||
],
|
||||
label: Some("Camera Bind Group"),
|
||||
});
|
||||
|
||||
|
@ -165,6 +191,7 @@ impl Renderer {
|
|||
depth_texture_view,
|
||||
camera_uniform,
|
||||
camera_buffer,
|
||||
point_lights_buffer,
|
||||
camera_bind_group,
|
||||
meshes_buffer,
|
||||
meshes_bind_group,
|
||||
|
@ -217,6 +244,7 @@ impl Renderer {
|
|||
&mut self,
|
||||
camera: &impl Camera,
|
||||
meshes: &Vec<MeshInstance>,
|
||||
point_lights: &Vec<PointLight>,
|
||||
) -> Result<(), wgpu::SurfaceError> {
|
||||
self.camera_uniform.update(camera);
|
||||
self.queue.write_buffer(
|
||||
|
@ -231,6 +259,21 @@ impl Renderer {
|
|||
self.queue
|
||||
.write_buffer(&self.meshes_buffer, 0, mesh_commands.get_storage());
|
||||
|
||||
let point_lights: Vec<PointLightUniform> = point_lights.iter().map(|p| p.into()).collect();
|
||||
|
||||
// TODO make a function to ease arranging header + array data (this is really ugly)
|
||||
// researching proper structure alignment will be necessary
|
||||
self.queue.write_buffer(
|
||||
&self.point_lights_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[point_lights.len() as u32]),
|
||||
);
|
||||
self.queue.write_buffer(
|
||||
&self.point_lights_buffer,
|
||||
16,
|
||||
bytemuck::cast_slice(&point_lights),
|
||||
);
|
||||
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output
|
||||
.texture
|
||||
|
@ -320,3 +363,19 @@ impl CameraUniform {
|
|||
self.vp = camera.get_vp();
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct PointLightUniform {
|
||||
center: [f32; 4],
|
||||
intensity: [f32; 4],
|
||||
}
|
||||
|
||||
impl From<&PointLight> for PointLightUniform {
|
||||
fn from(p: &PointLight) -> Self {
|
||||
Self {
|
||||
center: p.center.extend(0.0).to_array(),
|
||||
intensity: p.intensity.extend(0.0).to_array(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,3 +6,9 @@ pub struct MeshInstance {
|
|||
pub albedo: TextureHandle,
|
||||
pub transform: glam::Mat4,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct PointLight {
|
||||
pub center: glam::Vec3A,
|
||||
pub intensity: glam::Vec3A,
|
||||
}
|
||||
|
|
|
@ -10,6 +10,16 @@ struct MeshData {
|
|||
instances: array<MeshInstance>;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
center: vec4<f32>;
|
||||
intensity: vec4<f32>;
|
||||
};
|
||||
|
||||
struct PointLightData {
|
||||
num: i32;
|
||||
lights: array<PointLight>;
|
||||
};
|
||||
|
||||
struct VertexInput {
|
||||
[[location(0)]] position: vec3<f32>;
|
||||
[[location(1)]] tex_coords: vec2<f32>;
|
||||
|
@ -17,12 +27,16 @@ struct VertexInput {
|
|||
|
||||
struct VertexOutput {
|
||||
[[builtin(position)]] clip_position: vec4<f32>;
|
||||
[[location(0)]] tex_coords: vec2<f32>;
|
||||
[[location(0)]] position: vec3<f32>;
|
||||
[[location(1)]] tex_coords: vec2<f32>;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]]
|
||||
var<uniform> camera: CameraUniform;
|
||||
|
||||
[[group(0), binding(1)]]
|
||||
var<storage,read> point_lights: PointLightData;
|
||||
|
||||
[[group(1), binding(0)]]
|
||||
var<storage,read> meshes: MeshData;
|
||||
|
||||
|
@ -35,8 +49,11 @@ fn vs_main(
|
|||
vertex: VertexInput,
|
||||
) -> VertexOutput {
|
||||
let transform = meshes.instances[mesh_idx].transform;
|
||||
let world_pos = transform * vec4<f32>(vertex.position, 1.0);
|
||||
|
||||
var out: VertexOutput;
|
||||
out.clip_position = camera.vp * transform * vec4<f32>(vertex.position, 1.0);
|
||||
out.clip_position = camera.vp * world_pos;
|
||||
out.position = world_pos.xyz;
|
||||
out.tex_coords = vertex.tex_coords;
|
||||
return out;
|
||||
}
|
||||
|
@ -45,5 +62,15 @@ fn vs_main(
|
|||
fn fs_main(
|
||||
frag: VertexOutput,
|
||||
) -> [[location(0)]] vec4<f32> {
|
||||
return textureSample(t_albedo, s_albedo, frag.tex_coords);
|
||||
let albedo = textureSample(t_albedo, s_albedo, frag.tex_coords).rgb;
|
||||
|
||||
var lum = vec3<f32>(0.0);
|
||||
for(var i = 0; i < 4; i = i + 1) {
|
||||
let light = point_lights.lights[i];
|
||||
let light_relative = frag.position - light.center.xyz;
|
||||
let diffuse = albedo / dot(light_relative, light_relative);
|
||||
lum = lum + (diffuse * light.intensity.rgb);
|
||||
}
|
||||
|
||||
return vec4<f32>(lum, 1.0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue