From 9d8faeb6fb3264b85dc50d72654fce3caed7c47c Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 6 Sep 2023 17:01:42 -0700 Subject: [PATCH] render a a 3d projection onto a flat surface embedded in world space with screen space pixels --- src/main.rs | 45 +++++++++++++++++++++++++++++++++++++++------ src/shader.wgsl | 19 +++++++++++++++---- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 720fa6e4..45d26ed9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,12 +20,16 @@ struct Entity { //temp? struct ModelData { transform: glam::Mat4, + transform_depth: glam::Mat4, + use_depth: glam::Vec4, vertex_buf: wgpu::Buffer, entities: Vec, } struct Model { transform: glam::Mat4, + transform_depth: glam::Mat4, + use_depth: glam::Vec4, vertex_buf: wgpu::Buffer, entities: Vec, bind_group: wgpu::BindGroup, @@ -131,6 +135,7 @@ pub struct Skybox { models: Vec, depth_view: wgpu::TextureView, staging_belt: wgpu::util::StagingBelt, + start_time: Instant, } impl Skybox { @@ -159,9 +164,18 @@ 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_model_uniform_data(model:&Model) -> [f32; 4*4*2+4] { + let mut raw = [0f32; 4*4*2+4]; + raw[0..16].copy_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&model.transform)[..]); + raw[16..32].copy_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&model.transform_depth)[..]); + raw[32..36].copy_from_slice(AsRef::<[f32; 4]>::as_ref(&model.use_depth)); + raw +} +fn get_modeldata_uniform_data(model:&ModelData) -> [f32; 4*4*2+4] { + let mut raw = [0f32; 4*4*2+4]; + raw[0..16].copy_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&model.transform)[..]); + raw[16..32].copy_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&model.transform_depth)[..]); + raw[32..36].copy_from_slice(AsRef::<[f32; 4]>::as_ref(&model.use_depth)); raw } @@ -209,6 +223,8 @@ fn add_obj(device:&wgpu::Device,modeldatas:& mut Vec,source:&[u8]){ }); modeldatas.push(ModelData { transform: glam::Mat4::default(), + transform_depth: glam::Mat4::default(), + use_depth: glam::Vec4::ZERO, vertex_buf, entities, }) @@ -234,7 +250,15 @@ impl strafe_client::framework::Example for Skybox { add_obj(device,& mut modeldatas,include_bytes!("../models/teapot.obj")); 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.)); + + let proj = glam::Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0); + let view = glam::Mat4::from_translation(glam::vec3(0.,0.,10.)); + let view_inv = view.inverse(); + let model = glam::Mat4::from_translation(glam::vec3(-10.,5.,10.)); + + modeldatas[2].transform=model; + modeldatas[2].transform_depth=proj * view_inv; + modeldatas[2].use_depth=glam::Vec4::Z; let main_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -510,7 +534,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_modeldata_uniform_data(&modeldata); let model_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some(format!("Model{}",i).as_str()), contents: bytemuck::cast_slice(&model_uniforms), @@ -529,6 +553,8 @@ impl strafe_client::framework::Example for Skybox { //all of these are being moved here models.push(Model{ transform: modeldata.transform, + transform_depth: modeldata.transform_depth, + use_depth: modeldata.use_depth, vertex_buf:modeldata.vertex_buf, entities: modeldata.entities, bind_group: model_bind_group, @@ -548,6 +574,7 @@ impl strafe_client::framework::Example for Skybox { models, depth_view, staging_belt: wgpu::util::StagingBelt::new(0x100), + start_time: Instant::now(), } } @@ -658,6 +685,12 @@ impl strafe_client::framework::Example for Skybox { } } + let proj = glam::Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0); + let view_inv = glam::Mat4::from_translation(glam::vec3(0.,0.,10.)).inverse(); + let model = glam::Mat4::from_euler(glam::EulerRot::YXZ, self.start_time.elapsed().as_secs_f32(),0f32,0f32); + + self.models[2].transform_depth=proj * view_inv * model; + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); @@ -674,7 +707,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_model_uniform_data(&model); self.staging_belt .write_buffer( &mut encoder, diff --git a/src/shader.wgsl b/src/shader.wgsl index a60fc5c8..2b3852a7 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -68,9 +68,15 @@ struct EntityOutput { @location(3) view: vec3, }; +struct TransformData { + transform: mat4x4, + depth: mat4x4, + use_depth: vec4, +}; + @group(1) @binding(0) -var r_EntityTransform: mat4x4; +var transform: TransformData; @vertex fn vs_entity( @@ -78,12 +84,17 @@ fn vs_entity( @location(1) texture: vec2, @location(2) normal: vec3, ) -> EntityOutput { - var position: vec4 = r_EntityTransform * vec4(pos, 1.0); + var position_depth: vec4 = transform.depth * vec4(pos, 1.0); + var position_depth_0: vec4 = position_depth; + position_depth_0.z=0.0; + var position: vec4 = transform.transform * mix(position_depth,position_depth_0,transform.use_depth); + var result: EntityOutput; - result.normal = (r_EntityTransform * vec4(normal, 0.0)).xyz; + result.normal = (transform.transform * mix(vec4(normal,0.0),vec4(0.0,0.0,1.0,0.0),transform.use_depth.z)).xyz; result.texture=texture; result.view = position.xyz - r_data.cam_pos.xyz; - result.position = r_data.proj * r_data.view * position; + var screen_position: vec4 = r_data.proj * r_data.view * position; + result.position = mix(screen_position,position_depth,transform.use_depth); return result; }