hephae_render/
attribute.rs

1//! Defines functionalitie associated with vertex attributes and their respective layouts and
2//! formats.
3
4use bevy_color::prelude::*;
5use bevy_derive::{Deref, DerefMut};
6use bevy_reflect::prelude::*;
7use bevy_render::render_resource::{VertexAttribute, VertexFormat};
8use bytemuck::{Pod, Zeroable};
9pub use hephae_render_derive::VertexLayout;
10
11/// Represents values that, when passed to shaders as vertex attributes, are to be treated as
12/// normalized floating point numbers. For example, `[u8; 2]`'s format is [`VertexFormat::Uint8x2`],
13/// while `[Nor<u8>; 2]`'s format is [`VertexFormat::Unorm8x2`].
14#[derive(Reflect, Debug, Copy, Clone, Default, Pod, Zeroable, PartialEq, Eq, PartialOrd, Ord, Deref, DerefMut)]
15#[repr(transparent)]
16pub struct Nor<T>(pub T);
17
18impl<T> From<T> for Nor<T> {
19    #[inline]
20    fn from(value: T) -> Self {
21        Self(value)
22    }
23}
24
25/// Extension trait for `LinearRgba`.
26pub trait LinearRgbaExt {
27    /// [`to_u8_array`](LinearRgba::to_u8_array), treated as normalized values. Useful for
28    /// byte-color vertex attributes.
29    fn to_nor_array(self) -> [Nor<u8>; 4];
30}
31
32impl LinearRgbaExt for LinearRgba {
33    #[inline]
34    fn to_nor_array(self) -> [Nor<u8>; 4] {
35        self.to_u8_array().map(Nor)
36    }
37}
38
39/// Marks the type as acceptable by shader programs as vertex attributes. You shouldn't implement
40/// this manually, as this crate already does that for you.
41///
42/// # Safety
43///
44/// [`FORMAT::size()`](VertexFormat::size) == [`size_of::<Self>()`](size_of).
45pub unsafe trait IsVertexAttribute: Pod {
46    /// The associated vertex format of this vertex attribute.
47    const FORMAT: VertexFormat;
48}
49
50macro_rules! impl_is_vertex_attribute {
51    ($($target:ty => $result:ident)*) => {
52        $(
53            const _: () = assert!(size_of::<$target>() as u64 == VertexFormat::$result.size());
54
55            // Safety: Assertion above guarantees same sizes.
56            unsafe impl IsVertexAttribute for $target {
57                const FORMAT: VertexFormat = VertexFormat::$result;
58            }
59        )*
60    };
61}
62
63impl_is_vertex_attribute! {
64    [u8; 2] => Uint8x2
65    [u8; 4] => Uint8x4
66    [i8; 2] => Sint8x2
67    [i8; 4] => Sint8x4
68    [Nor<u8>; 2] => Unorm8x2
69    [Nor<u8>; 4] => Unorm8x4
70    [Nor<i8>; 2] => Snorm8x2
71    [Nor<i8>; 4] => Snorm8x4
72    [u16; 2] => Uint16x2
73    [u16; 4] => Uint16x4
74    [i16; 2] => Sint16x2
75    [i16; 4] => Sint16x4
76    [Nor<u16>; 2] => Unorm16x2
77    [Nor<u16>; 4] => Unorm16x4
78    [Nor<i16>; 2] => Snorm16x2
79    [Nor<i16>; 4] => Snorm16x4
80    // Currently, `Float16x2` and `Float16x4` is ignored.
81    f32 => Float32
82    [f32; 1] => Float32
83    [f32; 2] => Float32x2
84    [f32; 3] => Float32x3
85    [f32; 4] => Float32x4
86    u32 => Uint32
87    [u32; 1] => Uint32
88    [u32; 2] => Uint32x2
89    [u32; 3] => Uint32x3
90    [u32; 4] => Uint32x4
91    i32 => Sint32
92    [i32; 1] => Sint32
93    [i32; 2] => Sint32x2
94    [i32; 3] => Sint32x3
95    [i32; 4] => Sint32x4
96    f64 => Float64
97    [f64; 1] => Float64
98    [f64; 2] => Float64x2
99    [f64; 3] => Float64x3
100    [f64; 4] => Float64x4
101    // Currently, `Unorm10_10_10_2` is ignored.
102    LinearRgba => Float32x4
103}
104
105/// Represents vertex values in a [vertex buffer object](bevy_render::render_resource::Buffer).
106///
107/// # Safety
108///
109/// - The sum of `ATTRIBUTES`'s [size](VertexFormat::size) must be equal to
110///   [`size_of::<Self>()`](size_of).
111/// - Each `ATTRIBUTES`'s [offset](`VertexAttribute::offset`) must be equal to [`offset_of!(Self,
112///   field)`](std::mem::offset_of), where `field` is the field represented by the attribute.
113pub unsafe trait VertexLayout: Pod {
114    /// The attributes of this layout.
115    const ATTRIBUTES: &'static [VertexAttribute];
116}