From 532601bc4387cdcc9fb90322b6e0201803011b33 Mon Sep 17 00:00:00 2001 From: dongho Date: Tue, 3 Sep 2024 23:50:29 +0900 Subject: [PATCH] webgl-demo --> lib.rs migration finished --- src/lib.rs | 167 +++++++++++++++++++++++++--------------------------- src/lib2.rs | 147 +++++++++++++++++++++++++++++++++++++++++++++ src/lib3.rs | 131 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+), 88 deletions(-) create mode 100644 src/lib2.rs create mode 100644 src/lib3.rs diff --git a/src/lib.rs b/src/lib.rs index 2515234..eb814af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,147 +1,138 @@ use wasm_bindgen::prelude::*; -use web_sys::{WebGl2RenderingContext, WebGlProgram, WebGlShader}; +use web_sys::{ + WebGl2RenderingContext, WebGlBuffer, WebGlProgram, WebGlShader, WebGlVertexArrayObject, +}; #[wasm_bindgen(start)] -fn start() -> Result<(), JsValue> { +pub fn start() -> Result<(), JsValue> { let document = web_sys::window().unwrap().document().unwrap(); - let canvas = document.get_element_by_id("canvas").unwrap(); + let canvas = document.get_element_by_id("glcanvas").unwrap(); let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::()?; - let context = canvas + let gl = canvas .get_context("webgl2")? .unwrap() .dyn_into::()?; let vert_shader = compile_shader( - &context, + &gl, WebGl2RenderingContext::VERTEX_SHADER, - r##"#version 300 es - - in vec4 position; - + r#" + attribute vec4 aVertexPosition; void main() { - - gl_Position = position; + gl_Position = aVertexPosition; } - "##, + "#, )?; - let frag_shader = compile_shader( - &context, + &gl, WebGl2RenderingContext::FRAGMENT_SHADER, - r##"#version 300 es - - precision highp float; - out vec4 outColor; - + r#" void main() { - outColor = vec4(1, 1, 1, 1); + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); } - "##, + "#, )?; - let program = link_program(&context, &vert_shader, &frag_shader)?; - context.use_program(Some(&program)); + let program = link_program(&gl, &vert_shader, &frag_shader)?; + gl.use_program(Some(&program)); + let positions: [f32; 8] = [0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5]; + let buffer = bind_2d_float32_data(&gl, &positions)?; - let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0]; - - let position_attribute_location = context.get_attrib_location(&program, "position"); - let buffer = context.create_buffer().ok_or("Failed to create buffer")?; - context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer)); - - // 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 positions_array_buf_view = js_sys::Float32Array::view(&vertices); - - context.buffer_data_with_array_buffer_view( - WebGl2RenderingContext::ARRAY_BUFFER, - &positions_array_buf_view, - WebGl2RenderingContext::STATIC_DRAW, - ); - } - - let vao = context - .create_vertex_array() - .ok_or("Could not create vertex array object")?; - context.bind_vertex_array(Some(&vao)); - - context.vertex_attrib_pointer_with_i32( - position_attribute_location as u32, - 3, - WebGl2RenderingContext::FLOAT, - false, - 0, - 0, - ); - context.enable_vertex_attrib_array(position_attribute_location as u32); - - context.bind_vertex_array(Some(&vao)); - - let vert_count = (vertices.len() / 3) as i32; - draw(&context, vert_count); + draw(&gl, &program, &buffer)?; Ok(()) } -fn draw(context: &WebGl2RenderingContext, vert_count: i32) { - context.clear_color(0.0, 0.0, 0.0, 1.0); - context.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT); - - context.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count); -} - -pub fn compile_shader( - context: &WebGl2RenderingContext, +fn compile_shader( + gl: &WebGl2RenderingContext, shader_type: u32, source: &str, ) -> Result { - let shader = context + let shader = gl .create_shader(shader_type) .ok_or_else(|| String::from("Unable to create shader object"))?; - context.shader_source(&shader, source); - context.compile_shader(&shader); + gl.shader_source(&shader, source); + gl.compile_shader(&shader); - if context + if gl .get_shader_parameter(&shader, WebGl2RenderingContext::COMPILE_STATUS) .as_bool() .unwrap_or(false) { Ok(shader) } else { - Err(context + Err(gl .get_shader_info_log(&shader) .unwrap_or_else(|| String::from("Unknown error creating shader"))) } } -pub fn link_program( - context: &WebGl2RenderingContext, +fn link_program( + gl: &WebGl2RenderingContext, vert_shader: &WebGlShader, frag_shader: &WebGlShader, ) -> Result { - let program = context + let program = gl .create_program() .ok_or_else(|| String::from("Unable to create shader object"))?; - context.attach_shader(&program, vert_shader); - context.attach_shader(&program, frag_shader); - context.link_program(&program); + gl.attach_shader(&program, vert_shader); + gl.attach_shader(&program, frag_shader); + gl.link_program(&program); - if context + if gl .get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS) .as_bool() .unwrap_or(false) { Ok(program) } else { - Err(context + Err(gl .get_program_info_log(&program) .unwrap_or_else(|| String::from("Unknown error creating program object"))) } } + +fn bind_2d_float32_data( + gl: &WebGl2RenderingContext, + positions: &[f32], +) -> Result { + let position_buffer = gl.create_buffer().ok_or("Failed to create buffer")?; + gl.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&position_buffer)); + + unsafe { + let positions_array_buf_view = js_sys::Float32Array::view(positions); + + gl.buffer_data_with_array_buffer_view( + WebGl2RenderingContext::ARRAY_BUFFER, + &positions_array_buf_view, + WebGl2RenderingContext::STATIC_DRAW, + ); + } + + let vao = gl + .create_vertex_array() + .ok_or("Could not create vertex array object")?; + gl.bind_vertex_array(Some(&vao)); + + Ok(vao) +} + +fn draw( + gl: &WebGl2RenderingContext, + program: &WebGlProgram, + buffer: &WebGlVertexArrayObject, +) -> Result<(), JsValue> { + gl.clear_color(0.0, 0.0, 0.0, 1.0); + gl.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT); + + gl.use_program(Some(&program)); + gl.bind_vertex_array(Some(buffer)); + + gl.vertex_attrib_pointer_with_i32(0, 2, WebGl2RenderingContext::FLOAT, false, 0, 0); + gl.enable_vertex_attrib_array(0); + + gl.draw_arrays(WebGl2RenderingContext::TRIANGLE_STRIP, 0, 4); + + Ok(()) +} diff --git a/src/lib2.rs b/src/lib2.rs new file mode 100644 index 0000000..2515234 --- /dev/null +++ b/src/lib2.rs @@ -0,0 +1,147 @@ +use wasm_bindgen::prelude::*; +use web_sys::{WebGl2RenderingContext, WebGlProgram, WebGlShader}; + +#[wasm_bindgen(start)] +fn start() -> Result<(), JsValue> { + let document = web_sys::window().unwrap().document().unwrap(); + let canvas = document.get_element_by_id("canvas").unwrap(); + let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::()?; + + let context = canvas + .get_context("webgl2")? + .unwrap() + .dyn_into::()?; + + let vert_shader = compile_shader( + &context, + WebGl2RenderingContext::VERTEX_SHADER, + r##"#version 300 es + + in vec4 position; + + void main() { + + gl_Position = position; + } + "##, + )?; + + let frag_shader = compile_shader( + &context, + WebGl2RenderingContext::FRAGMENT_SHADER, + r##"#version 300 es + + precision highp float; + out vec4 outColor; + + void main() { + outColor = vec4(1, 1, 1, 1); + } + "##, + )?; + let program = link_program(&context, &vert_shader, &frag_shader)?; + context.use_program(Some(&program)); + + let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0]; + + let position_attribute_location = context.get_attrib_location(&program, "position"); + let buffer = context.create_buffer().ok_or("Failed to create buffer")?; + context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer)); + + // 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 positions_array_buf_view = js_sys::Float32Array::view(&vertices); + + context.buffer_data_with_array_buffer_view( + WebGl2RenderingContext::ARRAY_BUFFER, + &positions_array_buf_view, + WebGl2RenderingContext::STATIC_DRAW, + ); + } + + let vao = context + .create_vertex_array() + .ok_or("Could not create vertex array object")?; + context.bind_vertex_array(Some(&vao)); + + context.vertex_attrib_pointer_with_i32( + position_attribute_location as u32, + 3, + WebGl2RenderingContext::FLOAT, + false, + 0, + 0, + ); + context.enable_vertex_attrib_array(position_attribute_location as u32); + + context.bind_vertex_array(Some(&vao)); + + let vert_count = (vertices.len() / 3) as i32; + draw(&context, vert_count); + + Ok(()) +} + +fn draw(context: &WebGl2RenderingContext, vert_count: i32) { + context.clear_color(0.0, 0.0, 0.0, 1.0); + context.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT); + + context.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count); +} + +pub fn compile_shader( + context: &WebGl2RenderingContext, + shader_type: u32, + source: &str, +) -> Result { + 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, WebGl2RenderingContext::COMPILE_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(shader) + } else { + Err(context + .get_shader_info_log(&shader) + .unwrap_or_else(|| String::from("Unknown error creating shader"))) + } +} + +pub fn link_program( + context: &WebGl2RenderingContext, + vert_shader: &WebGlShader, + frag_shader: &WebGlShader, +) -> Result { + let program = context + .create_program() + .ok_or_else(|| String::from("Unable to create shader object"))?; + + context.attach_shader(&program, vert_shader); + context.attach_shader(&program, frag_shader); + context.link_program(&program); + + if context + .get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(program) + } else { + Err(context + .get_program_info_log(&program) + .unwrap_or_else(|| String::from("Unknown error creating program object"))) + } +} diff --git a/src/lib3.rs b/src/lib3.rs new file mode 100644 index 0000000..4af4ffb --- /dev/null +++ b/src/lib3.rs @@ -0,0 +1,131 @@ +use wasm_bindgen::prelude::*; +use web_sys::{WebGl2RenderingContext, WebGlProgram, WebGlShader}; + +#[wasm_bindgen(start)] +fn start() -> Result<(), JsValue> { + let document = web_sys::window().unwrap().document().unwrap(); + let canvas = document.get_element_by_id("canvas").unwrap(); + let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::()?; + + let context = canvas + .get_context("webgl2")? + .unwrap() + .dyn_into::()?; + + let vert_shader = compile_shader( + &context, + WebGl2RenderingContext::VERTEX_SHADER, + r##" + attribute vec4 aVertexPosition; + void main() { + gl_Position = aVertexPosition; + } + "##, + )?; + + let frag_shader = compile_shader( + &context, + WebGl2RenderingContext::FRAGMENT_SHADER, + r##" + void main() { + gl_FragColor = vec4(0, 1.0, 0, 1.0); + } + "##, + )?; + let program = link_program(&context, &vert_shader, &frag_shader)?; + context.use_program(Some(&program)); + + let vertices: [f32; 8] = [0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5]; + + let position_attribute_location = context.get_attrib_location(&program, "position"); + let buffer = context.create_buffer().ok_or("Failed to create buffer")?; + context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer)); + + unsafe { + let positions_array_buf_view = js_sys::Float32Array::view(&vertices); + + context.buffer_data_with_array_buffer_view( + WebGl2RenderingContext::ARRAY_BUFFER, + &positions_array_buf_view, + WebGl2RenderingContext::STATIC_DRAW, + ); + } + + let vao = context + .create_vertex_array() + .ok_or("Could not create vertex array object")?; + context.bind_vertex_array(Some(&vao)); + + context.vertex_attrib_pointer_with_i32( + 0, //position_attribute_location as u32, + 2, + WebGl2RenderingContext::FLOAT, + false, + 0, + 0, + ); + context.enable_vertex_attrib_array(0); //position_attribute_location as u32); + + context.bind_vertex_array(Some(&vao)); + + let vert_count = (vertices.len() / 3) as i32; + draw(&context, vert_count); + + Ok(()) +} + +fn draw(context: &WebGl2RenderingContext, vert_count: i32) { + context.clear_color(0.0, 0.0, 0.0, 1.0); + context.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT); + + context.draw_arrays(WebGl2RenderingContext::TRIANGLE_STRIP, 0, 3); //vert_count +} + +pub fn compile_shader( + context: &WebGl2RenderingContext, + shader_type: u32, + source: &str, +) -> Result { + 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, WebGl2RenderingContext::COMPILE_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(shader) + } else { + Err(context + .get_shader_info_log(&shader) + .unwrap_or_else(|| String::from("Unknown error creating shader"))) + } +} +pub fn link_program( + context: &WebGl2RenderingContext, + vert_shader: &WebGlShader, + frag_shader: &WebGlShader, +) -> Result { + let program = context + .create_program() + .ok_or_else(|| String::from("Unable to create shader object"))?; + + context.attach_shader(&program, vert_shader); + context.attach_shader(&program, frag_shader); + context.link_program(&program); + + if context + .get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(program) + } else { + Err(context + .get_program_info_log(&program) + .unwrap_or_else(|| String::from("Unknown error creating program object"))) + } +}