You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 line
5.3 KiB

  1. use crate::{
  2. array_buffer::ArrayBuffer,
  3. error::Error,
  4. misc::{AsEnum, BindGuard, Bindable},
  5. };
  6. /* VertexArray */
  7. pub struct VertexArray {
  8. id: gl::GLuint,
  9. buffers: Vec<ArrayBuffer>,
  10. }
  11. impl VertexArray {
  12. pub fn builder() -> Builder {
  13. Builder::default()
  14. }
  15. pub fn buffers(&self) -> &Vec<ArrayBuffer> {
  16. &self.buffers
  17. }
  18. pub fn buffers_mut(&mut self) -> &mut Vec<ArrayBuffer> {
  19. &mut self.buffers
  20. }
  21. }
  22. impl Drop for VertexArray {
  23. fn drop(&mut self) {
  24. gl::delete_vertex_arrays(1, &self.id);
  25. }
  26. }
  27. impl Bindable for VertexArray {
  28. fn bind(&self) {
  29. gl::bind_vertex_array(self.id);
  30. }
  31. fn unbind(&self) {
  32. gl::bind_vertex_array(0);
  33. }
  34. }
  35. /* Builder */
  36. #[derive(Default)]
  37. pub struct Builder {
  38. bindings: Vec<Binding>,
  39. }
  40. impl Builder {
  41. pub fn bind_buffer(mut self, buffer: ArrayBuffer) -> BindingBuilder {
  42. let binding = Binding {
  43. buffer,
  44. pointers: Vec::new(),
  45. };
  46. self.bindings.push(binding);
  47. BindingBuilder { builder: self }
  48. }
  49. pub fn build(self) -> Result<VertexArray, Error> {
  50. let mut id = 0;
  51. Error::checked(|| gl::create_vertex_arrays(1, &mut id))?;
  52. let mut vertex_array = VertexArray {
  53. id,
  54. buffers: Vec::new(),
  55. };
  56. let guard = BindGuard::new(&vertex_array);
  57. let mut buffers = Vec::new();
  58. for binding in self.bindings {
  59. let guard = BindGuard::new(&binding.buffer);
  60. for pointer in binding.pointers {
  61. Error::checked(|| gl::enable_vertex_attrib_array(pointer.index))?;
  62. Error::checked(|| {
  63. gl::vertex_attrib_pointer(
  64. pointer.index,
  65. pointer.size,
  66. pointer.type_.as_enum(),
  67. if pointer.normalize {
  68. gl::TRUE
  69. } else {
  70. gl::FALSE
  71. },
  72. pointer.stride,
  73. pointer.offset as *const _,
  74. )
  75. })?;
  76. if let Some(divisor) = pointer.divisor {
  77. Error::checked(|| gl::vertex_attrib_divisor(pointer.index, divisor))?;
  78. }
  79. }
  80. drop(guard);
  81. buffers.push(binding.buffer);
  82. }
  83. drop(guard);
  84. vertex_array.buffers = buffers;
  85. Ok(vertex_array)
  86. }
  87. }
  88. /* BindingBuilder */
  89. pub struct BindingBuilder {
  90. builder: Builder,
  91. }
  92. impl BindingBuilder {
  93. pub fn bind_buffer(self, buffer: ArrayBuffer) -> Self {
  94. self.builder.bind_buffer(buffer)
  95. }
  96. pub fn vertex_attrib_pointer(
  97. mut self,
  98. index: gl::GLuint,
  99. size: gl::GLint,
  100. type_: DataType,
  101. normalize: bool,
  102. stride: gl::GLsizei,
  103. offset: gl::GLsizei,
  104. ) -> Result<Self, Error> {
  105. for binding in &self.builder.bindings {
  106. for pointer in &binding.pointers {
  107. if pointer.index == index {
  108. return Err(Error::VertexArrayIndexAlreadyInUse(index));
  109. }
  110. }
  111. }
  112. let pointer = Pointer {
  113. index,
  114. size,
  115. type_,
  116. normalize,
  117. stride,
  118. offset,
  119. divisor: None,
  120. };
  121. self.builder
  122. .bindings
  123. .last_mut()
  124. .unwrap()
  125. .pointers
  126. .push(pointer);
  127. Ok(self)
  128. }
  129. pub fn vertex_attrib_divisor(mut self, divisor: gl::GLuint) -> Result<Self, Error> {
  130. let binding = self.builder.bindings.last_mut().unwrap();
  131. let pointer = binding
  132. .pointers
  133. .last_mut()
  134. .ok_or(Error::VertexArrayExpectedPointer)?;
  135. pointer.divisor = Some(divisor);
  136. Ok(self)
  137. }
  138. pub fn build(self) -> Result<VertexArray, Error> {
  139. self.builder.build()
  140. }
  141. }
  142. /* DataType */
  143. #[allow(non_camel_case_types)]
  144. pub enum DataType {
  145. Byte,
  146. UnsignedByte,
  147. Short,
  148. UnsignedShort,
  149. Int,
  150. UnsignedInt,
  151. HalfFloat,
  152. Float,
  153. Double,
  154. Fixed,
  155. Int_2_10_10_10_Rev,
  156. UnsignedInt_2_10_10_10_Rev,
  157. UnsignedInt_10f_11f_11f_Rev,
  158. }
  159. impl AsEnum for DataType {
  160. fn as_enum(&self) -> gl::GLenum {
  161. match self {
  162. Self::Byte => gl::BYTE,
  163. Self::UnsignedByte => gl::UNSIGNED_BYTE,
  164. Self::Short => gl::SHORT,
  165. Self::UnsignedShort => gl::UNSIGNED_SHORT,
  166. Self::Int => gl::INT,
  167. Self::UnsignedInt => gl::UNSIGNED_INT,
  168. Self::HalfFloat => gl::HALF_FLOAT,
  169. Self::Float => gl::FLOAT,
  170. Self::Double => gl::DOUBLE,
  171. Self::Fixed => gl::FIXED,
  172. Self::Int_2_10_10_10_Rev => gl::INT_2_10_10_10_REV,
  173. Self::UnsignedInt_2_10_10_10_Rev => gl::UNSIGNED_INT_2_10_10_10_REV,
  174. Self::UnsignedInt_10f_11f_11f_Rev => gl::UNSIGNED_INT_10F_11F_11F_REV,
  175. }
  176. }
  177. }
  178. /* Binding */
  179. struct Binding {
  180. buffer: ArrayBuffer,
  181. pointers: Vec<Pointer>,
  182. }
  183. /* Pointer */
  184. struct Pointer {
  185. index: gl::GLuint,
  186. size: gl::GLint,
  187. type_: DataType,
  188. normalize: bool,
  189. stride: gl::GLsizei,
  190. offset: gl::GLsizei,
  191. divisor: Option<gl::GLuint>,
  192. }