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(Planets::new(&mut ren));
|
||||||
let mut state: Box<dyn WorldState> = Box::new(Grid::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_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(_) => {}
|
Ok(_) => {}
|
||||||
Err(wgpu::SurfaceError::Lost) => ren.resize(ren.size),
|
Err(wgpu::SurfaceError::Lost) => ren.resize(ren.size),
|
||||||
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
|
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::camera::Camera;
|
use super::camera::Camera;
|
||||||
use super::commands::{CommandSet, Command};
|
use super::commands::{Command, CommandSet};
|
||||||
use super::mesh::Vertex;
|
use super::mesh::Vertex;
|
||||||
use super::pool::{MeshGroup, MeshPool, TexturePool};
|
use super::pool::{MeshGroup, MeshPool, TexturePool};
|
||||||
use super::scene::MeshInstance;
|
use super::scene::{MeshInstance, PointLight};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
|
@ -17,6 +17,7 @@ pub struct Renderer {
|
||||||
depth_texture_view: wgpu::TextureView,
|
depth_texture_view: wgpu::TextureView,
|
||||||
camera_uniform: CameraUniform,
|
camera_uniform: CameraUniform,
|
||||||
camera_buffer: wgpu::Buffer,
|
camera_buffer: wgpu::Buffer,
|
||||||
|
point_lights_buffer: wgpu::Buffer,
|
||||||
camera_bind_group: wgpu::BindGroup,
|
camera_bind_group: wgpu::BindGroup,
|
||||||
meshes_buffer: wgpu::Buffer,
|
meshes_buffer: wgpu::Buffer,
|
||||||
meshes_bind_group: wgpu::BindGroup,
|
meshes_bind_group: wgpu::BindGroup,
|
||||||
|
@ -44,27 +45,52 @@ impl Renderer {
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
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 =
|
let camera_bind_group_layout =
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
entries: &[
|
||||||
binding: 0,
|
wgpu::BindGroupLayoutEntry {
|
||||||
visibility: wgpu::ShaderStages::VERTEX,
|
binding: 0,
|
||||||
ty: wgpu::BindingType::Buffer {
|
visibility: wgpu::ShaderStages::VERTEX,
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
ty: wgpu::BindingType::Buffer {
|
||||||
has_dynamic_offset: false,
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
min_binding_size: None,
|
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"),
|
label: Some("Camera Bind Group Layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
layout: &camera_bind_group_layout,
|
layout: &camera_bind_group_layout,
|
||||||
entries: &[wgpu::BindGroupEntry {
|
entries: &[
|
||||||
binding: 0,
|
wgpu::BindGroupEntry {
|
||||||
resource: camera_buffer.as_entire_binding(),
|
binding: 0,
|
||||||
}],
|
resource: camera_buffer.as_entire_binding(),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: point_lights_buffer.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
label: Some("Camera Bind Group"),
|
label: Some("Camera Bind Group"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -165,6 +191,7 @@ impl Renderer {
|
||||||
depth_texture_view,
|
depth_texture_view,
|
||||||
camera_uniform,
|
camera_uniform,
|
||||||
camera_buffer,
|
camera_buffer,
|
||||||
|
point_lights_buffer,
|
||||||
camera_bind_group,
|
camera_bind_group,
|
||||||
meshes_buffer,
|
meshes_buffer,
|
||||||
meshes_bind_group,
|
meshes_bind_group,
|
||||||
|
@ -217,6 +244,7 @@ impl Renderer {
|
||||||
&mut self,
|
&mut self,
|
||||||
camera: &impl Camera,
|
camera: &impl Camera,
|
||||||
meshes: &Vec<MeshInstance>,
|
meshes: &Vec<MeshInstance>,
|
||||||
|
point_lights: &Vec<PointLight>,
|
||||||
) -> Result<(), wgpu::SurfaceError> {
|
) -> Result<(), wgpu::SurfaceError> {
|
||||||
self.camera_uniform.update(camera);
|
self.camera_uniform.update(camera);
|
||||||
self.queue.write_buffer(
|
self.queue.write_buffer(
|
||||||
|
@ -231,6 +259,21 @@ impl Renderer {
|
||||||
self.queue
|
self.queue
|
||||||
.write_buffer(&self.meshes_buffer, 0, mesh_commands.get_storage());
|
.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 output = self.surface.get_current_texture()?;
|
||||||
let view = output
|
let view = output
|
||||||
.texture
|
.texture
|
||||||
|
@ -320,3 +363,19 @@ impl CameraUniform {
|
||||||
self.vp = camera.get_vp();
|
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 albedo: TextureHandle,
|
||||||
pub transform: glam::Mat4,
|
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>;
|
instances: array<MeshInstance>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PointLight {
|
||||||
|
center: vec4<f32>;
|
||||||
|
intensity: vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointLightData {
|
||||||
|
num: i32;
|
||||||
|
lights: array<PointLight>;
|
||||||
|
};
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
[[location(0)]] position: vec3<f32>;
|
[[location(0)]] position: vec3<f32>;
|
||||||
[[location(1)]] tex_coords: vec2<f32>;
|
[[location(1)]] tex_coords: vec2<f32>;
|
||||||
|
@ -17,12 +27,16 @@ struct VertexInput {
|
||||||
|
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
[[builtin(position)]] clip_position: vec4<f32>;
|
[[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)]]
|
[[group(0), binding(0)]]
|
||||||
var<uniform> camera: CameraUniform;
|
var<uniform> camera: CameraUniform;
|
||||||
|
|
||||||
|
[[group(0), binding(1)]]
|
||||||
|
var<storage,read> point_lights: PointLightData;
|
||||||
|
|
||||||
[[group(1), binding(0)]]
|
[[group(1), binding(0)]]
|
||||||
var<storage,read> meshes: MeshData;
|
var<storage,read> meshes: MeshData;
|
||||||
|
|
||||||
|
@ -35,8 +49,11 @@ fn vs_main(
|
||||||
vertex: VertexInput,
|
vertex: VertexInput,
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
let transform = meshes.instances[mesh_idx].transform;
|
let transform = meshes.instances[mesh_idx].transform;
|
||||||
|
let world_pos = transform * vec4<f32>(vertex.position, 1.0);
|
||||||
|
|
||||||
var out: VertexOutput;
|
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;
|
out.tex_coords = vertex.tex_coords;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -45,5 +62,15 @@ fn vs_main(
|
||||||
fn fs_main(
|
fn fs_main(
|
||||||
frag: VertexOutput,
|
frag: VertexOutput,
|
||||||
) -> [[location(0)]] vec4<f32> {
|
) -> [[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