167 lines
5.9 KiB
Rust
167 lines
5.9 KiB
Rust
#[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::<ColorVertex>() 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<V, const V_NB: usize, const I_NB: usize>
|
|
where
|
|
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable,
|
|
{
|
|
vertex_buffer: wgpu::Buffer,
|
|
index_buffer: wgpu::Buffer,
|
|
|
|
vertex_type: PhantomData<V>,
|
|
}
|
|
|
|
impl <V, const V_NB: usize, const I_NB: usize> Mesh<V, V_NB, I_NB>
|
|
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::<V>()) 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::<u16>()) 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(..)
|
|
}
|
|
}
|
|
|