You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
7.9 KiB
235 lines
7.9 KiB
use std::rc::Rc;
|
|
use bytemuck::__core::mem;
|
|
use crate::light::Light;
|
|
use crate::render::EntityUniforms;
|
|
|
|
/*
|
|
|
|
This will eventually be within an ECS...
|
|
|
|
So I will probably take the same approach that I did for tracer and have meta-data for rendering
|
|
held by the ECS, and a render system which will cycle through them and render
|
|
|
|
|
|
*/
|
|
struct Entity {
|
|
mx_world: cgmath::Matrix4<f32>,
|
|
rotation_speed: f32,
|
|
color: wgpu::Color,
|
|
vertex_buf: Rc<wgpu::Buffer>, // Could probably tie this along with index & count to some resource handle in the renderer
|
|
index_buf: Rc<wgpu::Buffer>,
|
|
index_count: usize,
|
|
bind_group: wgpu::BindGroup, // This is a little weird to have in the entity isn't it?
|
|
uniform_buf: wgpu::Buffer,
|
|
}
|
|
|
|
pub struct Runtime {
|
|
entities: Vec<Entity>,
|
|
// This is going to be ECS'd
|
|
lights: Vec<Light>, // ECS
|
|
}
|
|
|
|
impl Runtime {
|
|
pub fn init(
|
|
sc_desc: &wgpu::SwapChainDescriptor,
|
|
device: &wgpu::Device,
|
|
_queue: &wgpu::Queue, ) -> Self
|
|
{
|
|
|
|
// https://sotrh.github.io/learn-wgpu/beginner/tutorial5-textures/#the-bindgroup
|
|
// It appears like bindgroups are the shader input definitions
|
|
/*
|
|
But it is defined in multiples places...
|
|
|
|
` `
|
|
|
|
one of these in each pass
|
|
let bind_group_layout =
|
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
entries: &[
|
|
wgpu::BindGroupLayoutEntry {
|
|
|
|
|
|
|
|
The entities have one
|
|
|
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
layout: &local_bind_group_layout,
|
|
entries: &[wgpu::BindGroupEntry {
|
|
binding: 0,
|
|
resource: wgpu::BindingResource::Buffer(plane_uniform_buf.slice(..)),
|
|
}],
|
|
label: None,
|
|
});
|
|
*/
|
|
// Defines the Uniform buffer for the Vertex and Fragment shaders
|
|
let local_bind_group_layout =
|
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
entries: &[wgpu::BindGroupLayoutEntry {
|
|
binding: 0,
|
|
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
|
ty: wgpu::BindingType::UniformBuffer {
|
|
dynamic: false,
|
|
min_binding_size: wgpu::BufferSize::new(
|
|
mem::size_of::<EntityUniforms>() as _
|
|
),
|
|
},
|
|
count: None,
|
|
}],
|
|
label: None,
|
|
});
|
|
|
|
|
|
let mut entities = vec![{
|
|
use cgmath::SquareMatrix;
|
|
|
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
layout: &local_bind_group_layout,
|
|
entries: &[wgpu::BindGroupEntry {
|
|
binding: 0,
|
|
resource: wgpu::BindingResource::Buffer(plane_uniform_buf.slice(..)),
|
|
}],
|
|
label: None,
|
|
});
|
|
Entity {
|
|
mx_world: cgmath::Matrix4::identity(),
|
|
rotation_speed: 0.0,
|
|
color: wgpu::Color::WHITE,
|
|
vertex_buf: Rc::new(plane_vertex_buf),
|
|
index_buf: Rc::new(plane_index_buf),
|
|
index_count: plane_index_data.len(),
|
|
bind_group,
|
|
uniform_buf: plane_uniform_buf,
|
|
}
|
|
}];
|
|
|
|
struct CubeDesc {
|
|
offset: cgmath::Vector3<f32>,
|
|
angle: f32,
|
|
scale: f32,
|
|
rotation: f32,
|
|
}
|
|
|
|
let cube_descs = [
|
|
CubeDesc {
|
|
offset: cgmath::vec3(-2.0, -2.0, 2.0),
|
|
angle: 10.0,
|
|
scale: 0.7,
|
|
rotation: 1.5,
|
|
},
|
|
];
|
|
|
|
|
|
for cube in &cube_descs {
|
|
use cgmath::{Decomposed, Deg, InnerSpace, Quaternion, Rotation3};
|
|
|
|
let transform = Decomposed {
|
|
disp: cube.offset.clone(),
|
|
rot: Quaternion::from_axis_angle(cube.offset.normalize(), Deg(cube.angle)),
|
|
scale: cube.scale,
|
|
};
|
|
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: None,
|
|
size: entity_uniform_size,
|
|
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
|
mapped_at_creation: false,
|
|
});
|
|
entities.push(Entity {
|
|
mx_world: cgmath::Matrix4::from(transform),
|
|
rotation_speed: cube.rotation,
|
|
color: wgpu::Color::GREEN,
|
|
vertex_buf: Rc::clone(&cube_vertex_buf),
|
|
index_buf: Rc::clone(&cube_index_buf),
|
|
index_count: cube_index_data.len(),
|
|
bind_group: device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
layout: &local_bind_group_layout,
|
|
entries: &[wgpu::BindGroupEntry {
|
|
binding: 0,
|
|
resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)),
|
|
}],
|
|
label: None,
|
|
}),
|
|
uniform_buf,
|
|
});
|
|
}
|
|
|
|
// Create other resources
|
|
let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
|
label: Some("shadow"),
|
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
|
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
|
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
|
mag_filter: wgpu::FilterMode::Linear,
|
|
min_filter: wgpu::FilterMode::Linear,
|
|
mipmap_filter: wgpu::FilterMode::Nearest,
|
|
compare: Some(wgpu::CompareFunction::LessEqual),
|
|
..Default::default()
|
|
});
|
|
|
|
let shadow_texture = device.create_texture(&wgpu::TextureDescriptor {
|
|
size: Self::SHADOW_SIZE,
|
|
mip_level_count: 1,
|
|
sample_count: 1,
|
|
dimension: wgpu::TextureDimension::D2,
|
|
format: Self::SHADOW_FORMAT,
|
|
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
|
|
label: None,
|
|
});
|
|
let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
|
|
|
let mut shadow_target_views = (0..2)
|
|
.map(|i| {
|
|
Some(shadow_texture.create_view(&wgpu::TextureViewDescriptor {
|
|
label: Some("shadow"),
|
|
format: None,
|
|
dimension: Some(wgpu::TextureViewDimension::D2),
|
|
aspect: wgpu::TextureAspect::All,
|
|
base_mip_level: 0,
|
|
level_count: None,
|
|
base_array_layer: i as u32,
|
|
array_layer_count: NonZeroU32::new(1),
|
|
}))
|
|
})
|
|
.collect::<Vec<_>>();
|
|
|
|
// This is just metadata we hold for the lights. We can hold onto this
|
|
let lights = vec![
|
|
Light {
|
|
pos: cgmath::Point3::new(7.0, -5.0, 10.0),
|
|
color: wgpu::Color {
|
|
r: 0.5,
|
|
g: 1.0,
|
|
b: 0.5,
|
|
a: 1.0,
|
|
},
|
|
fov: 60.0,
|
|
depth: 1.0..20.0,
|
|
target_view: shadow_target_views[0].take().unwrap(),
|
|
},
|
|
Light {
|
|
pos: cgmath::Point3::new(-5.0, 7.0, 10.0),
|
|
color: wgpu::Color {
|
|
r: 1.0,
|
|
g: 0.5,
|
|
b: 0.5,
|
|
a: 1.0,
|
|
},
|
|
fov: 45.0,
|
|
depth: 1.0..20.0,
|
|
target_view: shadow_target_views[1].take().unwrap(),
|
|
},
|
|
];
|
|
|
|
Runtime {
|
|
entities,
|
|
lights,
|
|
lights_are_dirty: true,
|
|
|
|
light_uniform_buf,
|
|
}
|
|
}
|
|
|
|
pub fn update(&mut self, _event: winit::event::WindowEvent) {
|
|
//empty
|
|
}
|
|
} |