glium/vertex/
mod.rs

1/*!
2Contains everything related to vertex sources.
3
4When you draw, you need to pass one or several sources of vertex attributes. This is done with
5the first parameter to the `draw` function.
6
7## Vertex
8
9The main trait of this module is `Vertex`, which must be implemented on structs whose instances
10describe individual vertices. The trait is unsafe to implement, so you are encouraged to use the
11`implement_vertex!` macro instead:
12
13```
14# #[macro_use]
15# extern crate glium;
16# extern crate glutin;
17# fn main() {
18#[derive(Copy, Clone)]
19struct MyVertex {
20    position: [f32; 3],
21    texcoords: [f32; 2],
22}
23
24// you must pass the list of members to the macro
25implement_vertex!(MyVertex, position, texcoords);
26# }
27```
28
29## Vertex buffer
30
31Once you have a struct that implements the `Vertex` trait, you can build an array of vertices and
32upload it to the video memory by creating a `VertexBuffer`.
33
34```no_run
35# use glutin::surface::{ResizeableSurface, SurfaceTypeTrait};
36# fn example<T>(display: glium::Display<T>) where T: SurfaceTypeTrait + ResizeableSurface {
37# #[derive(Copy, Clone)]
38# struct MyVertex {
39#     position: [f32; 3],
40#     texcoords: [f32; 2],
41# }
42# impl glium::vertex::Vertex for MyVertex {
43#     fn build_bindings() -> glium::vertex::VertexFormat { unimplemented!() }
44# }
45let data = &[
46    MyVertex {
47        position: [0.0, 0.0, 0.4],
48        texcoords: [0.0, 1.0]
49    },
50    MyVertex {
51        position: [12.0, 4.5, -1.8],
52        texcoords: [1.0, 0.5]
53    },
54    MyVertex {
55        position: [-7.124, 0.1, 0.0],
56        texcoords: [0.0, 0.4]
57    },
58];
59
60let vertex_buffer = glium::vertex::VertexBuffer::new(&display, data);
61# }
62```
63
64## Drawing
65
66When you draw, you can pass either a single vertex source or a tuple of multiple sources.
67Each source can be:
68
69 - A reference to a `VertexBuffer`.
70 - A slice of a vertex buffer, by calling `vertex_buffer.slice(start .. end).unwrap()`.
71 - A vertex buffer where each element corresponds to an instance, by
72   calling `vertex_buffer.per_instance()`.
73 - The same with a slice, by calling `vertex_buffer.slice(start .. end).unwrap().per_instance()`.
74 - A marker indicating a number of vertex sources, with `glium::vertex::EmptyVertexAttributes`.
75 - A marker indicating a number of instances, with `glium::vertex::EmptyInstanceAttributes`.
76
77```no_run
78# use glium::Surface;
79# use glutin::surface::{ResizeableSurface, SurfaceTypeTrait};
80# fn example<T, V>(display: glium::Display<T>, program: glium::program::Program,
81#            vertex_buffer: glium::vertex::VertexBuffer<V>, vertex_buffer2: glium::vertex::VertexBuffer<V>)
82#     where T: SurfaceTypeTrait + ResizeableSurface, V: glium::vertex::Vertex {
83# let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
84# let uniforms = glium::uniforms::EmptyUniforms;
85# let mut frame = display.draw();
86// drawing with a single vertex buffer
87frame.draw(&vertex_buffer, &indices, &program, &uniforms, &Default::default()).unwrap();
88
89// drawing with two parallel vertex buffers
90frame.draw((&vertex_buffer, &vertex_buffer2), &indices, &program,
91           &uniforms, &Default::default()).unwrap();
92
93// drawing without a vertex source
94frame.draw(glium::vertex::EmptyVertexAttributes { len: 12 }, &indices, &program,
95           &uniforms, &Default::default()).unwrap();
96
97// drawing a slice of a vertex buffer
98frame.draw(vertex_buffer.slice(6 .. 24).unwrap(), &indices, &program,
99           &uniforms, &Default::default()).unwrap();
100
101// drawing slices of two vertex buffers
102frame.draw((vertex_buffer.slice(6 .. 24).unwrap(), vertex_buffer2.slice(128 .. 146).unwrap()),
103           &indices, &program, &uniforms, &Default::default()).unwrap();
104
105// treating `vertex_buffer2` as a source of attributes per-instance instead of per-vertex
106frame.draw((&vertex_buffer, vertex_buffer2.per_instance().unwrap()), &indices,
107           &program, &uniforms, &Default::default()).unwrap();
108
109// instancing without any per-instance attribute
110frame.draw((&vertex_buffer, glium::vertex::EmptyInstanceAttributes { len: 36 }), &indices,
111           &program, &uniforms, &Default::default()).unwrap();
112# }
113```
114
115Note that if you use `index::EmptyIndices` as indices the length of all vertex sources must
116be the same, or a `DrawError::VerticesSourcesLengthMismatch` will be produced.
117
118In all situation, the length of all per-instance sources must match, or
119`DrawError::InstancesCountMismatch` will be returned.
120
121# Transform feedback
122
123Transform feedback allows you to write in a buffer the list of primitives that are generated by
124the GPU.
125
126To use it, you must first create a `TransformFeedbackSession` with
127`TransformFeedbackSession::new()`. This function requires you to pass a buffer of the correct
128type and a program. Then you must pass the `&TransformFeedbackSession` to the draw parameters.
129The program you use when drawing must be the same as you the one you created the session
130with, or else you will get an error.
131
132*/
133use std::iter::Chain;
134use std::option::IntoIter;
135
136pub use self::buffer::{VertexBuffer, VertexBufferAny};
137pub use self::buffer::VertexBufferSlice;
138pub use self::buffer::CreationError as BufferCreationError;
139pub use self::format::{AttributeType, VertexFormat};
140pub use self::transform_feedback::{is_transform_feedback_supported, TransformFeedbackSession};
141
142use crate::buffer::BufferAnySlice;
143use crate::CapabilitiesSource;
144
145mod buffer;
146mod format;
147mod transform_feedback;
148
149/// Describes the source to use for the vertices when drawing.
150#[derive(Clone)]
151pub enum VerticesSource<'a> {
152    /// A buffer uploaded in the video memory.
153    ///
154    /// The second parameter is the number of vertices in the buffer.
155    ///
156    /// The third parameter tells whether or not this buffer is "per instance" (true) or
157    /// "per vertex" (false).
158    VertexBuffer(BufferAnySlice<'a>, VertexFormat, bool),
159
160    /// A marker indicating a "phantom list of attributes".
161    Marker {
162        /// Number of attributes.
163        len: usize,
164
165        /// Whether or not this buffer is "per instance" (true) or "per vertex" (false).
166        per_instance: bool,
167    },
168}
169
170/// Marker that can be passed instead of a buffer to indicate an empty list of buffers.
171pub struct EmptyVertexAttributes {
172    /// Number of phantom vertices.
173    pub len: usize,
174}
175
176impl<'a> From<EmptyVertexAttributes> for VerticesSource<'a> {
177    #[inline]
178    fn from(this: EmptyVertexAttributes) -> VerticesSource<'a> {
179        VerticesSource::Marker { len: this.len, per_instance: false }
180    }
181}
182
183/// Marker that can be passed instead of a buffer to indicate an empty list of buffers.
184pub struct EmptyInstanceAttributes {
185    /// Number of phantom vertices.
186    pub len: usize,
187}
188
189impl<'a> From<EmptyInstanceAttributes> for VerticesSource<'a> {
190    #[inline]
191    fn from(this: EmptyInstanceAttributes) -> VerticesSource<'a> {
192        VerticesSource::Marker { len: this.len, per_instance: true }
193    }
194}
195
196/// Marker that instructs glium that the buffer is to be used per instance.
197pub struct PerInstance<'a>(BufferAnySlice<'a>, VertexFormat);
198
199impl<'a> From<PerInstance<'a>> for VerticesSource<'a> {
200    #[inline]
201    fn from(this: PerInstance<'a>) -> VerticesSource<'a> {
202        VerticesSource::VertexBuffer(this.0, this.1, true)
203    }
204}
205
206/// Objects that describe multiple vertex sources.
207pub trait MultiVerticesSource<'a> {
208    /// Iterator that enumerates each source.
209    type Iterator: Iterator<Item = VerticesSource<'a>>;
210
211    /// Iterates over the `VerticesSource`.
212    fn iter(self) -> Self::Iterator;
213}
214
215impl<'a, T> MultiVerticesSource<'a> for T
216    where T: Into<VerticesSource<'a>>
217{
218    type Iterator = IntoIter<VerticesSource<'a>>;
219
220    #[inline]
221    fn iter(self) -> IntoIter<VerticesSource<'a>> {
222        Some(self.into()).into_iter()
223    }
224}
225
226macro_rules! impl_for_tuple {
227    ($t:ident) => (
228        impl<'a, $t> MultiVerticesSource<'a> for ($t,)
229            where $t: Into<VerticesSource<'a>>
230        {
231            type Iterator = IntoIter<VerticesSource<'a>>;
232
233            #[inline]
234            fn iter(self) -> IntoIter<VerticesSource<'a>> {
235                Some(self.0.into()).into_iter()
236            }
237        }
238    );
239
240    ($t1:ident, $t2:ident) => (
241        #[allow(non_snake_case)]
242        impl<'a, $t1, $t2> MultiVerticesSource<'a> for ($t1, $t2)
243            where $t1: Into<VerticesSource<'a>>, $t2: Into<VerticesSource<'a>>
244        {
245            type Iterator = Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
246                                  <($t2,) as MultiVerticesSource<'a>>::Iterator>;
247
248            #[inline]
249            fn iter(self) -> Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
250                                   <($t2,) as MultiVerticesSource<'a>>::Iterator>
251            {
252                let ($t1, $t2) = self;
253                Some($t1.into()).into_iter().chain(($t2,).iter())
254            }
255        }
256
257        impl_for_tuple!($t2);
258    );
259
260    ($t1:ident, $($t2:ident),+) => (
261        #[allow(non_snake_case)]
262        impl<'a, $t1, $($t2),+> MultiVerticesSource<'a> for ($t1, $($t2),+)
263            where $t1: Into<VerticesSource<'a>>, $($t2: Into<VerticesSource<'a>>),+
264        {
265            type Iterator = Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
266                                  <($($t2),+) as MultiVerticesSource<'a>>::Iterator>;
267
268            #[inline]
269            fn iter(self) -> Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
270                                  <($($t2),+) as MultiVerticesSource<'a>>::Iterator>
271            {
272                let ($t1, $($t2),+) = self;
273                Some($t1.into()).into_iter().chain(($($t2),+).iter())
274            }
275        }
276
277        impl_for_tuple!($($t2),+);
278    );
279}
280
281impl_for_tuple!(A, B, C, D, E, F, G);
282
283/// Trait for structures that represent a vertex.
284///
285/// Instead of implementing this trait yourself, it is recommended to use the `implement_vertex!`
286/// macro instead.
287// TODO: this should be `unsafe`, but that would break the syntax extension
288pub trait Vertex: Copy + Sized {
289    /// Builds the `VertexFormat` representing the layout of this element.
290    fn build_bindings() -> VertexFormat;
291
292    /// Returns true if the backend supports this vertex format.
293    fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
294        let format = Self::build_bindings();
295
296        for &(_, _, _, ref ty, _) in format.iter() {
297            if !ty.is_supported(caps) {
298                return false;
299            }
300        }
301
302        true
303    }
304}
305
306/// Trait for types that can be used as vertex attributes.
307pub unsafe trait Attribute: Sized {
308    /// The type of data.
309    const TYPE: AttributeType;
310
311    #[inline]
312    /// Get the type of data.
313    fn get_type() -> AttributeType {
314        Self::TYPE
315    }
316
317    /// Returns true if the backend supports this type of attribute.
318    #[inline]
319    fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
320        Self::get_type().is_supported(caps)
321    }
322}