hephae_render/
attribute.rs

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