diff --git a/src/main.rs b/src/main.rs index 0e9bcde5..a855ed6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ struct Vertex { } struct Entity { + transform: glam::Affine3A, vertex_count: u32, vertex_buf: wgpu::Buffer, } @@ -34,6 +35,8 @@ struct Camera { walkspeed: f32, } +const MAGIC_ENTITIES: usize = 7; + const CONTROL_MOVEFORWARD:u32 = 0b00000001; const CONTROL_MOVEBACK:u32 = 0b00000010; const CONTROL_MOVERIGHT:u32 = 0b00000100; @@ -112,6 +115,7 @@ pub struct Skybox { ground_pipeline: wgpu::RenderPipeline, bind_group: wgpu::BindGroup, camera_buf: wgpu::Buffer, + entity_buf: wgpu::Buffer, entities: Vec, depth_view: wgpu::TextureView, staging_belt: wgpu::util::StagingBelt, @@ -143,6 +147,15 @@ impl Skybox { } } +fn get_entity_uniform_data(entities:& Vec) -> [f32; (9+3)*MAGIC_ENTITIES] { + let mut raw = [0f32; (9+3)*MAGIC_ENTITIES]; + for (i,entity) in entities.iter().enumerate() { + raw[i*12..(i+1)*12-3].copy_from_slice(&AsRef::<[f32; 9]>::as_ref(&glam::Mat3::from(entity.transform.matrix3))[..]); + raw[i*12+9..(i+1)*12].copy_from_slice(AsRef::<[f32; 3]>::as_ref(&glam::Vec3::from(entity.transform.translation))); + } + raw +} + fn add_obj(device:&wgpu::Device,entities:& mut Vec,source:&[u8]){ let data = obj::ObjData::load_buf(&source[..]).unwrap(); let mut vertices = Vec::new(); @@ -167,6 +180,7 @@ fn add_obj(device:&wgpu::Device,entities:& mut Vec,source:&[u8]){ usage: wgpu::BufferUsages::VERTEX, }); entities.push(Entity { + transform: glam::Affine3A::default(), vertex_count: vertices.len() as u32, vertex_buf, }); @@ -190,6 +204,8 @@ impl strafe_client::framework::Example for Skybox { let mut entities = Vec::::new(); add_obj(device,& mut entities,include_bytes!("../models/teslacyberv3.0.obj")); add_obj(device,& mut entities,include_bytes!("../models/suzanne.obj")); + println!("entities.len = {:?}", entities.len()); + entities[6].transform=glam::Affine3A::from_translation(glam::vec3(10.,5.,10.)); let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -220,6 +236,16 @@ impl strafe_client::framework::Example for Skybox { ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, ], }); @@ -252,6 +278,13 @@ impl strafe_client::framework::Example for Skybox { usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, }); + let entity_uniforms = get_entity_uniform_data(&entities); + let entity_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("EntityData"), + contents: bytemuck::cast_slice(&entity_uniforms), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], @@ -443,6 +476,10 @@ impl strafe_client::framework::Example for Skybox { binding: 2, resource: wgpu::BindingResource::Sampler(&sampler), }, + wgpu::BindGroupEntry { + binding: 3, + resource: entity_buf.as_entire_binding(), + }, ], label: None, }); @@ -456,6 +493,7 @@ impl strafe_client::framework::Example for Skybox { ground_pipeline, bind_group, camera_buf, + entity_buf, entities, depth_view, staging_belt: wgpu::util::StagingBelt::new(0x100), @@ -583,6 +621,16 @@ impl strafe_client::framework::Example for Skybox { device, ) .copy_from_slice(bytemuck::cast_slice(&camera_uniforms)); + let entity_uniforms = get_entity_uniform_data(&self.entities); + self.staging_belt + .write_buffer( + &mut encoder, + &self.entity_buf,//description of where data will be written when command is executed + 0,//offset in staging belt? + wgpu::BufferSize::new((entity_uniforms.len() * 4) as wgpu::BufferAddress).unwrap(), + device, + ) + .copy_from_slice(bytemuck::cast_slice(&entity_uniforms)); self.staging_belt.finish(); diff --git a/src/shader.wgsl b/src/shader.wgsl index 08e8ffe2..2ef5ce8e 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -67,15 +67,26 @@ struct EntityOutput { @location(3) view: vec3, }; + +struct EntityTransform { + matrix3: mat3x3, + translation: vec3, +}; +@group(0) +@binding(3) +var r_EntityTransforms: array; + @vertex fn vs_entity( + @builtin(instance_index) instance_index: u32, @location(0) pos: vec3, @location(1) normal: vec3, ) -> EntityOutput { + var position: vec3 = r_EntityTransforms[instance_index].matrix3 * pos+r_EntityTransforms[instance_index].translation; var result: EntityOutput; - result.normal = normal; - result.view = pos - r_data.cam_pos.xyz; - result.position = r_data.proj * r_data.view * vec4(pos, 1.0); + result.normal = r_EntityTransforms[instance_index].matrix3 * normal; + result.view = position - r_data.cam_pos.xyz; + result.position = r_data.proj * r_data.view * vec4(position, 1.0); return result; }