gloss_renderer/components/
mesh_gpu_comps.rs

1//! These represent GPU components which are usually added automatically and
2//! uploaded from CPU to GPU from the corresponding CPU components. When
3//! creating entities, you usually just add CPU components.
4
5use easy_wgpu::texture::TexParams;
6use ktx2;
7use pollster::FutureExt;
8use wgpu;
9
10#[derive(Debug)]
11pub struct VertsGPU {
12    pub buf: wgpu::Buffer,
13    pub nr_vertices: u32,
14}
15impl VertsGPU {
16    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
17    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
18        wgpu::VertexBufferLayout {
19            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
20            step_mode: wgpu::VertexStepMode::Vertex,
21            attributes: &wgpu::vertex_attr_array![
22            SHADER_LOCATION => Float32x3
23            ],
24        }
25    }
26    pub fn vertex_buffer_layout_instanced<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
27        wgpu::VertexBufferLayout {
28            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
29            step_mode: wgpu::VertexStepMode::Instance,
30            attributes: &wgpu::vertex_attr_array![
31            SHADER_LOCATION => Float32x3
32            ],
33        }
34    }
35}
36
37#[derive(Debug)]
38pub struct EdgesV1GPU {
39    pub buf: wgpu::Buffer,
40    pub nr_vertices: u32,
41}
42impl EdgesV1GPU {
43    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
44    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
45        wgpu::VertexBufferLayout {
46            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
47            step_mode: wgpu::VertexStepMode::Vertex,
48            attributes: &wgpu::vertex_attr_array![
49            SHADER_LOCATION => Float32x3
50            ],
51        }
52    }
53    pub fn vertex_buffer_layout_instanced<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
54        wgpu::VertexBufferLayout {
55            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
56            step_mode: wgpu::VertexStepMode::Instance,
57            attributes: &wgpu::vertex_attr_array![
58            SHADER_LOCATION => Float32x3
59            ],
60        }
61    }
62}
63#[derive(Debug)]
64pub struct EdgesV2GPU {
65    pub buf: wgpu::Buffer,
66    pub nr_vertices: u32,
67}
68impl EdgesV2GPU {
69    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
70    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
71        wgpu::VertexBufferLayout {
72            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
73            step_mode: wgpu::VertexStepMode::Vertex,
74            attributes: &wgpu::vertex_attr_array![
75            SHADER_LOCATION => Float32x3
76            ],
77        }
78    }
79    pub fn vertex_buffer_layout_instanced<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
80        wgpu::VertexBufferLayout {
81            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
82            step_mode: wgpu::VertexStepMode::Instance,
83            attributes: &wgpu::vertex_attr_array![
84            SHADER_LOCATION => Float32x3
85            ],
86        }
87    }
88}
89
90pub struct UVsGPU {
91    pub buf: wgpu::Buffer,
92    pub nr_vertices: u32,
93}
94impl UVsGPU {
95    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
96        wgpu::VertexBufferLayout {
97            array_stride: (2 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
98            step_mode: wgpu::VertexStepMode::Vertex,
99            attributes: &wgpu::vertex_attr_array![
100            SHADER_LOCATION => Float32x2
101            ],
102        }
103    }
104}
105pub struct NormalsGPU {
106    pub buf: wgpu::Buffer,
107    pub nr_vertices: u32,
108}
109impl NormalsGPU {
110    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
111    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
112        wgpu::VertexBufferLayout {
113            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
114            step_mode: wgpu::VertexStepMode::Vertex,
115            attributes: &wgpu::vertex_attr_array![
116            SHADER_LOCATION => Float32x3
117            ],
118        }
119    }
120}
121
122pub struct TangentsGPU {
123    pub buf: wgpu::Buffer,
124    pub nr_vertices: u32,
125}
126impl TangentsGPU {
127    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
128    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
129        wgpu::VertexBufferLayout {
130            //we make it 4 because we need to also store the handetness
131            array_stride: (4 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
132            step_mode: wgpu::VertexStepMode::Vertex,
133            attributes: &wgpu::vertex_attr_array![
134            SHADER_LOCATION => Float32x4
135            ],
136        }
137    }
138}
139
140pub struct ColorsGPU {
141    pub buf: wgpu::Buffer,
142    pub nr_vertices: u32,
143}
144impl ColorsGPU {
145    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
146    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
147        wgpu::VertexBufferLayout {
148            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
149            step_mode: wgpu::VertexStepMode::Vertex,
150            attributes: &wgpu::vertex_attr_array![
151            SHADER_LOCATION => Float32x3
152            ],
153        }
154    }
155    pub fn vertex_buffer_layout_instanced<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
156        wgpu::VertexBufferLayout {
157            array_stride: (3 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
158            step_mode: wgpu::VertexStepMode::Instance,
159            attributes: &wgpu::vertex_attr_array![
160            SHADER_LOCATION => Float32x3
161            ],
162        }
163    }
164}
165#[derive(Debug)]
166pub struct EdgesGPU {
167    pub buf: wgpu::Buffer,
168    pub nr_edges: u32,
169}
170impl EdgesGPU {
171    //returning a vertex layout witha  dynamic shader location //https://github.com/gfx-rs/wgpu/discussions/2050
172    pub fn vertex_buffer_layout<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
173        wgpu::VertexBufferLayout {
174            array_stride: (2 * std::mem::size_of::<u32>()) as wgpu::BufferAddress,
175            step_mode: wgpu::VertexStepMode::Vertex,
176            attributes: &wgpu::vertex_attr_array![
177            SHADER_LOCATION => Float32x2
178            ],
179        }
180    }
181    pub fn vertex_buffer_layout_instanced<const SHADER_LOCATION: u32>() -> wgpu::VertexBufferLayout<'static> {
182        wgpu::VertexBufferLayout {
183            array_stride: (2 * std::mem::size_of::<u32>()) as wgpu::BufferAddress,
184            step_mode: wgpu::VertexStepMode::Instance,
185            attributes: &wgpu::vertex_attr_array![
186            SHADER_LOCATION => Float32x2
187            ],
188        }
189    }
190}
191
192pub struct FacesGPU {
193    pub buf: wgpu::Buffer,
194    pub nr_triangles: u32,
195}
196
197#[derive(Clone)]
198pub struct DiffuseTex(pub easy_wgpu::texture::Texture);
199
200#[derive(Clone)]
201pub struct NormalTex(pub easy_wgpu::texture::Texture);
202
203#[derive(Clone)]
204pub struct MetalnessTex(pub easy_wgpu::texture::Texture);
205
206#[derive(Clone)]
207pub struct RoughnessTex(pub easy_wgpu::texture::Texture);
208
209pub trait TextureGetter {
210    fn texture(&self) -> &easy_wgpu::texture::Texture;
211    fn texture_mut(&mut self) -> &mut easy_wgpu::texture::Texture;
212}
213
214impl TextureGetter for DiffuseTex {
215    fn texture_mut(&mut self) -> &mut easy_wgpu::texture::Texture {
216        &mut self.0
217    }
218    fn texture(&self) -> &easy_wgpu::texture::Texture {
219        &self.0
220    }
221}
222
223impl TextureGetter for NormalTex {
224    fn texture_mut(&mut self) -> &mut easy_wgpu::texture::Texture {
225        &mut self.0
226    }
227    fn texture(&self) -> &easy_wgpu::texture::Texture {
228        &self.0
229    }
230}
231
232impl TextureGetter for MetalnessTex {
233    fn texture_mut(&mut self) -> &mut easy_wgpu::texture::Texture {
234        &mut self.0
235    }
236    fn texture(&self) -> &easy_wgpu::texture::Texture {
237        &self.0
238    }
239}
240
241impl TextureGetter for RoughnessTex {
242    fn texture_mut(&mut self) -> &mut easy_wgpu::texture::Texture {
243        &mut self.0
244    }
245    fn texture(&self) -> &easy_wgpu::texture::Texture {
246        &self.0
247    }
248}
249
250#[derive(Clone)]
251pub struct EnvironmentMapGpu {
252    pub diffuse_tex: easy_wgpu::texture::Texture,
253    pub specular_tex: easy_wgpu::texture::Texture,
254}
255impl EnvironmentMapGpu {
256    pub fn new_dummy(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
257        let diffuse_tex = easy_wgpu::texture::Texture::create_default_cubemap(device, queue);
258        let specular_tex = easy_wgpu::texture::Texture::create_default_cubemap(device, queue);
259        Self { diffuse_tex, specular_tex }
260    }
261
262    /// # Panics
263    /// Will panic if the environment map is not the expected format
264    #[allow(clippy::similar_names)]
265    pub fn reader2texture(reader: &ktx2::Reader<&[u8]>, device: &wgpu::Device, queue: &wgpu::Queue) -> easy_wgpu::texture::Texture {
266        // Get general texture information.
267        let header = reader.header();
268        assert_eq!(header.format, Some(ktx2::Format::R16G16B16A16_SFLOAT));
269        let nr_mips = header.level_count;
270        let width = header.pixel_width;
271        let height = header.pixel_height;
272        // println!("nr mips {}", nr_mips);
273        // println!("header is {:?}", header);
274
275        //make texture
276        let usages = wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST;
277        let desc = wgpu::TextureDescriptor {
278            label: None,
279            size: wgpu::Extent3d {
280                width,
281                height,
282                depth_or_array_layers: 6, //it's a cube txture so it's always 6 layers
283            },
284            mip_level_count: nr_mips,
285            sample_count: 1,
286            dimension: wgpu::TextureDimension::D2,
287            format: wgpu::TextureFormat::Rgba16Float,
288            usage: usages,
289            view_formats: &[],
290        };
291        let tex_params = TexParams::from_desc(&desc);
292        let texture = device.create_texture(&desc); //create with all mips but upload only 1 mip
293
294        //TODO maybe possible to upload all the mips at the same time using reader.data
295        // which gives you all the mips
296
297        // Read iterator over slices of each mipmap level.
298        let levels = reader.levels().collect::<Vec<_>>();
299        for (mip, level_data) in levels.iter().enumerate() {
300            easy_wgpu::texture::Texture::upload_single_mip(&texture, device, queue, &desc, level_data, None, u32::try_from(mip).unwrap())
301                .block_on()
302                .unwrap();
303        }
304
305        //view and sampler
306        let view = texture.create_view(&wgpu::TextureViewDescriptor {
307            dimension: Some(wgpu::TextureViewDimension::Cube),
308            ..Default::default()
309        });
310
311        let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
312            address_mode_u: wgpu::AddressMode::ClampToEdge,
313            address_mode_v: wgpu::AddressMode::ClampToEdge,
314            address_mode_w: wgpu::AddressMode::ClampToEdge,
315            mag_filter: wgpu::FilterMode::Linear,
316            min_filter: wgpu::FilterMode::Linear,
317            mipmap_filter: wgpu::FilterMode::Linear,
318            ..Default::default()
319        });
320
321        easy_wgpu::texture::Texture {
322            texture,
323            view,
324            sampler,
325            tex_params,
326        }
327    }
328}
329
330//implement some atributes for the vertex atributes so we can use them in a
331// generic function
332pub trait GpuAtrib {
333    fn data_ref(&self) -> &wgpu::Buffer;
334    fn new_from(buf: wgpu::Buffer, nr_rows: u32) -> Self;
335}
336
337impl GpuAtrib for VertsGPU {
338    fn data_ref(&self) -> &wgpu::Buffer {
339        &self.buf
340    }
341    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
342        Self { buf, nr_vertices }
343    }
344}
345impl GpuAtrib for EdgesV1GPU {
346    fn data_ref(&self) -> &wgpu::Buffer {
347        &self.buf
348    }
349    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
350        Self { buf, nr_vertices }
351    }
352}
353impl GpuAtrib for EdgesV2GPU {
354    fn data_ref(&self) -> &wgpu::Buffer {
355        &self.buf
356    }
357    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
358        Self { buf, nr_vertices }
359    }
360}
361impl GpuAtrib for EdgesGPU {
362    fn data_ref(&self) -> &wgpu::Buffer {
363        &self.buf
364    }
365    fn new_from(buf: wgpu::Buffer, nr_edges: u32) -> Self {
366        Self { buf, nr_edges }
367    }
368}
369impl GpuAtrib for FacesGPU {
370    fn data_ref(&self) -> &wgpu::Buffer {
371        &self.buf
372    }
373    fn new_from(buf: wgpu::Buffer, nr_triangles: u32) -> Self {
374        Self { buf, nr_triangles }
375    }
376}
377impl GpuAtrib for UVsGPU {
378    fn data_ref(&self) -> &wgpu::Buffer {
379        &self.buf
380    }
381    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
382        Self { buf, nr_vertices }
383    }
384}
385impl GpuAtrib for NormalsGPU {
386    fn data_ref(&self) -> &wgpu::Buffer {
387        &self.buf
388    }
389    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
390        Self { buf, nr_vertices }
391    }
392}
393impl GpuAtrib for TangentsGPU {
394    fn data_ref(&self) -> &wgpu::Buffer {
395        &self.buf
396    }
397    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
398        Self { buf, nr_vertices }
399    }
400}
401impl GpuAtrib for ColorsGPU {
402    fn data_ref(&self) -> &wgpu::Buffer {
403        &self.buf
404    }
405    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
406        Self { buf, nr_vertices }
407    }
408}
409
410//so we can use the Components inside the Mutex<Hashmap> in the scene and wasm
411// https://stackoverflow.com/a/73773940/22166964
412// shenanigans
413//vertsgpu
414#[cfg(target_arch = "wasm32")]
415unsafe impl Send for VertsGPU {}
416#[cfg(target_arch = "wasm32")]
417unsafe impl Sync for VertsGPU {}
418//vertsgpue1
419#[cfg(target_arch = "wasm32")]
420unsafe impl Send for EdgesV1GPU {}
421#[cfg(target_arch = "wasm32")]
422unsafe impl Sync for EdgesV1GPU {}
423//vertsgpue2
424#[cfg(target_arch = "wasm32")]
425unsafe impl Send for EdgesV2GPU {}
426#[cfg(target_arch = "wasm32")]
427unsafe impl Sync for EdgesV2GPU {}
428//edgesgpu
429#[cfg(target_arch = "wasm32")]
430unsafe impl Send for EdgesGPU {}
431#[cfg(target_arch = "wasm32")]
432unsafe impl Sync for EdgesGPU {}
433//facesgpu
434#[cfg(target_arch = "wasm32")]
435unsafe impl Send for FacesGPU {}
436#[cfg(target_arch = "wasm32")]
437unsafe impl Sync for FacesGPU {}
438//uvsgpu
439#[cfg(target_arch = "wasm32")]
440unsafe impl Send for UVsGPU {}
441#[cfg(target_arch = "wasm32")]
442unsafe impl Sync for UVsGPU {}
443//normalsgpu
444#[cfg(target_arch = "wasm32")]
445unsafe impl Send for NormalsGPU {}
446#[cfg(target_arch = "wasm32")]
447unsafe impl Sync for NormalsGPU {}
448//tangentsgpu
449#[cfg(target_arch = "wasm32")]
450unsafe impl Send for TangentsGPU {}
451#[cfg(target_arch = "wasm32")]
452unsafe impl Sync for TangentsGPU {}
453//colors
454#[cfg(target_arch = "wasm32")]
455unsafe impl Send for ColorsGPU {}
456#[cfg(target_arch = "wasm32")]
457unsafe impl Sync for ColorsGPU {}
458//Diffusetex
459#[cfg(target_arch = "wasm32")]
460unsafe impl Send for DiffuseTex {}
461#[cfg(target_arch = "wasm32")]
462unsafe impl Sync for DiffuseTex {}
463//Normaltex
464#[cfg(target_arch = "wasm32")]
465unsafe impl Send for NormalTex {}
466#[cfg(target_arch = "wasm32")]
467unsafe impl Sync for NormalTex {}
468//Metalnesstex
469#[cfg(target_arch = "wasm32")]
470unsafe impl Send for MetalnessTex {}
471#[cfg(target_arch = "wasm32")]
472unsafe impl Sync for MetalnessTex {}
473//Roughnesstex
474#[cfg(target_arch = "wasm32")]
475unsafe impl Send for RoughnessTex {}
476#[cfg(target_arch = "wasm32")]
477unsafe impl Sync for RoughnessTex {}
478//EnvironmentMap
479#[cfg(target_arch = "wasm32")]
480unsafe impl Send for EnvironmentMapGpu {}
481#[cfg(target_arch = "wasm32")]
482unsafe impl Sync for EnvironmentMapGpu {}