pub struct VertexBuffer { /* private fields */ }Expand description
Vertex buffer with dynamic layout. It is used to store multiple vertices of a single type, that implements VertexTrait.
Different vertex types used to for efficient memory usage. For example, you could have a simple vertex with only position
expressed as Vector3 and it will be enough for simple cases, when only position is required. However, if you want to draw
a mesh with skeletal animation, that also supports texturing, lighting, you need to provide a lot more data (bone indices,
bone weights, normals, tangents, texture coordinates).
Examples
#[derive(Copy, Clone)]
#[repr(C)]
struct MyVertex {
position: Vector3<f32>,
}
impl VertexTrait for MyVertex {
fn layout() -> &'static [VertexAttributeDescriptor] {
&[VertexAttributeDescriptor {
usage: VertexAttributeUsage::Position,
data_type: VertexAttributeDataType::F32,
size: 3,
divisor: 0,
shader_location: 0,
}]
}
}
fn create_triangle_vertex_buffer() -> VertexBuffer {
VertexBuffer::new(
3,
vec![
MyVertex {
position: Vector3::new(0.0, 0.0, 0.0),
},
MyVertex {
position: Vector3::new(0.0, 1.0, 0.0),
},
MyVertex {
position: Vector3::new(1.0, 1.0, 0.0),
},
],
)
.unwrap()
} This example creates a simple vertex buffer that contains a single triangle with custom vertex format. The most important
part here is VertexTrait::layout implementation - it describes each “attribute” of your vertex, if your layout does not
match the actual content of the vertex (in terms of size in bytes), then vertex buffer cannot be created and VertexBuffer::new
will return None.
The second, but not least important is #[repr(C)] attribute - it is mandatory for every vertex type, it forbids fields
reordering of you vertex structure and guarantees that they will have the same layout in memory as their declaration order.
Limitations
Vertex size cannot be more than 256 bytes, this limitation shouldn’t be a problem because almost every GPU supports up to 16 vertex attributes with 16 bytes of size each, which gives exactly 256 bytes.
Implementations§
source§impl VertexBuffer
impl VertexBuffer
sourcepub fn new<T>(
vertex_count: usize,
data: Vec<T>
) -> Result<Self, ValidationError>where
T: VertexTrait,
pub fn new<T>( vertex_count: usize, data: Vec<T> ) -> Result<Self, ValidationError>where T: VertexTrait,
Creates new vertex buffer from provided data and with the given layout of the vertex type T.
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if buffer does not contain any vertex, false - otherwise.
sourcepub fn data_hash(&self) -> u64
pub fn data_hash(&self) -> u64
Returns cached data hash. Cached value is guaranteed to be in actual state.
sourcepub fn layout_hash(&self) -> u64
pub fn layout_hash(&self) -> u64
Returns hash of vertex buffer layout. Cached value is guaranteed to be in actual state. The hash could be used to check if the layout has changed.
sourcepub fn modify(&mut self) -> VertexBufferRefMut<'_>
pub fn modify(&mut self) -> VertexBufferRefMut<'_>
Provides mutable access to content of the buffer.
Performance
This method returns special structure which has custom destructor that calculates hash of the data once modification is over. You must hold this structure as long as possible while modifying contents of the buffer. Do not even try to do this:
use fyrox::{
scene::mesh::buffer::{VertexBuffer, VertexWriteTrait, VertexAttributeUsage},
core::algebra::Vector3
};
fn do_something(buffer: &mut VertexBuffer) {
for i in 0..buffer.vertex_count() {
buffer
.modify() // Doing this in a loop will cause HUGE performance issues!
.get_mut(i as usize)
.unwrap()
.write_3_f32(VertexAttributeUsage::Position, Vector3::<f32>::default())
.unwrap();
}
}Instead do this:
use fyrox::{
scene::mesh::buffer::{VertexBuffer, VertexWriteTrait, VertexAttributeUsage},
core::algebra::Vector3
};
fn do_something(buffer: &mut VertexBuffer) {
let mut buffer_modifier = buffer.modify();
for mut vertex in buffer_modifier.iter_mut() {
vertex
.write_3_f32(VertexAttributeUsage::Position, Vector3::<f32>::default())
.unwrap();
}
}Why do we even need such complications? It is used for lazy hash calculation which is used for automatic upload of contents to GPU in case if content has changed.
sourcepub fn has_attribute(&self, usage: VertexAttributeUsage) -> bool
pub fn has_attribute(&self, usage: VertexAttributeUsage) -> bool
Checks if an attribute of usage exists.
sourcepub fn layout(&self) -> &[VertexAttribute]
pub fn layout(&self) -> &[VertexAttribute]
Returns vertex buffer layout.
sourcepub fn cast_data_ref<T>(&self) -> Result<&[T], ValidationError>where
T: VertexTrait,
pub fn cast_data_ref<T>(&self) -> Result<&[T], ValidationError>where T: VertexTrait,
Tries to cast internal data buffer to a slice of given type. It may fail if size of type is not equal with claimed size (which is set by the layout).
sourcepub fn iter(&self) -> impl Iterator<Item = VertexViewRef<'_>> + '_
pub fn iter(&self) -> impl Iterator<Item = VertexViewRef<'_>> + '_
Creates iterator that emits read accessors for vertices.
sourcepub fn get(&self, n: usize) -> Option<VertexViewRef<'_>>
pub fn get(&self, n: usize) -> Option<VertexViewRef<'_>>
Returns a read accessor of n-th vertex.
sourcepub fn vertex_count(&self) -> u32
pub fn vertex_count(&self) -> u32
Returns exact amount of vertices in the buffer.
sourcepub fn vertex_size(&self) -> u8
pub fn vertex_size(&self) -> u8
Return vertex size of the buffer.
sourcepub fn find_free_shader_location(&self) -> u8
pub fn find_free_shader_location(&self) -> u8
Finds free location for an attribute in the layout.
Trait Implementations§
source§impl Clone for VertexBuffer
impl Clone for VertexBuffer
source§fn clone(&self) -> VertexBuffer
fn clone(&self) -> VertexBuffer
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moresource§impl Debug for VertexBuffer
impl Debug for VertexBuffer
source§impl Default for VertexBuffer
impl Default for VertexBuffer
source§fn default() -> VertexBuffer
fn default() -> VertexBuffer
Auto Trait Implementations§
impl RefUnwindSafe for VertexBuffer
impl Send for VertexBuffer
impl Sync for VertexBuffer
impl Unpin for VertexBuffer
impl UnwindSafe for VertexBuffer
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.source§impl<T> FieldValue for Twhere
T: 'static,
impl<T> FieldValue for Twhere T: 'static,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<T> ScriptMessagePayload for Twhere
T: 'static + Send,
impl<T> ScriptMessagePayload for Twhere T: 'static + Send,
source§fn as_any_ref(&self) -> &(dyn Any + 'static)
fn as_any_ref(&self) -> &(dyn Any + 'static)
self as &dyn Anysource§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
self as &dyn Any§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.