fast_layer/
lib.rs

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}