diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/Cargo.toml | 1 | ||||
-rw-r--r-- | client/src/main.rs | 3 | ||||
-rw-r--r-- | client/src/part.rs | 157 |
3 files changed, 160 insertions, 1 deletions
diff --git a/client/Cargo.toml b/client/Cargo.toml index b0ba84a..ffa40e4 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -13,3 +13,4 @@ log = "0.4.22" pollster = "0.4.0" wgpu = "23.0.1" winit = "0.30.8" +weareshared = { path = "../shared" } diff --git a/client/src/main.rs b/client/src/main.rs index 1aa05db..543db6d 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,5 +1,6 @@ -pub mod window; pub mod renderer; +pub mod window; +pub mod part; use anyhow::Result; use clap::Parser; diff --git a/client/src/part.rs b/client/src/part.rs new file mode 100644 index 0000000..15835d0 --- /dev/null +++ b/client/src/part.rs @@ -0,0 +1,157 @@ +use anyhow::Result; +use weareshared::{ + packets::Resource, + resources::{Indecies, Part, VertexAttributes}, +}; +use wgpu::{ + BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Buffer, BufferUsages, + ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, + LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, + PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment, + RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, StoreOp, TextureFormat, + TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, + include_wgsl, + util::{BufferInitDescriptor, DeviceExt}, +}; + +pub struct RenderPart { + vertex: Buffer, + index: Buffer, + pipeline: RenderPipeline, + bind_group: BindGroup, + n_vertex: u32, +} +pub struct PartData { + target: Part, + vertex: Vec<Option<VertexAttributes>>, + index: Option<Indecies>, +} + +impl PartData { + pub fn update(&mut self, hash: Resource, data: &[u8]) -> Result<bool> { + if Some(hash) == self.target.index { + self.index = Some(Indecies::deserialize(data)?) + } + for (thash, tdata) in self.target.vertex.iter().zip(self.vertex.iter_mut()) { + if hash == *thash { + *tdata = Some(VertexAttributes::deserialize(data)?) + } + } + Ok(self.vertex.iter().all(|v| v.is_some()) && self.index.is_some()) + } +} + +impl RenderPart { + pub fn new(device: Device, data: PartData, format: TextureFormat) -> Self { + let mut vertex = Vec::new(); + let mut index = Vec::new(); + let attrs = data.vertex.unwrap(); + for i in 0..data.vertex[0].as_ref().unwrap().0.len() { + vertex.extend(attrs[0].0[i].to_le_bytes()); + vertex.extend(attrs[1].0[i].to_le_bytes()); + vertex.extend(attrs[2].0[i].to_le_bytes()); + } + let mut n_vertex = 0; + for ind in data.index.unwrap().0 { + index.extend(ind[0].to_le_bytes()); + index.extend(ind[1].to_le_bytes()); + index.extend(ind[2].to_le_bytes()); + n_vertex += 3; + } + + let vertex = device.create_buffer_init(&BufferInitDescriptor { + label: None, + contents: &vertex, + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + }); + let index = device.create_buffer_init(&BufferInitDescriptor { + label: None, + contents: &index, + usage: BufferUsages::INDEX | BufferUsages::COPY_DST, + }); + + let module = device.create_shader_module(include_wgsl!("shader.wgsl")); + + let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[], + label: None, + }); + let bind_group = device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[], + }); + let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + fragment: Some(FragmentState { + module: &module, + entry_point: Some("fs_main"), + targets: &[Some(ColorTargetState { + blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING), + format, + write_mask: ColorWrites::all(), + })], + compilation_options: PipelineCompilationOptions::default(), + }), + vertex: VertexState { + module: &module, + entry_point: Some("vs_main"), + buffers: &[VertexBufferLayout { + step_mode: VertexStepMode::Vertex, + array_stride: 3, + attributes: &[VertexAttribute { + format: VertexFormat::Float32x3, + offset: 0, + shader_location: 0, + }], + }], + compilation_options: PipelineCompilationOptions::default(), + }, + primitive: PrimitiveState { + topology: PrimitiveTopology::TriangleList, + front_face: FrontFace::Ccw, + cull_mode: None, //Some(Face::Back), + polygon_mode: PolygonMode::Fill, + ..Default::default() + }, + depth_stencil: Default::default(), + multisample: MultisampleState::default(), + multiview: None, + cache: None, + }); + + Self { + bind_group, + index, + vertex, + pipeline, + n_vertex, + } + } + pub fn draw(&self, commands: &mut CommandEncoder, target: TextureView) { + let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { + label: None, + color_attachments: &[Some(RenderPassColorAttachment { + view: &target, + resolve_target: None, + ops: Operations { + store: StoreOp::Store, + load: LoadOp::Load, + }, + })], + ..Default::default() + }); + + rpass.set_bind_group(0, &self.bind_group, &[]); + rpass.set_pipeline(&self.pipeline); + rpass.set_vertex_buffer(0, self.vertex.slice(..)); + rpass.set_index_buffer(self.index.slice(..), IndexFormat::Uint16); + rpass.draw(0..self.n_vertex, 0..1); + } +} |