diff --git a/crates/renderer/src/mesh.rs b/crates/renderer/src/mesh.rs new file mode 100644 index 0000000..fa1ab4b --- /dev/null +++ b/crates/renderer/src/mesh.rs @@ -0,0 +1,47 @@ +use bytemuck::{Pod, Zeroable}; + +/// Represents a single vertex in 3D space with position and texture coordinates. +/// +/// Uses `repr(C)` to ensure the memory layout matches what the GPU expects (no Rust-specific reordering). +/// `Pod` and `Zeroable` allows safely casting this struct to a raw byte slice. +#[repr(C)] +#[derive(Copy, Clone, Debug, Pod, Zeroable)] +pub struct Vertex { + /// 3D position of the vertex (X, Y, Z). + pub position: [f32; 3], + /// 2D texture coordinates (U, V). + pub tex_coord: [f32; 2], +} + +impl Vertex { + /// Describes how Vulkan should read the vertex data from a buffer. + /// + /// This defines the 'stride' (distance between vertices) and specifies that + /// data is read per-vertex rather than per-instance. + pub fn get_binding_description() -> ash::vk::VertexInputBindingDescription { + ash::vk::VertexInputBindingDescription::default() + .binding(0) + .stride(std::mem::size_of::() as u32) + .input_rate(ash::vk::VertexInputRate::VERTEX) + } + + /// Describes the layout of individual fields (attributes) within a single vertex. + /// + /// These 'locations' must match the `layout(location = X)` qualifiers in the vertex shader. + pub fn get_attribute_descriptions() -> [ash::vk::VertexInputAttributeDescription; 2] { + [ + // Location 0: position (vec3 -> R32G32B32_SFLOAT) + ash::vk::VertexInputAttributeDescription::default() + .binding(0) + .location(0) + .format(ash::vk::Format::R32G32B32_SFLOAT) + .offset(0), + // Location 1: tex_coord (vec2 -> R32G32_SFLOAT) + ash::vk::VertexInputAttributeDescription::default() + .binding(0) + .location(1) + .format(ash::vk::Format::R32G32_SFLOAT) + .offset(std::mem::size_of::<[f32; 3]>() as u32), + ] + } +}