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>, index: Option, } impl PartData { pub fn update(&mut self, hash: Resource, data: &[u8]) -> Result { 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); } }