use wasm_bindgen::prelude::*;
use web_sys::{
console, window, Element, HtmlCanvasElement, WebGl2RenderingContext, WebGlProgram, WebGlShader,
WebGlUniformLocation,
};
#[wasm_bindgen]
pub struct FastLayer {
canvas_id: String,
context: WebGl2RenderingContext,
program: Option<WebGlProgram>,
}
#[wasm_bindgen]
impl FastLayer {
pub fn new(canvas_id: &str) -> FastLayer {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id(canvas_id).unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap();
let context = canvas
.get_context("webgl2")
.unwrap()
.unwrap()
.dyn_into()
.unwrap();
FastLayer {
canvas_id: canvas_id.to_string(),
context,
program: None,
}
}
pub fn compile(&mut self) {
let vertex_source = r#"#version 300 es
uniform mat4 u_matrix;
void main() {
gl_Position = vec4(0.5, 0.5, 0.0, 1.0);
gl_PointSize = 20.0;
}"#;
let fragment_source = r#"#version 300 es
out highp vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}"#;
let vertex_shader = self
.context
.create_shader(WebGl2RenderingContext::VERTEX_SHADER)
.unwrap();
self.context.shader_source(&vertex_shader, vertex_source);
self.context.compile_shader(&vertex_shader);
if !self
.context
.get_shader_parameter(&vertex_shader, WebGl2RenderingContext::COMPILE_STATUS)
.as_bool()
.unwrap_or(false)
{
let info = self
.context
.get_shader_info_log(&vertex_shader)
.unwrap_or_else(|| "Unknown error".to_string());
panic!("Could not compile vertex shader. \n\n{}", info);
}
let fragment_shader = self
.context
.create_shader(WebGl2RenderingContext::FRAGMENT_SHADER)
.unwrap();
self.context
.shader_source(&fragment_shader, fragment_source);
self.context.compile_shader(&fragment_shader);
if !self
.context
.get_shader_parameter(&fragment_shader, WebGl2RenderingContext::COMPILE_STATUS)
.as_bool()
.unwrap_or(false)
{
let info = self
.context
.get_shader_info_log(&fragment_shader)
.unwrap_or_else(|| "Unknown error".to_string());
panic!("Could not compile fragment shader. \n\n{}", info);
}
let program = self.context.create_program().unwrap();
self.context.attach_shader(&program, &vertex_shader);
self.context.attach_shader(&program, &fragment_shader);
self.context.link_program(&program);
if !self
.context
.get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS)
.as_bool()
.unwrap_or(false)
{
let info = self
.context
.get_program_info_log(&program)
.unwrap_or_else(|| "Unknown error".to_string());
panic!("Could not link WebGL program. \n\n{}", info);
}
self.program = Some(program);
}
pub fn draw(&self, matrix: &[f64]) {
console::log_1(&format!("{:?}", self.program).into());
self.context
.use_program(Some(self.program.as_ref().unwrap()));
let location = self
.context
.get_uniform_location(self.program.as_ref().unwrap(), "u_matrix");
if let Some(loc) = location {
if matrix.len() >= 4 {
self.context.uniform4f(
Some(&loc),
matrix[0] as f32,
matrix[1] as f32,
matrix[2] as f32,
matrix[3] as f32,
);
}
}
self.context
.draw_arrays(web_sys::WebGl2RenderingContext::POINTS, 0, 1);
}
}