maia_wasm/render/engine/
vao.rs1use crate::array_view::ArrayView;
2use std::rc::Rc;
3use wasm_bindgen::prelude::*;
4use web_sys::{WebGl2RenderingContext, WebGlBuffer, WebGlProgram, WebGlVertexArrayObject};
5
6use super::RenderEngine;
7
8pub struct VaoBuilder<'a> {
13 engine: &'a mut RenderEngine,
14 vao: Rc<WebGlVertexArrayObject>,
15}
16
17impl VaoBuilder<'_> {
18 pub(super) fn new(engine: &mut RenderEngine) -> Result<VaoBuilder<'_>, JsValue> {
19 let vao = Rc::new(
20 engine
21 .gl
22 .create_vertex_array()
23 .ok_or("failed to create VAO")?,
24 );
25 Ok(Self::modify_vao(engine, vao))
26 }
27
28 pub(super) fn modify_vao(
29 engine: &mut RenderEngine,
30 vao: Rc<WebGlVertexArrayObject>,
31 ) -> VaoBuilder<'_> {
32 engine.bind_vertex_array(&vao);
33 VaoBuilder { engine, vao }
34 }
35
36 pub fn create_array_buffer<T: ArrayView>(
42 self,
43 program: &WebGlProgram,
44 attribute: &str,
45 size: i32,
46 contents: &[T],
47 ) -> Result<Self, JsValue> {
48 let attribute_location = match self.engine.gl.get_attrib_location(program, attribute) {
49 x if x >= 0 => Ok(x as u32),
50 _ => Err("failed to get attribute location"),
51 }?;
52 self.engine
53 .gl
54 .enable_vertex_attrib_array(attribute_location);
55 self.create_and_fill_buffer(WebGl2RenderingContext::ARRAY_BUFFER, contents)?;
56 let normalized = false;
57 let stride = 0;
58 let offset = 0;
59 self.engine.gl.vertex_attrib_pointer_with_i32(
60 attribute_location,
61 size,
62 T::GL_TYPE,
63 normalized,
64 stride,
65 offset,
66 );
67 Ok(self)
68 }
69
70 pub fn create_element_array_buffer(self, contents: &[u16]) -> Result<Self, JsValue> {
75 self.create_and_fill_buffer(WebGl2RenderingContext::ELEMENT_ARRAY_BUFFER, contents)?;
76 Ok(self)
77 }
78
79 fn create_and_fill_buffer<T: ArrayView>(
80 &self,
81 target: u32,
82 contents: &[T],
83 ) -> Result<WebGlBuffer, JsValue> {
84 let buffer = self
85 .engine
86 .gl
87 .create_buffer()
88 .ok_or("failed to create_buffer")?;
89 self.engine.gl.bind_buffer(target, Some(&buffer));
90 unsafe {
91 let view = T::view(contents);
92 self.engine.gl.buffer_data_with_array_buffer_view(
93 target,
94 &view,
95 WebGl2RenderingContext::STATIC_DRAW,
96 );
97 }
98 Ok(buffer)
99 }
100
101 pub fn build(self) -> Rc<WebGlVertexArrayObject> {
105 self.vao
106 }
107}