98 lines
2.5 KiB
Rust
98 lines
2.5 KiB
Rust
|
use wgpu::{self, util::DeviceExt};
|
||
|
|
||
|
use super::BufferObject;
|
||
|
|
||
|
pub struct VertexBuffer {
|
||
|
/// Vertices to draw.
|
||
|
///
|
||
|
/// This can be set to None if each instance
|
||
|
/// only needs one vertex. Note that the shader
|
||
|
/// must be prepared for this!
|
||
|
vertices: Option<wgpu::Buffer>,
|
||
|
|
||
|
/// Vertex indices. This will be None if we're
|
||
|
/// drawing vertices directly, without indices.
|
||
|
indices: Option<wgpu::Buffer>,
|
||
|
|
||
|
pub instances: wgpu::Buffer,
|
||
|
pub layout: Box<[wgpu::VertexBufferLayout<'static>]>,
|
||
|
}
|
||
|
|
||
|
impl VertexBuffer {
|
||
|
pub fn new<VertexType, InstanceType>(
|
||
|
label: &str,
|
||
|
device: &wgpu::Device,
|
||
|
vertices: Option<&[VertexType]>,
|
||
|
indices: Option<&[u16]>,
|
||
|
length: u64,
|
||
|
) -> Self
|
||
|
where
|
||
|
VertexType: BufferObject,
|
||
|
InstanceType: BufferObject,
|
||
|
{
|
||
|
let vertices = if let Some(vertices) = vertices {
|
||
|
Some(
|
||
|
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||
|
label: Some(&format!("[{}] vertex buffer", label)),
|
||
|
contents: bytemuck::cast_slice(vertices),
|
||
|
usage: wgpu::BufferUsages::VERTEX,
|
||
|
}),
|
||
|
)
|
||
|
} else {
|
||
|
None
|
||
|
};
|
||
|
|
||
|
let indices = if let Some(indices) = indices {
|
||
|
if vertices.is_none() {
|
||
|
unreachable!("Bad code! You cannot draw indexed vertices if vertices is None!")
|
||
|
}
|
||
|
|
||
|
Some(
|
||
|
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||
|
label: Some(&format!("[{}] index buffer", label)),
|
||
|
contents: bytemuck::cast_slice(indices),
|
||
|
usage: wgpu::BufferUsages::INDEX,
|
||
|
}),
|
||
|
)
|
||
|
} else {
|
||
|
None
|
||
|
};
|
||
|
|
||
|
let instances = device.create_buffer(&wgpu::BufferDescriptor {
|
||
|
label: Some(&format!("[{}] instance buffer", label)),
|
||
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||
|
size: InstanceType::SIZE * length,
|
||
|
mapped_at_creation: false,
|
||
|
});
|
||
|
|
||
|
let mut layout = Vec::new();
|
||
|
if vertices.is_some() {
|
||
|
layout.push(VertexType::layout());
|
||
|
}
|
||
|
layout.push(InstanceType::layout());
|
||
|
|
||
|
Self {
|
||
|
vertices,
|
||
|
indices,
|
||
|
instances,
|
||
|
layout: layout.into(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Set the buffers defined here as buffers in a RenderPass.
|
||
|
pub fn set_in_pass<'a, 'b: 'a>(&'b self, render_pass: &'a mut wgpu::RenderPass<'b>) {
|
||
|
// TODO: why do these lifetimes work?
|
||
|
let mut v_slot = 0u32;
|
||
|
if let Some(vertices) = &self.vertices {
|
||
|
render_pass.set_vertex_buffer(v_slot, vertices.slice(..));
|
||
|
v_slot += 1;
|
||
|
}
|
||
|
render_pass.set_vertex_buffer(v_slot, self.instances.slice(..));
|
||
|
//v_slot += 1;
|
||
|
|
||
|
if let Some(indices) = &self.indices {
|
||
|
render_pass.set_index_buffer(indices.slice(..), wgpu::IndexFormat::Uint16);
|
||
|
}
|
||
|
}
|
||
|
}
|