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, rotation_speed: f32, color: wgpu::Color, vertex_buf: Rc, // Could probably tie this along with index & count to some resource handle in the renderer index_buf: Rc, 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, // This is going to be ECS'd lights: Vec, // 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::() 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, 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::>(); // 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 } }