summaryrefslogtreecommitdiff
path: root/client/src/part.rs
blob: 15835d0eed4a9e30f719f543d89deee20725120d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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);
    }
}