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 wgpu;
8
9extern crate nalgebra as na;
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
197pub struct DiffuseTex(pub easy_wgpu::texture::Texture);
198pub struct NormalTex(pub easy_wgpu::texture::Texture);
199pub struct MetalnessTex(pub easy_wgpu::texture::Texture);
200pub struct RoughnessTex(pub easy_wgpu::texture::Texture);
201
202pub struct EnvironmentMapGpu {
203    pub diffuse_tex: easy_wgpu::texture::Texture,
204    pub specular_tex: easy_wgpu::texture::Texture,
205}
206impl EnvironmentMapGpu {
207    pub fn new_dummy(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
208        let diffuse_tex = easy_wgpu::texture::Texture::create_default_cubemap(device, queue);
209        let specular_tex = easy_wgpu::texture::Texture::create_default_cubemap(device, queue);
210        Self { diffuse_tex, specular_tex }
211    }
212
213    /// # Panics
214    /// Will panic if the environment map is not the expected format
215    #[allow(clippy::similar_names)]
216    pub fn reader2texture(reader: &ktx2::Reader<&[u8]>, device: &wgpu::Device, queue: &wgpu::Queue) -> easy_wgpu::texture::Texture {
217        // Get general texture information.
218        let header = reader.header();
219        assert_eq!(header.format, Some(ktx2::Format::R16G16B16A16_SFLOAT));
220        let nr_mips = header.level_count;
221        let width = header.pixel_width;
222        let height = header.pixel_height;
223        // println!("nr mips {}", nr_mips);
224        // println!("header is {:?}", header);
225
226        //make texture
227        let usages = wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST;
228        let desc = wgpu::TextureDescriptor {
229            label: None,
230            size: wgpu::Extent3d {
231                width,
232                height,
233                depth_or_array_layers: 6, //it's a cube txture so it's always 6 layers
234            },
235            mip_level_count: nr_mips,
236            sample_count: 1,
237            dimension: wgpu::TextureDimension::D2,
238            format: wgpu::TextureFormat::Rgba16Float,
239            usage: usages,
240            view_formats: &[],
241        };
242        let tex_params = TexParams::from_desc(&desc);
243        let texture = device.create_texture(&desc); //create with all mips but upload only 1 mip
244
245        //TODO maybe possible to upload all the mips at the same time using reader.data
246        // which gives you all the mips
247
248        // Read iterator over slices of each mipmap level.
249        let levels = reader.levels().collect::<Vec<_>>();
250        for (mip, level_data) in levels.iter().enumerate() {
251            easy_wgpu::texture::Texture::upload_single_mip(&texture, device, queue, &desc, level_data, None, u32::try_from(mip).unwrap());
252        }
253
254        //view and sampler
255        let view = texture.create_view(&wgpu::TextureViewDescriptor {
256            dimension: Some(wgpu::TextureViewDimension::Cube),
257            ..Default::default()
258        });
259
260        let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
261            address_mode_u: wgpu::AddressMode::ClampToEdge,
262            address_mode_v: wgpu::AddressMode::ClampToEdge,
263            address_mode_w: wgpu::AddressMode::ClampToEdge,
264            mag_filter: wgpu::FilterMode::Linear,
265            min_filter: wgpu::FilterMode::Linear,
266            mipmap_filter: wgpu::FilterMode::Linear,
267            ..Default::default()
268        });
269
270        easy_wgpu::texture::Texture {
271            texture,
272            view,
273            sampler,
274            tex_params,
275        }
276    }
277}
278
279//implement some atributes for the vertex atributes so we can use them in a
280// generic function
281pub trait GpuAtrib {
282    fn data_ref(&self) -> &wgpu::Buffer;
283    fn new_from(buf: wgpu::Buffer, nr_rows: u32) -> Self;
284}
285
286impl GpuAtrib for VertsGPU {
287    fn data_ref(&self) -> &wgpu::Buffer {
288        &self.buf
289    }
290    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
291        Self { buf, nr_vertices }
292    }
293}
294impl GpuAtrib for EdgesV1GPU {
295    fn data_ref(&self) -> &wgpu::Buffer {
296        &self.buf
297    }
298    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
299        Self { buf, nr_vertices }
300    }
301}
302impl GpuAtrib for EdgesV2GPU {
303    fn data_ref(&self) -> &wgpu::Buffer {
304        &self.buf
305    }
306    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
307        Self { buf, nr_vertices }
308    }
309}
310impl GpuAtrib for EdgesGPU {
311    fn data_ref(&self) -> &wgpu::Buffer {
312        &self.buf
313    }
314    fn new_from(buf: wgpu::Buffer, nr_edges: u32) -> Self {
315        Self { buf, nr_edges }
316    }
317}
318impl GpuAtrib for FacesGPU {
319    fn data_ref(&self) -> &wgpu::Buffer {
320        &self.buf
321    }
322    fn new_from(buf: wgpu::Buffer, nr_triangles: u32) -> Self {
323        Self { buf, nr_triangles }
324    }
325}
326impl GpuAtrib for UVsGPU {
327    fn data_ref(&self) -> &wgpu::Buffer {
328        &self.buf
329    }
330    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
331        Self { buf, nr_vertices }
332    }
333}
334impl GpuAtrib for NormalsGPU {
335    fn data_ref(&self) -> &wgpu::Buffer {
336        &self.buf
337    }
338    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
339        Self { buf, nr_vertices }
340    }
341}
342impl GpuAtrib for TangentsGPU {
343    fn data_ref(&self) -> &wgpu::Buffer {
344        &self.buf
345    }
346    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
347        Self { buf, nr_vertices }
348    }
349}
350impl GpuAtrib for ColorsGPU {
351    fn data_ref(&self) -> &wgpu::Buffer {
352        &self.buf
353    }
354    fn new_from(buf: wgpu::Buffer, nr_vertices: u32) -> Self {
355        Self { buf, nr_vertices }
356    }
357}
358
359//so we can use the Components inside the Mutex<Hashmap> in the scene and wasm
360// https://stackoverflow.com/a/73773940/22166964
361// shenanigans
362//vertsgpu
363#[cfg(target_arch = "wasm32")]
364unsafe impl Send for VertsGPU {}
365#[cfg(target_arch = "wasm32")]
366unsafe impl Sync for VertsGPU {}
367//vertsgpue1
368#[cfg(target_arch = "wasm32")]
369unsafe impl Send for EdgesV1GPU {}
370#[cfg(target_arch = "wasm32")]
371unsafe impl Sync for EdgesV1GPU {}
372//vertsgpue2
373#[cfg(target_arch = "wasm32")]
374unsafe impl Send for EdgesV2GPU {}
375#[cfg(target_arch = "wasm32")]
376unsafe impl Sync for EdgesV2GPU {}
377//edgesgpu
378#[cfg(target_arch = "wasm32")]
379unsafe impl Send for EdgesGPU {}
380#[cfg(target_arch = "wasm32")]
381unsafe impl Sync for EdgesGPU {}
382//facesgpu
383#[cfg(target_arch = "wasm32")]
384unsafe impl Send for FacesGPU {}
385#[cfg(target_arch = "wasm32")]
386unsafe impl Sync for FacesGPU {}
387//uvsgpu
388#[cfg(target_arch = "wasm32")]
389unsafe impl Send for UVsGPU {}
390#[cfg(target_arch = "wasm32")]
391unsafe impl Sync for UVsGPU {}
392//normalsgpu
393#[cfg(target_arch = "wasm32")]
394unsafe impl Send for NormalsGPU {}
395#[cfg(target_arch = "wasm32")]
396unsafe impl Sync for NormalsGPU {}
397//tangentsgpu
398#[cfg(target_arch = "wasm32")]
399unsafe impl Send for TangentsGPU {}
400#[cfg(target_arch = "wasm32")]
401unsafe impl Sync for TangentsGPU {}
402//colors
403#[cfg(target_arch = "wasm32")]
404unsafe impl Send for ColorsGPU {}
405#[cfg(target_arch = "wasm32")]
406unsafe impl Sync for ColorsGPU {}
407//Diffusetex
408#[cfg(target_arch = "wasm32")]
409unsafe impl Send for DiffuseTex {}
410#[cfg(target_arch = "wasm32")]
411unsafe impl Sync for DiffuseTex {}
412//Normaltex
413#[cfg(target_arch = "wasm32")]
414unsafe impl Send for NormalTex {}
415#[cfg(target_arch = "wasm32")]
416unsafe impl Sync for NormalTex {}
417//Metalnesstex
418#[cfg(target_arch = "wasm32")]
419unsafe impl Send for MetalnessTex {}
420#[cfg(target_arch = "wasm32")]
421unsafe impl Sync for MetalnessTex {}
422//Roughnesstex
423#[cfg(target_arch = "wasm32")]
424unsafe impl Send for RoughnessTex {}
425#[cfg(target_arch = "wasm32")]
426unsafe impl Sync for RoughnessTex {}
427//EnvironmentMap
428#[cfg(target_arch = "wasm32")]
429unsafe impl Send for EnvironmentMapGpu {}
430#[cfg(target_arch = "wasm32")]
431unsafe impl Sync for EnvironmentMapGpu {}