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}