appy/utils/array_buffer.rs
1use crate::gl;
2
3/// Abstraction for an OpenGL array buffer.
4///
5/// This array buffer can hold a number of floating point components.
6/// It is set as a flat array, but should be thought of as a two
7/// dimensional array. The number of components is the number of
8/// columns in the array. The array buffer can be bound to several
9/// attribute locations, with each attribute location using one or
10/// more components.
11pub struct ArrayBuffer {
12 vao: gl::types::GLuint,
13 vbo: gl::types::GLuint,
14 components: u32,
15 len: usize,
16}
17
18impl ArrayBuffer {
19 /// Create an [`ArrayBuffer`] with a specified number of components.
20 pub fn new(components: u32) -> Self {
21 let mut vao: gl::types::GLuint = 0;
22 unsafe {
23 gl::GenVertexArrays(1, &mut vao);
24 gl::BindVertexArray(vao);
25 }
26
27 let mut vbo: gl::types::GLuint = 0;
28 unsafe {
29 gl::GenBuffers(1, &mut vbo);
30 }
31
32 Self {
33 vao,
34 vbo,
35 components,
36 len: 0,
37 }
38 }
39
40 /// Get the number of items in the array.
41 pub fn len(&self) -> usize {
42 self.len
43 }
44
45 /*pub fn is_empty(&self) -> bool {
46 self.len == 0
47 }*/
48
49 /// Set data.
50 ///
51 /// The vertices array is a flat array, but should be thought of
52 /// as a two dimensional array. The length of the [`ArrayBuffer`] will
53 /// be the lenght of the array divided by the number of components.
54 pub fn set_data(&mut self, vertices: Vec<f32>) {
55 self.len = vertices.len() / self.components as usize;
56
57 unsafe {
58 gl::BindVertexArray(self.vao);
59 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
60 gl::BufferData(
61 gl::ARRAY_BUFFER, // target
62 (vertices.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
63 vertices.as_ptr() as *const gl::types::GLvoid, // pointer to data
64 gl::STATIC_DRAW, // usage
65 );
66 }
67 }
68
69 /// Bind array buffer to an attribute location.
70 ///
71 /// The `offs` parameter specifies the first component to bind, and `num`
72 /// specifies the number of compontns to bind.
73 pub fn bind(&self, attrib_location: i32, offs: usize, num: u32) {
74 unsafe {
75 gl::BindVertexArray(self.vao);
76 gl::EnableVertexAttribArray(attrib_location as u32); // this is "layout (location = 0)" in vertex shader
77 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
78 gl::VertexAttribPointer(
79 attrib_location as u32, // index of the generic vertex attribute ("layout (location = 0)")
80 num as i32, // the number of components per generic vertex attribute
81 gl::FLOAT, // data type
82 gl::FALSE, // normalized (int-to-float conversion)
83 ((self.components as usize) * std::mem::size_of::<f32>()) as gl::types::GLint, // stride (byte offset between consecutive attributes)
84 (offs * std::mem::size_of::<f32>()) as *const _, // offset of the first component
85 );
86 }
87 }
88}