#[allow(unused_imports)] use log::{debug, error, info, trace, warn}; //--Internal imports-------------------------------------------------------------------------------- //--External imports-------------------------------------------------------------------------------- use std::marker::PhantomData; use super::WgpuRenderer; //--Bind group layouts------------------------------------------------------------------------------ /// Creates the layout bind_group used by all matrixes of the renderer pub fn new_matrix_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, } ], label: Some("matrix_bind_group_layout"), }) } /// Crates the layout bind group used by all textures of the renderer pub fn new_texture_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { multisampled: false, view_dimension: wgpu::TextureViewDimension::D2, sample_type: wgpu::TextureSampleType::Float { filterable: true }, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, // This should match the filterable field of the // corresponding Texture entry above. ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], label: Some("texture_bind_group_layout"), }) } //--TextureVertex struct---------------------------------------------------------------------------- #[repr(C)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] pub struct ColorVertex { pub position: [f32; 2], pub color: [f32; 3], } impl ColorVertex { const ATTRIBS: [wgpu::VertexAttribute; 2] = wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x3]; pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { wgpu::VertexBufferLayout { array_stride: std::mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, attributes: &Self::ATTRIBS, } } } //--Mesh struct------------------------------------------------------------------------------------- /// Handles the buffers to be used to draw a Mesh /// /// The mesh consist of an array of vertices, and its ccorresponding indices. /// /// A vertex can be any type that can be converted to a byte array using the bytemuck crate. /// Generaly, adding `#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]` to a struct /// is enough for that. /// /// An index is a standard u16 /// /// A mesh can be used with, and only with, the renderer for wich it was created pub struct Mesh where V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable, { vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, vertex_type: PhantomData, } impl Mesh where V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable + std::fmt::Debug { /// Creates a new mesh using the [Device] from the renderer to be used pub fn new(device: &wgpu::Device) -> Self { use std::mem::size_of; use wgpu_types::BufferUsages as Usages; let vertex_buffer = device.create_buffer( &wgpu_types::BufferDescriptor { label: Some("Vertex Buffer"), size: (V_NB * size_of::()) as u64, usage: Usages::VERTEX | Usages::COPY_DST, mapped_at_creation: false, } ); let index_buffer = device.create_buffer( &wgpu_types::BufferDescriptor { label: Some("Index Buffer"), size: (I_NB * size_of::()) as u64, usage: Usages::INDEX | Usages::COPY_DST, mapped_at_creation: false, } ); Self { vertex_buffer, index_buffer, vertex_type: PhantomData::default(), } } /// Updates the vertices of the [Mesh]. The modification will be applied before the next /// rendering of the [Mesh]. The function will fail if the given slice has more elements than /// specified at the [Mesh] creation pub fn set_vertices(&mut self, renderer: &WgpuRenderer, vertices: &[V]) { renderer.queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(vertices)); } /// Updates the indices of the [Mesh]. The modification will be applied before the next /// rendering of the [Mesh]. The function will fail if the given slice has more elements than /// specified at the [Mesh] creation pub fn set_indices(&mut self, renderer: &WgpuRenderer, indices: &[u16]) { renderer.queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(indices)); } /// Returns a [BufferSlice] containing the vertices, to be used in a render pass pub fn get_vertex_buffer_slice(&self) -> wgpu::BufferSlice { self.vertex_buffer.slice(..) } /// Returns a [BufferSlice] containing the indices, to be used in a render pass pub fn get_index_buffer_slice(&self) -> wgpu::BufferSlice { self.index_buffer.slice(..) } }