fyrox_graphics/geometry_buffer.rs
1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Geometry buffer is a mesh buffer, that could contain multiple vertex buffers and only one
22//! element buffer.
23
24#![warn(missing_docs)]
25
26use crate::{
27 buffer::BufferUsage,
28 core::{array_as_u8_slice, math::TriangleDefinition},
29 define_shared_wrapper, ElementKind,
30};
31use bytemuck::Pod;
32use fyrox_core::define_as_any_trait;
33use std::mem::size_of;
34
35/// Attribute kind of a vertex.
36#[derive(Copy, Clone)]
37#[allow(dead_code)]
38pub enum AttributeKind {
39 /// Floating point 32-bit number.
40 Float,
41 /// Integer unsigned 8-bit number.
42 UnsignedByte,
43 /// Integer unsigned 16-bit number.
44 UnsignedShort,
45 /// Integer unsigned 32-bit number.
46 UnsignedInt,
47}
48
49/// Vertex attribute definition.
50pub struct AttributeDefinition {
51 /// Binding point of the vertex attribute.
52 pub location: u32,
53 /// Vertex attribute kind. See [`AttributeKind`] docs for more info.
54 pub kind: AttributeKind,
55 /// Component count in the vertex. This could be 1,2,3 or 4.
56 pub component_count: usize,
57 /// A flag, that defines whether the attribute is normalized or not. Normalized attributes
58 /// are always real numbers in `[-1.0; 1.0]` range (or `[0.0; 1.0]` for unsigned attributes).
59 pub normalized: bool,
60 /// Defines feed rate of the vertex attribute. 0 - means that the attribute will be unique per
61 /// vertex, 1 - per each drawn instance, 2 - per two instances and so on.
62 pub divisor: u32,
63}
64
65impl AttributeKind {
66 /// Returns attribute size in bytes.
67 pub fn size(self) -> usize {
68 match self {
69 AttributeKind::Float => size_of::<f32>(),
70 AttributeKind::UnsignedByte => size_of::<u8>(),
71 AttributeKind::UnsignedShort => size_of::<u16>(),
72 AttributeKind::UnsignedInt => size_of::<u32>(),
73 }
74 }
75}
76
77/// Untyped vertex buffer data.
78pub struct VertexBufferData<'a> {
79 /// Vertex size.
80 pub element_size: usize,
81 /// Vertex buffer data.
82 pub bytes: Option<&'a [u8]>,
83}
84
85impl<'a> VertexBufferData<'a> {
86 /// Creates a new untyped vertex buffer data from a typed slice. Underlying type must implement
87 /// [`Pod`] trait!
88 pub fn new<T: Pod>(vertices: Option<&'a [T]>) -> Self {
89 Self {
90 element_size: size_of::<T>(),
91 bytes: vertices.map(|v| array_as_u8_slice(v)),
92 }
93 }
94}
95
96/// Vertex buffer descriptor contains information about vertex buffer layout and content usage as
97/// well as the data that will be uploaded to GPU.
98pub struct VertexBufferDescriptor<'a> {
99 /// Vertex buffer usage. See [`BufferUsage`] docs for more info.
100 pub usage: BufferUsage,
101 /// Attributes of the vertex buffer.
102 pub attributes: &'a [AttributeDefinition],
103 /// Data of the vertex buffer. See [`VertexBufferData`] docs for more info.
104 pub data: VertexBufferData<'a>,
105}
106
107/// Describes elements for the geometry buffer.
108pub enum ElementsDescriptor<'a> {
109 /// Triangles are formed by a triple of vertex indices.
110 Triangles(&'a [TriangleDefinition]),
111 /// Lines are formed by a pair of vertex indices.
112 Lines(&'a [[u32; 2]]),
113 /// Points are just straight vertex indices.
114 Points(&'a [u32]),
115}
116
117impl ElementsDescriptor<'_> {
118 /// Returns element kind of the elements' descriptor.
119 pub fn element_kind(&self) -> ElementKind {
120 match self {
121 ElementsDescriptor::Triangles(_) => ElementKind::Triangle,
122 ElementsDescriptor::Lines(_) => ElementKind::Line,
123 ElementsDescriptor::Points(_) => ElementKind::Point,
124 }
125 }
126}
127
128/// Descriptor of the geometry buffer. It essentially binds multiple vertex buffers and one element
129/// buffer.
130pub struct GpuGeometryBufferDescriptor<'a> {
131 /// Name of the geometry buffer. Used only for debugging purposes.
132 pub name: &'a str,
133 /// Vertex buffers of the buffer. There must be at least one vertex buffer.
134 pub buffers: &'a [VertexBufferDescriptor<'a>],
135 /// Usage of the geometry buffer. See [`BufferUsage`] docs for more info.
136 pub usage: BufferUsage,
137 /// Elements of the geometry buffer.
138 pub elements: ElementsDescriptor<'a>,
139}
140
141define_as_any_trait!(GpuGeometryBufferAsAny => GpuGeometryBufferTrait);
142
143/// Geometry buffer is a mesh buffer, that could contain multiple vertex buffers and only one
144/// element buffer. Element could be either a line or triangle (the most commonly used one).
145///
146/// ## Examples
147///
148/// The simplest possible example shows how to create a geometry buffer that has a single triangle:
149///
150/// ```rust
151/// use fyrox_graphics::{
152/// buffer::BufferUsage,
153/// core::{algebra::Vector3, math::TriangleDefinition},
154/// error::FrameworkError,
155/// geometry_buffer::{
156/// AttributeDefinition, AttributeKind, ElementsDescriptor, GpuGeometryBuffer,
157/// GpuGeometryBufferDescriptor, VertexBufferData, VertexBufferDescriptor,
158/// },
159/// server::GraphicsServer,
160/// };
161/// use bytemuck::{Pod, Zeroable};
162///
163/// // Vertex type must implement a bunch of traits, that guarantees that the data will be tightly
164/// // packed with expected order of elements.
165/// #[derive(Pod, Copy, Clone, Zeroable)]
166/// #[repr(C)]
167/// struct Vertex {
168/// position: Vector3<f32>,
169/// }
170///
171/// fn create_geometry_buffer(
172/// server: &dyn GraphicsServer,
173/// ) -> Result<GpuGeometryBuffer, FrameworkError> {
174/// let vertices = [
175/// Vertex {
176/// position: Vector3::new(0.0, 0.0, 0.0),
177/// },
178/// Vertex {
179/// position: Vector3::new(0.0, 1.0, 0.0),
180/// },
181/// Vertex {
182/// position: Vector3::new(1.0, 0.0, 0.0),
183/// },
184/// ];
185///
186/// let triangles = [TriangleDefinition([0, 1, 2])];
187///
188/// server.create_geometry_buffer(GpuGeometryBufferDescriptor {
189/// name: "MyBuffer",
190/// buffers: &[VertexBufferDescriptor {
191/// usage: BufferUsage::StaticDraw,
192/// attributes: &[AttributeDefinition {
193/// location: 0,
194/// kind: AttributeKind::Float,
195/// component_count: 3,
196/// normalized: false,
197/// divisor: 0,
198/// }],
199/// data: VertexBufferData::new(Some(&vertices)),
200/// }],
201/// usage: BufferUsage::StaticDraw,
202/// elements: ElementsDescriptor::Triangles(&triangles),
203/// })
204/// }
205/// ```
206pub trait GpuGeometryBufferTrait: GpuGeometryBufferAsAny {
207 /// Write untyped data to a vertex buffer with the given index.
208 fn set_buffer_data(&self, buffer: usize, data: &[u8]);
209
210 /// Returns total number of elements in the geometry buffer.
211 fn element_count(&self) -> usize;
212
213 /// Writes triangles to the buffer. Each triangle definition contains triangle indices, that
214 /// forms the triangle.
215 fn set_triangles(&self, triangles: &[TriangleDefinition]);
216
217 /// Writes lines to the buffer. Each pair defines starting and ending vertex index of the line.
218 fn set_lines(&self, lines: &[[u32; 2]]);
219
220 /// Writes points to the buffer. Each index in the slice defines vertex index.
221 fn set_points(&self, points: &[u32]);
222}
223
224impl dyn GpuGeometryBufferTrait {
225 /// Writes a typed data to a vertex buffer with the given index. Underlying type must implement
226 /// [`Pod`] trait!
227 pub fn set_buffer_data_of_type<T: Pod>(&self, buffer: usize, data: &[T]) {
228 self.set_buffer_data(buffer, array_as_u8_slice(data))
229 }
230}
231
232define_shared_wrapper!(GpuGeometryBuffer<dyn GpuGeometryBufferTrait>);