From 7e427b3879da4c69187082bf069e7d74cd2e7155 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 20 Sep 2023 13:03:25 -0700 Subject: [PATCH] instanced rendering --- src/main.rs | 36 ++++++++++++++++++++++-------------- src/shader.wgsl | 9 +++++---- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index a3349dd..e78103f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,13 +19,13 @@ struct Entity { //temp? struct ModelData { - transform: glam::Mat4, + transforms: Vec, vertex_buf: wgpu::Buffer, entities: Vec, } struct ModelGraphics { - transform: glam::Mat4, + transforms: Vec, vertex_buf: wgpu::Buffer, entities: Vec, bind_group: wgpu::BindGroup, @@ -152,9 +152,13 @@ impl Skybox { } } -fn get_transform_uniform_data(transform:&glam::Mat4) -> [f32; 4*4] { - let mut raw = [0f32; 4*4]; - raw[0..16].copy_from_slice(&AsRef::<[f32; 4*4]>::as_ref(transform)[..]); +fn get_transform_uniform_data(transforms:&Vec) -> Vec { + let mut raw = Vec::with_capacity(4*4*transforms.len()); + for (i,t) in transforms.iter().enumerate(){ + let mut v = raw.split_off(4*4*i); + raw.extend_from_slice(&AsRef::<[f32; 4*4]>::as_ref(t)[..]); + raw.append(&mut v); + } raw } @@ -200,7 +204,7 @@ fn add_obj(device:&wgpu::Device,modeldatas:& mut Vec,data:obj::ObjDat usage: wgpu::BufferUsages::VERTEX, }); modeldatas.push(ModelData { - transform: glam::Mat4::default(), + transforms: vec![glam::Mat4::default()], vertex_buf, entities, }) @@ -246,9 +250,13 @@ impl strafe_client::framework::Example for Skybox { add_obj(device,& mut modeldatas,obj::ObjData::load_buf(&include_bytes!("../models/teapot.obj")[..]).unwrap()); add_obj(device,& mut modeldatas,ground); println!("models.len = {:?}", modeldatas.len()); - modeldatas[1].transform=glam::Mat4::from_translation(glam::vec3(10.,5.,10.)); - modeldatas[2].transform=glam::Mat4::from_translation(glam::vec3(-10.,5.,10.)); - modeldatas[3].transform=glam::Mat4::from_translation(glam::vec3(0.,-10.,0.))*glam::Mat4::from_scale(glam::vec3(160.0, 1.0, 160.0)); + modeldatas[0].transforms[0]=glam::Mat4::from_translation(glam::vec3(10.,0.,-10.)); + modeldatas[1].transforms[0]=glam::Mat4::from_translation(glam::vec3(10.,5.,10.)); + modeldatas[1].transforms.push(glam::Mat4::from_translation(glam::vec3(20.,5.,10.))); + modeldatas[1].transforms.push(glam::Mat4::from_translation(glam::vec3(10.,5.,20.))); + modeldatas[1].transforms.push(glam::Mat4::from_translation(glam::vec3(20.,5.,20.))); + modeldatas[2].transforms[0]=glam::Mat4::from_translation(glam::vec3(-10.,5.,10.)); + modeldatas[3].transforms[0]=glam::Mat4::from_translation(glam::vec3(0.,0.,0.))*glam::Mat4::from_scale(glam::vec3(160.0, 1.0, 160.0)); let main_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -326,7 +334,7 @@ impl strafe_client::framework::Example for Skybox { temp_control_dir: glam::Vec3::ZERO, walkspeed: 18.0, contacts: std::collections::HashSet::new(), - models_cringe_clone: modeldatas.iter().map(|m|strafe_client::body::Model::new(m.transform)).collect(), + models_cringe_clone: modeldatas.iter().map(|m|m.transforms.iter().map(|t|strafe_client::body::Model::new(*t))).flatten().collect(), walk: strafe_client::body::WalkState::new(), hitbox_halfsize: glam::vec3(1.0,2.5,1.0), }; @@ -341,7 +349,7 @@ impl strafe_client::framework::Example for Skybox { //drain the modeldata vec so entities can be /moved/ to models.entities let mut models = Vec::::with_capacity(modeldatas.len()); for (i,modeldata) in modeldatas.drain(..).enumerate() { - let model_uniforms = get_transform_uniform_data(&modeldata.transform); + let model_uniforms = get_transform_uniform_data(&modeldata.transforms); let model_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some(format!("ModelGraphics{}",i).as_str()), contents: bytemuck::cast_slice(&model_uniforms), @@ -359,7 +367,7 @@ impl strafe_client::framework::Example for Skybox { }); //all of these are being moved here models.push(ModelGraphics{ - transform: modeldata.transform, + transforms: modeldata.transforms, vertex_buf:modeldata.vertex_buf, entities: modeldata.entities, bind_group: model_bind_group, @@ -675,7 +683,7 @@ impl strafe_client::framework::Example for Skybox { .copy_from_slice(bytemuck::cast_slice(&camera_uniforms)); //This code only needs to run when the uniforms change for model in self.models.iter() { - let model_uniforms = get_transform_uniform_data(&model.transform); + let model_uniforms = get_transform_uniform_data(&model.transforms); self.staging_belt .write_buffer( &mut encoder, @@ -723,7 +731,7 @@ impl strafe_client::framework::Example for Skybox { for entity in model.entities.iter() { rpass.set_index_buffer(entity.index_buf.slice(..), wgpu::IndexFormat::Uint16); - rpass.draw_indexed(0..entity.index_count, 0, 0..1); + rpass.draw_indexed(0..entity.index_count, 0, 0..model.transforms.len() as u32); } } diff --git a/src/shader.wgsl b/src/shader.wgsl index e3fce46..bcfa5fc 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -45,20 +45,21 @@ struct EntityOutput { @location(2) normal: vec3, @location(3) view: vec3, }; - +const MAX_ENTITY_INSTANCES=1024; @group(1) @binding(0) -var r_EntityTransform: mat4x4; +var r_EntityTransform: array,MAX_ENTITY_INSTANCES>; @vertex fn vs_entity( + @builtin(instance_index) instance: u32, @location(0) pos: vec3, @location(1) texture: vec2, @location(2) normal: vec3, ) -> EntityOutput { - var position: vec4 = r_EntityTransform * vec4(pos, 1.0); + var position: vec4 = r_EntityTransform[instance] * vec4(pos, 1.0); var result: EntityOutput; - result.normal = (r_EntityTransform * vec4(normal, 0.0)).xyz; + result.normal = (r_EntityTransform[instance] * vec4(normal, 0.0)).xyz; result.texture=texture; result.view = position.xyz - r_data.cam_pos.xyz; result.position = r_data.proj * r_data.view * position;