summaryrefslogtreecommitdiff
path: root/client/src
diff options
context:
space:
mode:
Diffstat (limited to 'client/src')
-rw-r--r--client/src/armature.rs34
-rw-r--r--client/src/main.rs12
-rw-r--r--client/src/renderer.rs6
-rw-r--r--client/src/scene_prepare.rs44
-rw-r--r--client/src/scene_render.rs87
-rw-r--r--client/src/shaders/fragment_pbr.wgsl1
-rw-r--r--client/src/shaders/fragment_ui.wgsl1
-rw-r--r--client/src/shaders/vertex_world_skin.wgsl1
8 files changed, 126 insertions, 60 deletions
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<Buffer>,
+ joint_mat: Vec<Mat4>,
+ 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::<f32>() * 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 <https://www.gnu.org/licenses/>.
*/
-#![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 <https://www.gnu.org/licenses/>.
*/
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<K: Hash + Eq + Clone, V: Clone> DemandMap<K, V> {
pub struct ScenePreparer {
device: Arc<Device>,
queue: Arc<Queue>,
- texture_bgl: BindGroupLayout,
- material_bgl: BindGroupLayout,
+ layouts: SceneBgLayouts,
textures: DemandMap<(Resource<Image<'static>>, bool), (Arc<Texture>, Arc<BindGroup>)>,
placeholder_textures: DemandMap<TextureIdentityKind, (Arc<Texture>, Arc<BindGroup>)>,
@@ -110,12 +111,14 @@ pub struct RMeshPart {
pub va_normal: Arc<Buffer>,
pub va_tangent: Arc<Buffer>,
pub va_texcoord: Arc<Buffer>,
- pub va_joint_index: Option<Arc<Buffer>>,
- pub va_joint_weight: Option<Arc<Buffer>>,
pub tex_albedo: Arc<BindGroup>,
pub tex_normal: Arc<BindGroup>,
pub material: Arc<BindGroup>,
pub double_sided: bool,
+
+ pub va_joint_index: Option<Arc<Buffer>>,
+ pub va_joint_weight: Option<Arc<Buffer>>,
+ pub joint_uniform: Option<Arc<Buffer>>,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -154,17 +157,11 @@ struct Material {
}
impl ScenePreparer {
- pub fn new(
- device: Arc<Device>,
- queue: Arc<Queue>,
- texture_bgl: BindGroupLayout,
- material_bgl: BindGroupLayout,
- ) -> Self {
+ pub fn new(device: Arc<Device>, queue: Arc<Queue>, 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::<f32>() 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<f32> {
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 <https://www.gnu.org/licenses/>.
-
struct VertexOut {
@builtin(position) clip: vec4<f32>,
@location(0) uv: vec2<f32>,
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<f32>,
}
+var<uniform> joints: array<mat4x4<f32>>;
var<push_constant> pc: PushConst;
@vertex