From a3621790a6f4466daab0f38f5eaf57fe064b2e92 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 21 Jan 2025 22:59:01 +0100 Subject: more work on armature --- client/src/armature.rs | 34 ++++++++++++ client/src/main.rs | 12 ++--- client/src/renderer.rs | 6 +-- client/src/scene_prepare.rs | 44 ++++++++++------ client/src/scene_render.rs | 87 +++++++++++++++++++------------ client/src/shaders/fragment_pbr.wgsl | 1 + client/src/shaders/fragment_ui.wgsl | 1 - client/src/shaders/vertex_world_skin.wgsl | 1 + 8 files changed, 126 insertions(+), 60 deletions(-) create mode 100644 client/src/armature.rs (limited to 'client') diff --git a/client/src/armature.rs b/client/src/armature.rs new file mode 100644 index 0000000..d955415 --- /dev/null +++ b/client/src/armature.rs @@ -0,0 +1,34 @@ +use std::sync::Arc; + +use glam::Mat4; +use weareshared::resources::Armature; +use wgpu::{Buffer, BufferDescriptor, BufferUsages, Device, Queue}; + +pub struct RArmature { + pub joint_mat_uniform_buffer: Arc, + joint_mat: Vec, + data: Armature, +} + +impl RArmature { + pub fn new(device: &Device, armature: Armature) -> Self { + Self { + joint_mat_uniform_buffer: Arc::new(device.create_buffer(&BufferDescriptor { + label: Some("joint uniform"), + size: (armature.parent.as_ref().unwrap().len() * size_of::() * 16) as u64, + usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM, + mapped_at_creation: false, + })), + data: armature, + joint_mat: vec![], + } + } + pub fn update(&mut self) {} + pub fn write_uniform(&self, queue: &Queue) { + queue.write_buffer( + &self.joint_mat_uniform_buffer, + 0, + bytemuck::cast_slice(self.joint_mat.as_slice()), + ); + } +} diff --git a/client/src/main.rs b/client/src/main.rs index cd77266..66bd21f 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -14,12 +14,13 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -#![feature(iter_array_chunks)] -#![feature(mpmc_channel)] -#![feature(array_chunks)] -#![feature(new_zeroed_alloc)] +#![feature(iter_array_chunks, mpmc_channel, array_chunks, new_zeroed_alloc)] +pub mod armature; +pub mod audio; pub mod camera; pub mod download; +pub mod interfaces; +pub mod meshops; pub mod network; pub mod renderer; pub mod scene_prepare; @@ -27,9 +28,6 @@ pub mod scene_render; pub mod state; pub mod ui; pub mod window; -pub mod audio; -pub mod interfaces; -pub mod meshops; use anyhow::Result; use clap::Parser; diff --git a/client/src/renderer.rs b/client/src/renderer.rs index 02859a1..e655420 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -92,13 +92,11 @@ impl<'a> Renderer<'a> { let device = Arc::new(device); let queue = Arc::new(queue); - let (scene_pipeline, texture_bgl, material_bgl) = - ScenePipeline::new(&device, surface_configuration.format); + let (scene_pipeline, layouts) = ScenePipeline::new(&device, surface_configuration.format); let scene_prepare = Arc::new(ScenePreparer::new( device.clone(), queue.clone(), - texture_bgl, - material_bgl, + layouts )); let ui_renderer = diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 05e9533..4e57e77 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -15,8 +15,10 @@ along with this program. If not, see . */ use crate::{ + armature::{self, RArmature}, download::Downloader, meshops::{generate_normals, generate_tangents, generate_texcoords}, + scene_render::SceneBgLayouts, }; use anyhow::Result; use bytemuck::{Pod, Zeroable}; @@ -36,7 +38,7 @@ use std::{ use weareshared::{ Affine3A, packets::Resource, - resources::{Image, MeshPart, Prefab}, + resources::{Armature, Image, MeshPart, Prefab}, }; use wgpu::{ AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindingResource, @@ -87,8 +89,7 @@ impl DemandMap { pub struct ScenePreparer { device: Arc, queue: Arc, - texture_bgl: BindGroupLayout, - material_bgl: BindGroupLayout, + layouts: SceneBgLayouts, textures: DemandMap<(Resource>, bool), (Arc, Arc)>, placeholder_textures: DemandMap, Arc)>, @@ -110,12 +111,14 @@ pub struct RMeshPart { pub va_normal: Arc, pub va_tangent: Arc, pub va_texcoord: Arc, - pub va_joint_index: Option>, - pub va_joint_weight: Option>, pub tex_albedo: Arc, pub tex_normal: Arc, pub material: Arc, pub double_sided: bool, + + pub va_joint_index: Option>, + pub va_joint_weight: Option>, + pub joint_uniform: Option>, } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -154,17 +157,11 @@ struct Material { } impl ScenePreparer { - pub fn new( - device: Arc, - queue: Arc, - texture_bgl: BindGroupLayout, - material_bgl: BindGroupLayout, - ) -> Self { + pub fn new(device: Arc, queue: Arc, layouts: SceneBgLayouts) -> Self { Self { device, queue, - texture_bgl, - material_bgl, + layouts, index_buffers: DemandMap::new(), vertex_buffers: DemandMap::new(), mesh_parts: DemandMap::new(), @@ -247,7 +244,7 @@ impl ScenePreparer { let tex_bg = create_texture( &self.device, &self.queue, - &self.texture_bgl, + &self.layouts.texture, &image, dims.0, dims.1, @@ -272,7 +269,7 @@ impl ScenePreparer { let tex_bg = create_texture( &self.device, &self.queue, - &self.texture_bgl, + &self.layouts.texture, &color, 1, 1, @@ -458,6 +455,12 @@ impl ScenePreparer { } }); + let armature = if let Some(res) = part.armature.clone() { + Some(dls.try_get(res)?) + } else { + Some(None) + }; + if let ( Some((index, index_count)), Some(va_normal), @@ -466,6 +469,7 @@ impl ScenePreparer { Some(va_position), Some(va_joint_index), Some(va_joint_weight), + Some(armature), Some(tex_normal), Some(tex_albedo), Some(material), @@ -477,11 +481,20 @@ impl ScenePreparer { position, joint_index, joint_weight, + armature, tex_normal, tex_albedo, material, ) { let double_sided = part.g_double_sided.is_some(); + + let joint_uniform = if let Some(a) = armature { + let ra = RArmature::new(&self.device, a); + Some(ra.joint_mat_uniform_buffer.clone()) + } else { + None + }; + debug!("part created (took {:?}) {pres}", start.elapsed()); self.mesh_parts.insert( pres, @@ -498,6 +511,7 @@ impl ScenePreparer { tex_normal, material, double_sided, + joint_uniform, }), 0, ); diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index 3698ff7..77217d6 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -36,50 +36,72 @@ pub struct ScenePipeline { pipeline_no_cull: RenderPipeline, } +pub struct SceneBgLayouts { + pub texture: BindGroupLayout, + pub material: BindGroupLayout, + pub joints: BindGroupLayout, +} + impl ScenePipeline { - pub fn new(device: &Device, format: TextureFormat) -> (Self, BindGroupLayout, BindGroupLayout) { + pub fn new(device: &Device, format: TextureFormat) -> (Self, SceneBgLayouts) { let fragment_pbr = device.create_shader_module(include_wgsl!("shaders/fragment_pbr.wgsl")); let vertex_world = device.create_shader_module(include_wgsl!("shaders/vertex_world.wgsl")); let _vertex_world_skin = device.create_shader_module(include_wgsl!("shaders/vertex_world_skin.wgsl")); - let texture_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[ - BindGroupLayoutEntry { + let layouts = SceneBgLayouts { + texture: device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[ + BindGroupLayoutEntry { + binding: 0, + count: None, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Texture { + sample_type: TextureSampleType::Float { filterable: true }, + view_dimension: TextureViewDimension::D2, + multisampled: false, + }, + }, + BindGroupLayoutEntry { + binding: 1, + count: None, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Sampler(SamplerBindingType::Filtering), + }, + ], + label: None, + }), + material: device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[BindGroupLayoutEntry { binding: 0, count: None, visibility: ShaderStages::FRAGMENT, - ty: BindingType::Texture { - sample_type: TextureSampleType::Float { filterable: true }, - view_dimension: TextureViewDimension::D2, - multisampled: false, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, }, - }, - BindGroupLayoutEntry { - binding: 1, + }], + label: None, + }), + joints: device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[BindGroupLayoutEntry { + binding: 0, count: None, - visibility: ShaderStages::FRAGMENT, - ty: BindingType::Sampler(SamplerBindingType::Filtering), - }, - ], - label: None, - }); - let material_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[BindGroupLayoutEntry { - binding: 0, - count: None, - visibility: ShaderStages::FRAGMENT, - ty: BindingType::Buffer { - ty: BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - }], - label: None, - }); + visibility: ShaderStages::VERTEX, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + }], + label: None, + }), + }; + let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { label: None, - bind_group_layouts: &[&texture_bgl, &texture_bgl, &material_bgl], + bind_group_layouts: &[&layouts.texture, &layouts.texture, &layouts.material], push_constant_ranges: &[PushConstantRange { range: 0..((4 * 4 + 3 * 4) * size_of::() as u32), stages: ShaderStages::VERTEX, @@ -170,8 +192,7 @@ impl ScenePipeline { pipeline, pipeline_no_cull, }, - texture_bgl, - material_bgl, + layouts, ) } diff --git a/client/src/shaders/fragment_pbr.wgsl b/client/src/shaders/fragment_pbr.wgsl index ac2638d..d1d2b1d 100644 --- a/client/src/shaders/fragment_pbr.wgsl +++ b/client/src/shaders/fragment_pbr.wgsl @@ -48,6 +48,7 @@ fn main(vo: VertexOut) -> @location(0) vec4 { let color = t_albedo.rgb * lighting; + // TODO better (and faster?) randomneess for alpha dither if fract(dot(sin(vo.clip * 123.) * 1213., vec4(3., 2., 1., 4.))) > alpha { discard; } diff --git a/client/src/shaders/fragment_ui.wgsl b/client/src/shaders/fragment_ui.wgsl index 6638628..7cb66ab 100644 --- a/client/src/shaders/fragment_ui.wgsl +++ b/client/src/shaders/fragment_ui.wgsl @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . - struct VertexOut { @builtin(position) clip: vec4, @location(0) uv: vec2, diff --git a/client/src/shaders/vertex_world_skin.wgsl b/client/src/shaders/vertex_world_skin.wgsl index 85dda64..86250f1 100644 --- a/client/src/shaders/vertex_world_skin.wgsl +++ b/client/src/shaders/vertex_world_skin.wgsl @@ -33,6 +33,7 @@ struct PushConst { model_basis: mat3x3, } +var joints: array>; var pc: PushConst; @vertex -- cgit v1.2.3-70-g09d2