2018-11-27 12:07:59 -08:00
|
|
|
use js_sys::WebAssembly;
|
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
|
|
|
|
2018-11-28 09:25:51 -08:00
|
|
|
#[wasm_bindgen(start)]
|
|
|
|
pub fn start() -> Result<(), JsValue> {
|
2018-09-19 13:18:48 -07:00
|
|
|
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
|
2018-11-08 10:58:55 -08:00
|
|
|
.get_context("webgl")?
|
2018-09-15 23:28:15 -07:00
|
|
|
.unwrap()
|
2018-11-08 10:58:55 -08:00
|
|
|
.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-11-08 10:58:55 -08:00
|
|
|
)?;
|
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);
|
|
|
|
}
|
|
|
|
"#,
|
2018-11-08 10:58:55 -08:00
|
|
|
)?;
|
|
|
|
let program = link_program(&context, [vert_shader, frag_shader].iter())?;
|
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-11-27 12:07:59 -08:00
|
|
|
let memory_buffer = wasm_bindgen::memory()
|
|
|
|
.dyn_into::<WebAssembly::Memory>()?
|
|
|
|
.buffer();
|
2018-10-14 17:00:56 -04:00
|
|
|
let vertices_location = vertices.as_ptr() as u32 / 4;
|
2018-11-27 12:07:59 -08:00
|
|
|
let vert_array = js_sys::Float32Array::new(&memory_buffer)
|
|
|
|
.subarray(vertices_location, vertices_location + vertices.len() as u32);
|
2018-09-15 23:28:15 -07:00
|
|
|
|
2018-11-08 10:58:55 -08: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));
|
2018-10-14 12:38:54 -04:00
|
|
|
context.buffer_data_with_array_buffer_view(
|
2018-09-15 23:28:15 -07:00
|
|
|
WebGlRenderingContext::ARRAY_BUFFER,
|
2018-11-08 10:58:55 -08:00
|
|
|
&vert_array,
|
2018-09-15 23:28:15 -07:00
|
|
|
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,
|
|
|
|
);
|
2018-11-08 10:58:55 -08:00
|
|
|
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)
|
|
|
|
.unwrap_or_else(|| "Unknown error creating shader".into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
|
|
|
|
context: &WebGlRenderingContext,
|
|
|
|
shaders: T,
|
|
|
|
) -> Result<WebGlProgram, String> {
|
|
|
|
let program = context
|
|
|
|
.create_program()
|
|
|
|
.ok_or_else(|| String::from("Unable to create shader object"))?;
|
|
|
|
for shader in shaders {
|
|
|
|
context.attach_shader(&program, shader)
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
.unwrap_or_else(|| "Unknown error creating program object".into()))
|
|
|
|
}
|
|
|
|
}
|