1use wasm_bindgen::prelude::*;
2use web_sys::{
3 console, window, Element, HtmlCanvasElement, WebGl2RenderingContext, WebGlProgram, WebGlShader,
4 WebGlUniformLocation,
5};
6
7#[wasm_bindgen]
8pub struct FastLayer {
9 canvas_id: String,
10 context: WebGl2RenderingContext,
11 program: Option<WebGlProgram>,
12}
13
14#[wasm_bindgen]
15impl FastLayer {
16 pub fn new(canvas_id: &str) -> FastLayer {
17 let document = web_sys::window().unwrap().document().unwrap();
18 let canvas = document.get_element_by_id(canvas_id).unwrap();
19 let canvas: web_sys::HtmlCanvasElement = canvas
20 .dyn_into::<web_sys::HtmlCanvasElement>()
21 .map_err(|_| ())
22 .unwrap();
23 let context = canvas
24 .get_context("webgl2")
25 .unwrap()
26 .unwrap()
27 .dyn_into()
28 .unwrap();
29
30 FastLayer {
31 canvas_id: canvas_id.to_string(),
32 context,
33 program: None,
34 }
35 }
36
37 pub fn compile(&mut self) {
38 let vertex_source = r#"#version 300 es
39 uniform mat4 u_matrix;
40 void main() {
41 gl_Position = vec4(0.5, 0.5, 0.0, 1.0);
42 gl_PointSize = 20.0;
43 }"#;
44
45 let fragment_source = r#"#version 300 es
46
47 out highp vec4 fragColor;
48 void main() {
49 fragColor = vec4(1.0, 0.0, 0.0, 1.0);
50 }"#;
51
52 let vertex_shader = self
53 .context
54 .create_shader(WebGl2RenderingContext::VERTEX_SHADER)
55 .unwrap();
56 self.context.shader_source(&vertex_shader, vertex_source);
57 self.context.compile_shader(&vertex_shader);
58
59 if !self
60 .context
61 .get_shader_parameter(&vertex_shader, WebGl2RenderingContext::COMPILE_STATUS)
62 .as_bool()
63 .unwrap_or(false)
64 {
65 let info = self
66 .context
67 .get_shader_info_log(&vertex_shader)
68 .unwrap_or_else(|| "Unknown error".to_string());
69 panic!("Could not compile vertex shader. \n\n{}", info);
70 }
71
72 let fragment_shader = self
73 .context
74 .create_shader(WebGl2RenderingContext::FRAGMENT_SHADER)
75 .unwrap();
76 self.context
77 .shader_source(&fragment_shader, fragment_source);
78 self.context.compile_shader(&fragment_shader);
79
80 if !self
81 .context
82 .get_shader_parameter(&fragment_shader, WebGl2RenderingContext::COMPILE_STATUS)
83 .as_bool()
84 .unwrap_or(false)
85 {
86 let info = self
87 .context
88 .get_shader_info_log(&fragment_shader)
89 .unwrap_or_else(|| "Unknown error".to_string());
90 panic!("Could not compile fragment shader. \n\n{}", info);
91 }
92
93 let program = self.context.create_program().unwrap();
94 self.context.attach_shader(&program, &vertex_shader);
95 self.context.attach_shader(&program, &fragment_shader);
96 self.context.link_program(&program);
97
98 if !self
99 .context
100 .get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS)
101 .as_bool()
102 .unwrap_or(false)
103 {
104 let info = self
105 .context
106 .get_program_info_log(&program)
107 .unwrap_or_else(|| "Unknown error".to_string());
108 panic!("Could not link WebGL program. \n\n{}", info);
109 }
110
111 self.program = Some(program);
112 }
113
114 pub fn draw(&self, matrix: &[f64]) {
115 console::log_1(&format!("{:?}", self.program).into());
116 self.context
117 .use_program(Some(self.program.as_ref().unwrap()));
118 let location = self
119 .context
120 .get_uniform_location(self.program.as_ref().unwrap(), "u_matrix");
121
122 if let Some(loc) = location {
123 if matrix.len() >= 4 {
124 self.context.uniform4f(
125 Some(&loc),
126 matrix[0] as f32,
127 matrix[1] as f32,
128 matrix[2] as f32,
129 matrix[3] as f32,
130 );
131 }
132 }
133
134 self.context
135 .draw_arrays(web_sys::WebGl2RenderingContext::POINTS, 0, 1);
136 }
137}