diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-05 21:28:19 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-05 21:28:19 +0100 |
commit | c427fed04f89147bcdcb2b4b1be9198a063d89cd (patch) | |
tree | b713c689795592ee93125575588e9be5cfe925c8 /client/src/part.rs | |
parent | a6f57036bc954bab45d61fb41c1bd0a27001bad6 (diff) | |
download | weareserver-c427fed04f89147bcdcb2b4b1be9198a063d89cd.tar weareserver-c427fed04f89147bcdcb2b4b1be9198a063d89cd.tar.bz2 weareserver-c427fed04f89147bcdcb2b4b1be9198a063d89cd.tar.zst |
a
Diffstat (limited to 'client/src/part.rs')
-rw-r--r-- | client/src/part.rs | 157 |
1 files changed, 157 insertions, 0 deletions
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); + } +} |