124 lines
3.8 KiB
Rust
Raw Normal View History

2018-09-15 23:28:15 -07:00
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{WebGlProgram, WebGlRenderingContext, WebGlShader};
2018-10-14 12:38:54 -04:00
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
2018-09-15 23:28:15 -07:00
let canvas = document.get_element_by_id("canvas").unwrap();
2018-11-27 12:07:59 -08:00
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::<web_sys::HtmlCanvasElement>()?;
2018-09-15 23:28:15 -07:00
let context = canvas
.get_context("webgl")?
2018-09-15 23:28:15 -07:00
.unwrap()
.dyn_into::<WebGlRenderingContext>()?;
2018-09-15 23:28:15 -07:00
let vert_shader = compile_shader(
&context,
WebGlRenderingContext::VERTEX_SHADER,
r#"
attribute vec4 position;
void main() {
gl_Position = position;
}
"#,
)?;
2018-09-15 23:28:15 -07:00
let frag_shader = compile_shader(
&context,
WebGlRenderingContext::FRAGMENT_SHADER,
r#"
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
"#,
)?;
2019-03-10 17:40:02 +03:00
let program = link_program(&context, &vert_shader, &frag_shader)?;
2018-09-15 23:28:15 -07:00
context.use_program(Some(&program));
2018-10-14 12:38:54 -04:00
let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0];
2018-09-15 23:28:15 -07:00
let buffer = context.create_buffer().ok_or("failed to create buffer")?;
2018-09-15 23:28:15 -07:00
context.bind_buffer(WebGlRenderingContext::ARRAY_BUFFER, Some(&buffer));
2019-06-24 18:21:12 +02:00
// Note that `Float32Array::view` is somewhat dangerous (hence the
// `unsafe`!). This is creating a raw view into our module's
// `WebAssembly.Memory` buffer, but if we allocate more pages for ourself
// (aka do a memory allocation in Rust) it'll cause the buffer to change,
// causing the `Float32Array` to be invalid.
//
// As a result, after `Float32Array::view` we have to be very careful not to
// do any memory allocations before it's dropped.
unsafe {
let vert_array = js_sys::Float32Array::view(&vertices);
context.buffer_data_with_array_buffer_view(
WebGlRenderingContext::ARRAY_BUFFER,
&vert_array,
WebGlRenderingContext::STATIC_DRAW,
);
}
2018-09-19 13:19:41 -07:00
context.vertex_attrib_pointer_with_i32(0, 3, WebGlRenderingContext::FLOAT, false, 0, 0);
2018-09-15 23:28:15 -07:00
context.enable_vertex_attrib_array(0);
context.clear_color(0.0, 0.0, 0.0, 1.0);
context.clear(WebGlRenderingContext::COLOR_BUFFER_BIT);
2018-09-19 13:19:41 -07:00
context.draw_arrays(
WebGlRenderingContext::TRIANGLES,
0,
(vertices.len() / 3) as i32,
);
Ok(())
2018-09-15 23:28:15 -07:00
}
pub fn compile_shader(
context: &WebGlRenderingContext,
shader_type: u32,
source: &str,
) -> Result<WebGlShader, String> {
let shader = context
.create_shader(shader_type)
.ok_or_else(|| String::from("Unable to create shader object"))?;
context.shader_source(&shader, source);
context.compile_shader(&shader);
if context
.get_shader_parameter(&shader, WebGlRenderingContext::COMPILE_STATUS)
.as_bool()
.unwrap_or(false)
{
Ok(shader)
} else {
Err(context
.get_shader_info_log(&shader)
2019-03-10 17:40:02 +03:00
.unwrap_or_else(|| String::from("Unknown error creating shader")))
2018-09-15 23:28:15 -07:00
}
}
2019-03-10 17:40:02 +03:00
pub fn link_program(
2018-09-15 23:28:15 -07:00
context: &WebGlRenderingContext,
2019-03-10 17:40:02 +03:00
vert_shader: &WebGlShader,
frag_shader: &WebGlShader,
2018-09-15 23:28:15 -07:00
) -> Result<WebGlProgram, String> {
let program = context
.create_program()
.ok_or_else(|| String::from("Unable to create shader object"))?;
2019-03-10 17:40:02 +03:00
context.attach_shader(&program, vert_shader);
context.attach_shader(&program, frag_shader);
2018-09-15 23:28:15 -07:00
context.link_program(&program);
if context
.get_program_parameter(&program, WebGlRenderingContext::LINK_STATUS)
.as_bool()
.unwrap_or(false)
{
Ok(program)
} else {
Err(context
.get_program_info_log(&program)
2019-03-10 17:40:02 +03:00
.unwrap_or_else(|| String::from("Unknown error creating program object")))
2018-09-15 23:28:15 -07:00
}
}