j_webgl/structs/renderable/
cube.rs

1use super::*;
2
3struct Inner {
4  program: web_sys::WebGlProgram,
5  vao: web_sys::WebGlVertexArrayObject,
6  matrix_location: web_sys::WebGlUniformLocation,
7}
8
9#[wasm_bindgen::prelude::wasm_bindgen]
10#[derive(Default)]
11pub struct Cube {
12  inner: std::cell::RefCell<Option<Inner>>,
13}
14
15#[wasm_bindgen::prelude::wasm_bindgen]
16impl Cube {
17  pub fn new() -> Result<Cube> {
18    Ok(Cube { inner: std::cell::RefCell::new(None), })
19  }
20}
21
22impl traits::Renderable for Cube {
23  fn render(
24    &self,
25    context: &web_sys::WebGl2RenderingContext,
26    camera: &[f32],
27  ) -> Result<()>
28  {
29    if self.inner.borrow().is_none() {
30      let program = utils::compile_program(
31        context,
32        shaders::vertex::position_matrix()?, // VERTEX_SHADER_SOURCE,
33        shaders::fragment::color()?, // FRAGMENT_SHADER_SOURCE,
34      )?;
35
36      let position_attribute_location = context
37          .get_attrib_location(&program, "a_position");
38      let matrix_location = context
39          .get_uniform_location(&program, "u_matrix");
40      let color_location = context.get_uniform_location(&program, "u_color");
41
42      let position_buffer = context.create_buffer().unwrap();
43
44      let vao = context.create_vertex_array().unwrap();
45      context.bind_vertex_array(Some(&vao));
46
47      context.enable_vertex_attrib_array(position_attribute_location as u32);
48      context.bind_buffer(web_sys::WebGl2RenderingContext::ARRAY_BUFFER, Some(&position_buffer));
49      let vertices: [f32; 24] = [
50            // Front face
51            -0.5, -0.5,  0.5,  // 0: bottom-left-front
52             0.5, -0.5,  0.5,  // 1: bottom-right-front
53             0.5,  0.5,  0.5,  // 2: top-right-front
54            -0.5,  0.5,  0.5,  // 3: top-left-front
55            // Back face
56            -0.5, -0.5, -0.5,  // 4: bottom-left-back
57             0.5, -0.5, -0.5,  // 5: bottom-right-back
58             0.5,  0.5, -0.5,  // 6: top-right-back
59            -0.5,  0.5, -0.5,  // 7: top-left-back
60      ];
61
62      // Cube indices: 12 triangles (2 per face) = 36 indices
63      let indices: [usize; 36] = [
64            // Front face
65            0, 1, 2,  2, 3, 0,
66            // Back face
67            4, 6, 5,  6, 4, 7,
68            // Top face
69            3, 2, 6,  6, 7, 3,
70            // Bottom face
71            0, 4, 5,  5, 1, 0,
72            // Right face
73            1, 5, 6,  6, 2, 1,
74            // Left face
75            0, 3, 7,  7, 4, 0,
76      ];
77      let array: Vec<f32> = indices.iter()
78      .fold(Vec::new(), |mut a, i| {
79          a.push(vertices[*i*3]);
80          a.push(vertices[*i*3+1]);
81          a.push(vertices[*i*3+2]);
82          a
83      });
84
85      unsafe {
86          let vertices_array = js_sys::Float32Array::view(array.as_slice());
87          context.buffer_data_with_array_buffer_view(
88                web_sys::WebGl2RenderingContext::ARRAY_BUFFER,
89                &vertices_array,
90                web_sys::WebGl2RenderingContext::STATIC_DRAW,
91          );
92      }
93
94      context.vertex_attrib_pointer_with_i32(position_attribute_location as u32,
95          3, // size
96          web_sys::WebGl2RenderingContext::FLOAT,
97          false, // don't normalize
98          0, // stride
99          0, // offset
100      );
101
102      context.use_program(Some(&program));
103      context.uniform4f(
104        color_location.as_ref(),
105        0.2, // R
106        1.0, // G
107        0.2, // B
108        1.0, // Alpha
109      );
110
111      *self.inner.borrow_mut() = Some(
112        Inner {
113          program,
114          vao,
115          matrix_location: matrix_location.unwrap(),
116        }
117      );
118    }
119
120    let binding = self.inner.borrow();
121    let inner = binding.as_ref().unwrap();
122
123    context.use_program(Some(&inner.program));
124    context.bind_vertex_array(Some(&inner.vao));
125    context.uniform_matrix4fv_with_f32_array(
126      Some(&inner.matrix_location),
127      false,
128      camera,
129    );
130    context.draw_arrays(
131          web_sys::WebGl2RenderingContext::TRIANGLES,
132          0, // offset
133          12 * 3, // count
134    );
135
136    Ok(())
137  }
138}