glium/index/mod.rs
1/*!
2In order to draw, you need to provide a way for the video card to know how to link primitives
3together.
4
5There are eleven types of primitives, each one with a corresponding struct:
6
7 - `PointsList`
8 - `LinesList`
9 - `LinesListAdjacency`
10 - `LineStrip`
11 - `LineStripAdjacency`
12 - `TrianglesList`
13 - `TrianglesListAdjacency`
14 - `TriangleStrip`
15 - `TriangleStripAdjacency`
16 - `TriangleFan`
17 - `Patches`
18
19There are two ways to specify the indices that must be used:
20
21 - Passing a reference to an `IndexBuffer`, which contains a list of indices.
22 - `NoIndices`, in which case the vertices will be used in the order in which they are in the
23 vertex buffer.
24
25## Multidraw indirect
26
27In addition to indices, you can also use **multidraw indirect** rendering.
28
29The idea is to put a list of things to render in a buffer, and pass that buffer to OpenGL.
30
31*/
32use crate::gl;
33use crate::ToGlEnum;
34use crate::CapabilitiesSource;
35use crate::version::Api;
36use crate::version::Version;
37
38use std::mem;
39
40use crate::buffer::BufferAnySlice;
41
42pub use self::buffer::{IndexBuffer, IndexBufferSlice, IndexBufferAny};
43pub use self::buffer::CreationError as BufferCreationError;
44pub use self::multidraw::{DrawCommandsNoIndicesBuffer, DrawCommandNoIndices};
45pub use self::multidraw::{DrawCommandsIndicesBuffer, DrawCommandIndices};
46
47mod buffer;
48mod multidraw;
49
50/// Describes a source of indices used for drawing.
51#[derive(Clone)]
52pub enum IndicesSource<'a> {
53 /// A buffer uploaded in video memory.
54 IndexBuffer {
55 /// The buffer.
56 buffer: BufferAnySlice<'a>,
57 /// Type of indices in the buffer.
58 data_type: IndexType,
59 /// Type of primitives contained in the vertex source.
60 primitives: PrimitiveType,
61 },
62
63 /// Use a multidraw indirect buffer without indices.
64 MultidrawArray {
65 /// The buffer.
66 buffer: BufferAnySlice<'a>,
67 /// Type of primitives contained in the vertex source.
68 primitives: PrimitiveType,
69 },
70
71 /// Use a multidraw indirect buffer with indices.
72 MultidrawElement {
73 /// The buffer of the commands.
74 commands: BufferAnySlice<'a>,
75 /// The buffer of the indices.
76 indices: BufferAnySlice<'a>,
77 /// Type of indices in the buffer.
78 data_type: IndexType,
79 /// Type of primitives contained in the vertex source.
80 primitives: PrimitiveType,
81 },
82
83 /// Don't use indices. Assemble primitives by using the order in which the vertices are in
84 /// the vertices source.
85 NoIndices {
86 /// Type of primitives contained in the vertex source.
87 primitives: PrimitiveType,
88 },
89}
90
91impl<'a> IndicesSource<'a> {
92 /// Returns the type of the primitives.
93 #[inline]
94 pub fn get_primitives_type(&self) -> PrimitiveType {
95 *match self {
96 IndicesSource::IndexBuffer { primitives, .. } => primitives,
97 IndicesSource::MultidrawArray { primitives, .. } => primitives,
98 IndicesSource::MultidrawElement { primitives, .. } => primitives,
99 IndicesSource::NoIndices { primitives } => primitives,
100 }
101 }
102}
103
104/// List of available primitives.
105///
106/// See [this page for a visual representation of each primitive
107/// type](https://msdn.microsoft.com/en-us/library/windows/desktop/bb205124%28v=vs.85%29.aspx).
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum PrimitiveType {
110 /// Each vertex is an individual point.
111 Points,
112
113 /// Vertices are grouped by chunks of two vertices. Each chunk represents a line.
114 LinesList,
115
116 /// Vertices are grouped by chunks of four vertices. The second and third vertices of each
117 /// chunk represents the line.
118 ///
119 /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
120 /// there is any.
121 /// The first vertex represents the vertex adjacent to the second vertex. The fourth vertex
122 /// represents the vertex adjacent to the third vertex.
123 LinesListAdjacency,
124
125 /// Each vertex (except the last one) forms a line with the next vertex.
126 ///
127 /// For example vertices 0 and 1 form a line, vertices 1 and 2 form a line, vertices 2 and 3
128 /// form a line, etc.
129 LineStrip,
130
131 /// Similar to `LineStrip`, but with an additional vertex at the beginning and at the end
132 /// that represent the vertices adjacent to the first and last ones.
133 ///
134 /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
135 /// there is any.
136 LineStripAdjacency,
137
138 /// Each vertex forms a line with the next vertex. The last vertex form a line with the first
139 /// one.
140 LineLoop,
141
142 /// Vertices are grouped by chunks of three vertices. Each chunk represents a triangle.
143 ///
144 /// The order of the vertices is important, as it determines whether the triangle will be
145 /// clockwise or counter-clockwise. See `BackfaceCulling` for more infos.
146 TrianglesList,
147
148 /// Vertices are grouped by chunks of six vertices. The first, third and fifth vertices
149 /// represent a triangle.
150 ///
151 /// The order of the vertices is important, as it determines whether the triangle will be
152 /// clockwise or counter-clockwise. See `BackfaceCulling` for more infos.
153 ///
154 /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
155 /// there is any.
156 /// The second vertex represents the vertex adjacent to the first and third vertices. The
157 /// fourth vertex represents the vertex adjacent to the third and fifth vertices. The sixth
158 /// vertex represents the vertex adjacent to the first and fifth vertices.
159 TrianglesListAdjacency,
160
161 /// Each vertex (except the first one and the last one) forms a triangle with the previous
162 /// and the next vertices.
163 ///
164 /// For example vertices `0, 1, 2` form a triangle, `1, 2, 3` form a triangle, `2, 3, 4` form a
165 /// triangle, `3, 4, 5` form a triangle, etc.
166 ///
167 /// Each uneven triangle is reversed so that all triangles are facing the same
168 /// direction.
169 TriangleStrip,
170
171 /// Each even vertex forms a triangle with vertices `n+2` and `n+4`.
172 ///
173 /// Each uneven vertex is adjacent to the previous and next ones.
174 /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
175 /// there is any.
176 TriangleStripAdjacency,
177
178 /// Starting at the second vertex, each vertex forms a triangle with the next and the first
179 /// vertices.
180 ///
181 /// For example vertices `0, 1, 2` form a triangle, `0, 2, 3` form a triangle, `0, 3, 4` form a
182 /// triangle, `0, 4, 5` form a triangle, etc.
183 TriangleFan,
184
185 /// Vertices are grouped by chunks of `vertices_per_patch` vertices.
186 ///
187 /// This primitives type can only be used in conjunction with a tessellation shader. The
188 /// tessellation shader will indicate how each patch will be divided into lines or triangles.
189 Patches {
190 /// Number of vertices per patch.
191 vertices_per_patch: u16,
192 },
193}
194
195impl PrimitiveType {
196 /// Returns true if the backend supports this type of primitives.
197 pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
198 match self {
199 &PrimitiveType::Points | &PrimitiveType::LinesList | &PrimitiveType::LineStrip |
200 &PrimitiveType::LineLoop | &PrimitiveType::TrianglesList |
201 &PrimitiveType::TriangleStrip | &PrimitiveType::TriangleFan => true,
202
203 &PrimitiveType::LinesListAdjacency | &PrimitiveType::LineStripAdjacency |
204 &PrimitiveType::TrianglesListAdjacency | &PrimitiveType::TriangleStripAdjacency => {
205 caps.get_version() >= &Version(Api::Gl, 3, 0) ||
206 caps.get_extensions().gl_arb_geometry_shader4 ||
207 caps.get_extensions().gl_ext_geometry_shader4 ||
208 caps.get_extensions().gl_ext_geometry_shader
209 },
210
211 &PrimitiveType::Patches { .. } => {
212 caps.get_version() >= &Version(Api::Gl, 4, 0) ||
213 caps.get_extensions().gl_arb_tessellation_shader
214 },
215 }
216 }
217}
218
219impl ToGlEnum for PrimitiveType {
220 #[inline]
221 fn to_glenum(&self) -> gl::types::GLenum {
222 match self {
223 PrimitiveType::Points => gl::POINTS,
224 PrimitiveType::LinesList => gl::LINES,
225 PrimitiveType::LinesListAdjacency => gl::LINES_ADJACENCY,
226 PrimitiveType::LineStrip => gl::LINE_STRIP,
227 PrimitiveType::LineStripAdjacency => gl::LINE_STRIP_ADJACENCY,
228 PrimitiveType::LineLoop => gl::LINE_LOOP,
229 PrimitiveType::TrianglesList => gl::TRIANGLES,
230 PrimitiveType::TrianglesListAdjacency => gl::TRIANGLES_ADJACENCY,
231 PrimitiveType::TriangleStrip => gl::TRIANGLE_STRIP,
232 PrimitiveType::TriangleStripAdjacency => gl::TRIANGLE_STRIP_ADJACENCY,
233 PrimitiveType::TriangleFan => gl::TRIANGLE_FAN,
234 PrimitiveType::Patches { .. } => gl::PATCHES,
235 }
236 }
237}
238
239/// Marker that can be used as an indices source when you don't need indices.
240///
241/// If you use this, then the primitives will be constructed using the order in which the
242/// vertices are in the vertices sources.
243#[derive(Copy, Clone, Debug)]
244pub struct NoIndices(pub PrimitiveType);
245
246impl<'a> From<NoIndices> for IndicesSource<'a> {
247 #[inline]
248 fn from(marker: NoIndices) -> IndicesSource<'a> {
249 IndicesSource::NoIndices {
250 primitives: marker.0
251 }
252 }
253}
254
255impl<'a, 'b> From<&'b NoIndices> for IndicesSource<'a> {
256 #[inline]
257 fn from(marker: &'b NoIndices) -> IndicesSource<'a> {
258 IndicesSource::NoIndices {
259 primitives: marker.0
260 }
261 }
262}
263
264/// Type of the indices in an index source.
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266#[repr(u32)] // GLenum
267pub enum IndexType {
268 /// u8
269 U8 = gl::UNSIGNED_BYTE,
270 /// u16
271 U16 = gl::UNSIGNED_SHORT,
272 /// u32
273 U32 = gl::UNSIGNED_INT,
274}
275
276impl IndexType {
277 /// Returns the size in bytes of each index of this type.
278 #[inline]
279 pub fn get_size(&self) -> usize {
280 match self {
281 IndexType::U8 => mem::size_of::<u8>(),
282 IndexType::U16 => mem::size_of::<u16>(),
283 IndexType::U32 => mem::size_of::<u32>(),
284 }
285 }
286
287 /// Returns true if the backend supports this type of index.
288 #[inline]
289 pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
290 match self {
291 IndexType::U8 => true,
292 IndexType::U16 => true,
293 IndexType::U32 => {
294 caps.get_version() >= &Version(Api::Gl, 1, 0) ||
295 caps.get_version() >= &Version(Api::GlEs, 3, 0) ||
296 caps.get_extensions().gl_oes_element_index_uint
297 },
298 }
299 }
300}
301
302impl ToGlEnum for IndexType {
303 #[inline]
304 fn to_glenum(&self) -> gl::types::GLenum {
305 *self as gl::types::GLenum
306 }
307}
308
309/// An index from the index buffer.
310pub unsafe trait Index: Copy + Send + 'static {
311 /// Returns the `IndexType` corresponding to this type.
312 fn get_type() -> IndexType;
313
314 /// Returns true if this type of index is supported by the backend.
315 fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
316 Self::get_type().is_supported(caps)
317 }
318}
319
320unsafe impl Index for u8 {
321 #[inline]
322 fn get_type() -> IndexType {
323 IndexType::U8
324 }
325}
326
327unsafe impl Index for u16 {
328 #[inline]
329 fn get_type() -> IndexType {
330 IndexType::U16
331 }
332}
333
334unsafe impl Index for u32 {
335 #[inline]
336 fn get_type() -> IndexType {
337 IndexType::U32
338 }
339}